@joebigelow / wix-1 / commits / 9f8cb537

Additional IR updates

Rob Mensching committed Nov 11, 2017 at 01:45 UTC 9f8cb5374481b6c8a06eb2739858332350f72666
45 files changed +2001 -2442
src/WixToolset.Core.WindowsInstaller/Bind/AssignMediaCommand.cs
+92 -95
@@ -1,43 +1,44 @@
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.WindowsInstaller.Databases
3 +namespace WixToolset.Core.WindowsInstaller.Bind
4 {
5 using System;
6 using System.Collections.Generic;
7 using System.Globalization;
8 + using System.Linq;
9 using WixToolset.Core.Bind;
10 using WixToolset.Data;
11 using WixToolset.Data.Rows;
12 + using WixToolset.Data.Tuples;
13
14 /// <summary>
15 /// AssignMediaCommand assigns files to cabs based on Media or MediaTemplate rows.
16 /// </summary>
15 - public class AssignMediaCommand
17 + internal class AssignMediaCommand
18 {
17 - public AssignMediaCommand()
19 + public AssignMediaCommand(IntermediateSection section)
20 {
21 this.CabinetNameTemplate = "Cab{0}.cab";
22 + this.Section = section;
23 }
24
22 - public Output Output { private get; set; }
25 + private IntermediateSection Section { get; }
26 +
27 + public IEnumerable<FileFacade> FileFacades { private get; set; }
28
29 public bool FilesCompressed { private get; set; }
30
31 public string CabinetNameTemplate { private get; set; }
32
28 - public IEnumerable<FileFacade> FileFacades { private get; set; }
29 -
30 - public TableDefinitionCollection TableDefinitions { private get; set; }
31 -
33 /// <summary>
34 /// Gets cabinets with their file rows.
35 /// </summary>
35 - public Dictionary<MediaRow, IEnumerable<FileFacade>> FileFacadesByCabinetMedia { get; private set; }
36 + public Dictionary<MediaTuple, IEnumerable<FileFacade>> FileFacadesByCabinetMedia { get; private set; }
37
38 /// <summary>
39 /// Get media rows.
40 /// </summary>
40 - public RowDictionary<MediaRow> MediaRows { get; private set; }
41 + public Dictionary<int, MediaTuple> MediaRows { get; private set; }
42
43 /// <summary>
44 /// Get uncompressed file rows. This will contain file rows of File elements that are marked with compression=no.
@@ -47,42 +48,41 @@ namespace WixToolset.Core.WindowsInstaller.Databases
48
49 public void Execute()
50 {
50 - Dictionary<MediaRow, List<FileFacade>> filesByCabinetMedia = new Dictionary<MediaRow, List<FileFacade>>();
51 + var filesByCabinetMedia = new Dictionary<MediaTuple, List<FileFacade>>();
52
52 - RowDictionary<MediaRow> mediaRows = new RowDictionary<MediaRow>();
53 + var mediaRows = new Dictionary<int, MediaTuple>();
54
55 List<FileFacade> uncompressedFiles = new List<FileFacade>();
56
56 - MediaRow mergeModuleMediaRow = null;
57 - Table mediaTable = this.Output.Tables["Media"];
58 - Table mediaTemplateTable = this.Output.Tables["WixMediaTemplate"];
57 + var mediaTable = this.Section.Tuples.OfType<MediaTuple>().ToList();
58 + var mediaTemplateTable = this.Section.Tuples.OfType<WixMediaTemplateTuple>().ToList();
59
60 // If both tables are authored, it is an error.
61 - if ((mediaTemplateTable != null && mediaTemplateTable.Rows.Count > 0) && (mediaTable != null && mediaTable.Rows.Count > 1))
61 + if ((mediaTemplateTable != null && mediaTemplateTable.Count > 0) && (mediaTable != null && mediaTable.Count > 1))
62 {
63 throw new WixException(WixErrors.MediaTableCollision(null));
64 }
65
66 // When building merge module, all the files go to "#MergeModule.CABinet".
67 - if (OutputType.Module == this.Output.Type)
67 + if (SectionType.Module == this.Section.Type)
68 {
69 - Table mergeModuleMediaTable = new Table(this.TableDefinitions["Media"]);
70 - mergeModuleMediaRow = (MediaRow)mergeModuleMediaTable.CreateRow(null);
69 + var mergeModuleMediaRow = new MediaTuple();
70 mergeModuleMediaRow.Cabinet = "#MergeModule.CABinet";
71
73 - filesByCabinetMedia.Add(mergeModuleMediaRow, new List<FileFacade>());
74 - }
72 + this.Section.Tuples.Add(mergeModuleMediaRow);
73
76 - if (OutputType.Module == this.Output.Type || null == mediaTemplateTable)
74 + filesByCabinetMedia.Add(mergeModuleMediaRow, new List<FileFacade>(this.FileFacades));
75 + }
76 + else if (null == mediaTemplateTable)
77 {
78 - this.ManuallyAssignFiles(mediaTable, mergeModuleMediaRow, this.FileFacades, filesByCabinetMedia, mediaRows, uncompressedFiles);
78 + this.ManuallyAssignFiles(mediaTable, this.FileFacades, filesByCabinetMedia, mediaRows, uncompressedFiles);
79 }
80 else
81 {
82 this.AutoAssignFiles(mediaTable, this.FileFacades, filesByCabinetMedia, mediaRows, uncompressedFiles);
83 }
84
85 - this.FileFacadesByCabinetMedia = new Dictionary<MediaRow, IEnumerable<FileFacade>>();
85 + this.FileFacadesByCabinetMedia = new Dictionary<MediaTuple, IEnumerable<FileFacade>>();
86
87 foreach (var mediaRowWithFiles in filesByCabinetMedia)
88 {
@@ -98,7 +98,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases
98 /// Assign files to cabinets based on MediaTemplate authoring.
99 /// </summary>
100 /// <param name="fileFacades">FileRowCollection</param>
101 - private void AutoAssignFiles(Table mediaTable, IEnumerable<FileFacade> fileFacades, Dictionary<MediaRow, List<FileFacade>> filesByCabinetMedia, RowDictionary<MediaRow> mediaRows, List<FileFacade> uncompressedFiles)
101 + private void AutoAssignFiles(List<MediaTuple> mediaTable, IEnumerable<FileFacade> fileFacades, Dictionary<MediaTuple, List<FileFacade>> filesByCabinetMedia, Dictionary<int, MediaTuple> mediaRows, List<FileFacade> uncompressedFiles)
102 {
103 const int MaxCabIndex = 999;
104
@@ -107,13 +107,19 @@ namespace WixToolset.Core.WindowsInstaller.Databases
107 int maxPreCabSizeInMB = 0;
108 int currentCabIndex = 0;
109
110 - MediaRow currentMediaRow = null;
110 + MediaTuple currentMediaRow = null;
111
112 - Table mediaTemplateTable = this.Output.Tables["WixMediaTemplate"];
112 + var mediaTemplateTable = this.Section.Tuples.OfType<WixMediaTemplateTuple>();
113 +
114 + // Remove all previous media tuples since they will be replaced with
115 + // media template.
116 + foreach (var mediaTuple in mediaTable)
117 + {
118 + this.Section.Tuples.Remove(mediaTuple);
119 + }
120
121 // Auto assign files to cabinets based on maximum uncompressed media size
115 - mediaTable.Rows.Clear();
116 - WixMediaTemplateRow mediaTemplateRow = (WixMediaTemplateRow)mediaTemplateTable.Rows[0];
122 + var mediaTemplateRow = mediaTemplateTable.Single();
123
124 if (!String.IsNullOrEmpty(mediaTemplateRow.CabinetTemplate))
125 {
@@ -149,9 +155,9 @@ namespace WixToolset.Core.WindowsInstaller.Databases
155 {
156 // When building a product, if the current file is not to be compressed or if
157 // the package set not to be compressed, don't cab it.
152 - if (OutputType.Product == this.Output.Type &&
153 - (!facade.File.Compressed.Value ||
154 - (!facade.File.Compressed.HasValue && !this.FilesCompressed)))
158 + if (SectionType.Product == this.Section.Type &&
159 + ((facade.File.Compressed.HasValue && !facade.File.Compressed.Value) ||
160 + (!facade.File.Compressed.HasValue && !this.FilesCompressed)))
161 {
162 uncompressedFiles.Add(facade);
163 continue;
@@ -172,8 +178,8 @@ namespace WixToolset.Core.WindowsInstaller.Databases
178 if (currentPreCabSize > maxPreCabSizeInBytes)
179 {
180 // Overflow due to current file
175 - currentMediaRow = this.AddMediaRow(mediaTemplateRow, mediaTable, ++currentCabIndex);
176 - mediaRows.Add(currentMediaRow);
181 + currentMediaRow = this.AddMediaRow(mediaTemplateRow, ++currentCabIndex);
182 + mediaRows.Add(currentMediaRow.DiskId, currentMediaRow);
183 filesByCabinetMedia.Add(currentMediaRow, new List<FileFacade>());
184
185 List<FileFacade> cabinetFileRows = filesByCabinetMedia[currentMediaRow];
@@ -188,8 +194,8 @@ namespace WixToolset.Core.WindowsInstaller.Databases
194 if (currentMediaRow == null)
195 {
196 // Create new cab and MediaRow
191 - currentMediaRow = this.AddMediaRow(mediaTemplateRow, mediaTable, ++currentCabIndex);
192 - mediaRows.Add(currentMediaRow);
197 + currentMediaRow = this.AddMediaRow(mediaTemplateRow, ++currentCabIndex);
198 + mediaRows.Add(currentMediaRow.DiskId, currentMediaRow);
199 filesByCabinetMedia.Add(currentMediaRow, new List<FileFacade>());
200 }
201
@@ -201,11 +207,13 @@ namespace WixToolset.Core.WindowsInstaller.Databases
207 }
208
209 // If there are uncompressed files and no MediaRow, create a default one.
204 - if (uncompressedFiles.Count > 0 && mediaTable.Rows.Count == 0)
210 + if (uncompressedFiles.Count > 0 && !this.Section.Tuples.OfType<MediaTuple>().Any())
211 {
206 - MediaRow defaultMediaRow = (MediaRow)mediaTable.CreateRow(null);
212 + var defaultMediaRow = new MediaTuple(null, new Identifier(1, AccessModifier.Private));
213 defaultMediaRow.DiskId = 1;
208 - mediaRows.Add(defaultMediaRow);
214 +
215 + mediaRows.Add(1, defaultMediaRow);
216 + this.Section.Tuples.Add(defaultMediaRow);
217 }
218 }
219
@@ -213,79 +221,65 @@ namespace WixToolset.Core.WindowsInstaller.Databases
221 /// Assign files to cabinets based on Media authoring.
222 /// </summary>
223 /// <param name="mediaTable"></param>
216 - /// <param name="mergeModuleMediaRow"></param>
224 /// <param name="fileFacades"></param>
218 - private void ManuallyAssignFiles(Table mediaTable, MediaRow mergeModuleMediaRow, IEnumerable<FileFacade> fileFacades, Dictionary<MediaRow, List<FileFacade>> filesByCabinetMedia, RowDictionary<MediaRow> mediaRows, List<FileFacade> uncompressedFiles)
225 + private void ManuallyAssignFiles(List<MediaTuple> mediaTable, IEnumerable<FileFacade> fileFacades, Dictionary<MediaTuple, List<FileFacade>> filesByCabinetMedia, Dictionary<int, MediaTuple> mediaRows, List<FileFacade> uncompressedFiles)
226 {
220 - if (OutputType.Module != this.Output.Type)
227 + if (mediaTable.Any())
228 {
222 - if (null != mediaTable)
229 + var cabinetMediaRows = new Dictionary<string, MediaTuple>(StringComparer.OrdinalIgnoreCase);
230 + foreach (var mediaRow in mediaTable)
231 {
224 - Dictionary<string, MediaRow> cabinetMediaRows = new Dictionary<string, MediaRow>(StringComparer.InvariantCultureIgnoreCase);
225 - foreach (MediaRow mediaRow in mediaTable.Rows)
232 + // If the Media row has a cabinet, make sure it is unique across all Media rows.
233 + if (!String.IsNullOrEmpty(mediaRow.Cabinet))
234 {
227 - // If the Media row has a cabinet, make sure it is unique across all Media rows.
228 - if (!String.IsNullOrEmpty(mediaRow.Cabinet))
235 + if (cabinetMediaRows.TryGetValue(mediaRow.Cabinet, out var existingRow))
236 {
230 - MediaRow existingRow;
231 - if (cabinetMediaRows.TryGetValue(mediaRow.Cabinet, out existingRow))
232 - {
233 - Messaging.Instance.OnMessage(WixErrors.DuplicateCabinetName(mediaRow.SourceLineNumbers, mediaRow.Cabinet));
234 - Messaging.Instance.OnMessage(WixErrors.DuplicateCabinetName2(existingRow.SourceLineNumbers, existingRow.Cabinet));
235 - }
236 - else
237 - {
238 - cabinetMediaRows.Add(mediaRow.Cabinet, mediaRow);
239 - }
237 + Messaging.Instance.OnMessage(WixErrors.DuplicateCabinetName(mediaRow.SourceLineNumbers, mediaRow.Cabinet));
238 + Messaging.Instance.OnMessage(WixErrors.DuplicateCabinetName2(existingRow.SourceLineNumbers, existingRow.Cabinet));
239 + }
240 + else
241 + {
242 + cabinetMediaRows.Add(mediaRow.Cabinet, mediaRow);
243 }
241 -
242 - mediaRows.Add(mediaRow);
244 }
245 +
246 + mediaRows.Add(mediaRow.DiskId, mediaRow);
247 }
248 + }
249
246 - foreach (MediaRow mediaRow in mediaRows.Values)
250 + foreach (var mediaRow in mediaRows.Values)
251 + {
252 + if (null != mediaRow.Cabinet)
253 {
248 - if (null != mediaRow.Cabinet)
249 - {
250 - filesByCabinetMedia.Add(mediaRow, new List<FileFacade>());
251 - }
254 + filesByCabinetMedia.Add(mediaRow, new List<FileFacade>());
255 }
256 }
257
258 foreach (FileFacade facade in fileFacades)
259 {
257 - if (OutputType.Module == this.Output.Type)
260 + if (!mediaRows.TryGetValue(facade.WixFile.DiskId, out var mediaRow))
261 {
259 - filesByCabinetMedia[mergeModuleMediaRow].Add(facade);
262 + Messaging.Instance.OnMessage(WixErrors.MissingMedia(facade.File.SourceLineNumbers, facade.WixFile.DiskId));
263 + continue;
264 }
261 - else
262 - {
263 - MediaRow mediaRow;
264 - if (!mediaRows.TryGetValue(facade.WixFile.DiskId.ToString(CultureInfo.InvariantCulture), out mediaRow))
265 - {
266 - Messaging.Instance.OnMessage(WixErrors.MissingMedia(facade.File.SourceLineNumbers, facade.WixFile.DiskId));
267 - continue;
268 - }
265
270 - // When building a product, if the current file is not to be compressed or if
271 - // the package set not to be compressed, don't cab it.
272 - if (OutputType.Product == this.Output.Type &&
273 - (!facade.File.Compressed.Value ||
274 - (!facade.File.Compressed.HasValue && !this.FilesCompressed)))
266 + // When building a product, if the current file is not to be compressed or if
267 + // the package set not to be compressed, don't cab it.
268 + if (SectionType.Product == this.Section.Type &&
269 + (!facade.File.Compressed.Value ||
270 + (!facade.File.Compressed.HasValue && !this.FilesCompressed)))
271 + {
272 + uncompressedFiles.Add(facade);
273 + }
274 + else // file is marked compressed.
275 + {
276 + if (filesByCabinetMedia.TryGetValue(mediaRow, out var cabinetFiles))
277 {
276 - uncompressedFiles.Add(facade);
278 + cabinetFiles.Add(facade);
279 }
278 - else // file is marked compressed.
280 + else
281 {
280 - List<FileFacade> cabinetFiles;
281 - if (filesByCabinetMedia.TryGetValue(mediaRow, out cabinetFiles))
282 - {
283 - cabinetFiles.Add(facade);
284 - }
285 - else
286 - {
287 - Messaging.Instance.OnMessage(WixErrors.ExpectedMediaCabinet(facade.File.SourceLineNumbers, facade.File.File, facade.WixFile.DiskId));
288 - }
282 + Messaging.Instance.OnMessage(WixErrors.ExpectedMediaCabinet(facade.File.SourceLineNumbers, facade.File.File, facade.WixFile.DiskId));
283 }
284 }
285 }
@@ -297,17 +291,20 @@ namespace WixToolset.Core.WindowsInstaller.Databases
291 /// <param name="mediaTable"></param>
292 /// <param name="cabIndex"></param>
293 /// <returns></returns>
300 - private MediaRow AddMediaRow(WixMediaTemplateRow mediaTemplateRow, Table mediaTable, int cabIndex)
294 + private MediaTuple AddMediaRow(WixMediaTemplateTuple mediaTemplateRow, int cabIndex)
295 {
302 - MediaRow currentMediaRow = (MediaRow)mediaTable.CreateRow(mediaTemplateRow.SourceLineNumbers);
296 + var currentMediaRow = new MediaTuple(mediaTemplateRow.SourceLineNumbers, new Identifier(cabIndex, AccessModifier.Private));
297 currentMediaRow.DiskId = cabIndex;
298 currentMediaRow.Cabinet = String.Format(CultureInfo.InvariantCulture, this.CabinetNameTemplate, cabIndex);
299
306 - Table wixMediaTable = this.Output.EnsureTable(this.TableDefinitions["WixMedia"]);
307 - WixMediaRow row = (WixMediaRow)wixMediaTable.CreateRow(mediaTemplateRow.SourceLineNumbers);
308 - row.DiskId = cabIndex;
300 + this.Section.Tuples.Add(currentMediaRow);
301 +
302 + var row = new WixMediaTuple(mediaTemplateRow.SourceLineNumbers, new Identifier(cabIndex, AccessModifier.Private));
303 + row.DiskId_ = cabIndex;
304 row.CompressionLevel = mediaTemplateRow.CompressionLevel;
305
306 + this.Section.Tuples.Add(row);
307 +
308 return currentMediaRow;
309 }
310 }
src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs
+224 -515
@@ -3,21 +3,15 @@
3 namespace WixToolset.Core.WindowsInstaller.Bind
4 {
5 using System;
6 - using System.Collections;
6 using System.Collections.Generic;
8 - using System.Diagnostics;
9 - using System.Globalization;
7 using System.IO;
8 using System.Linq;
12 - using WixToolset.Bind;
9 using WixToolset.Core.Bind;
14 - using WixToolset.Core.WindowsInstaller.Databases;
10 using WixToolset.Data;
11 using WixToolset.Data.Bind;
17 - using WixToolset.Data.Rows;
12 + using WixToolset.Data.Tuples;
13 using WixToolset.Extensibility;
14 using WixToolset.Extensibility.Services;
20 - using WixToolset.Msi;
15
16 /// <summary>
17 /// Binds a databse.
@@ -25,11 +19,11 @@ namespace WixToolset.Core.WindowsInstaller.Bind
19 internal class BindDatabaseCommand
20 {
21 // As outlined in RFC 4122, this is our namespace for generating name-based (version 3) UUIDs.
28 - private static readonly Guid WixComponentGuidNamespace = new Guid("{3064E5C6-FB63-4FE9-AC49-E446A792EFA5}");
22 + internal static readonly Guid WixComponentGuidNamespace = new Guid("{3064E5C6-FB63-4FE9-AC49-E446A792EFA5}");
23
24 public BindDatabaseCommand(IBindContext context, Validator validator)
25 {
32 - this.TableDefinitions = WindowsInstallerStandard.GetTableDefinitions();
26 + this.TableDefinitions = WindowsInstallerStandardInternal.GetTableDefinitions();
27
28 this.BindPaths = context.BindPaths;
29 this.CabbingThreadCount = context.CabbingThreadCount;
@@ -73,8 +67,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind
67
68 private Intermediate Intermediate { get; }
69
76 - private Output Output { get; }
77 -
70 private string OutputPath { get; }
71
72 private bool SuppressAddingValidationRows { get; }
@@ -95,22 +87,16 @@ namespace WixToolset.Core.WindowsInstaller.Bind
87
88 public void Execute()
89 {
98 - this.Intermediate.Save(this.OutputPath);
99 -#if FINISH
100 - List<FileTransfer> fileTransfers = new List<FileTransfer>();
90 + var section = this.Intermediate.Sections.Single();
91
102 - HashSet<string> suppressedTableNames = new HashSet<string>();
92 + var fileTransfers = new List<FileTransfer>();
93
104 - // If there are any fields to resolve later, create the cache to populate during bind.
105 - IDictionary<string, string> variableCache = null;
106 - if (this.DelayedFields.Any())
107 - {
108 - variableCache = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
109 - }
94 + var suppressedTableNames = new HashSet<string>();
95
111 - this.LocalizeUI(this.Output.Tables);
96 + // If there are any fields to resolve later, create the cache to populate during bind.
97 + var variableCache = this.DelayedFields.Any() ? new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase) : null;
98
113 - this.Output = CreateOutputFromIR(this.Intermediate);
99 + this.LocalizeUI(section);
100
101 // Process the summary information table before the other tables.
102 bool compressed;
@@ -118,8 +104,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
104 int installerVersion;
105 string modularizationGuid;
106 {
121 - BindSummaryInfoCommand command = new BindSummaryInfoCommand();
122 - command.Output = this.Output;
107 + var command = new BindSummaryInfoCommand(section);
108 command.Execute();
109
110 compressed = command.Compressed;
@@ -128,42 +113,61 @@ namespace WixToolset.Core.WindowsInstaller.Bind
113 modularizationGuid = command.ModularizationGuid;
114 }
115
131 - // Stop processing if an error previously occurred.
132 - if (Messaging.Instance.EncounteredError)
133 - {
134 - return;
135 - }
136 -
137 - // Modularize identifiers and add tables with real streams to the import tables.
138 - if (OutputType.Module == this.Output.Type)
116 + // Add binder variables for all properties.
117 + if (SectionType.Product == section.Type || variableCache != null)
118 {
140 - // Gather all the suppress modularization identifiers
141 - HashSet<string> suppressModularizationIdentifiers = null;
142 - Table wixSuppressModularizationTable = this.Output.Tables["WixSuppressModularization"];
143 - if (null != wixSuppressModularizationTable)
119 + foreach (var propertyRow in section.Tuples.OfType<PropertyTuple>())
120 {
145 - suppressModularizationIdentifiers = new HashSet<string>(wixSuppressModularizationTable.Rows.Select(row => (string)row[0]));
146 - }
121 + // Set the ProductCode if it is to be generated.
122 + if ("ProductCode".Equals(propertyRow.Property, StringComparison.Ordinal) && "*".Equals(propertyRow.Value, StringComparison.Ordinal))
123 + {
124 + propertyRow.Value = Common.GenerateGuid();
125
148 - foreach (Table table in this.Output.Tables)
149 - {
150 - table.Modularize(modularizationGuid, suppressModularizationIdentifiers);
126 +#if TODO_FIX_INSTANCE_TRANSFORM
127 + // Update the target ProductCode in any instance transforms.
128 + foreach (SubStorage subStorage in this.Output.SubStorages)
129 + {
130 + Output subStorageOutput = subStorage.Data;
131 + if (OutputType.Transform != subStorageOutput.Type)
132 + {
133 + continue;
134 + }
135 +
136 + Table instanceSummaryInformationTable = subStorageOutput.Tables["_SummaryInformation"];
137 + foreach (Row row in instanceSummaryInformationTable.Rows)
138 + {
139 + if ((int)SummaryInformation.Transform.ProductCodes == row.FieldAsInteger(0))
140 + {
141 + row[1] = row.FieldAsString(1).Replace("*", propertyRow.Value);
142 + break;
143 + }
144 + }
145 + }
146 +#endif
147 + }
148 +
149 + // Add the property name and value to the variableCache.
150 + if (variableCache != null)
151 + {
152 + var key = String.Concat("property.", propertyRow.Property);
153 + variableCache[key] = propertyRow.Value;
154 + }
155 }
156 }
157
154 - // This must occur after all variables and source paths have been resolved and after modularization.
155 - List<FileFacade> fileFacades;
158 + // Sequence all the actions.
159 {
157 - GetFileFacadesCommand command = new GetFileFacadesCommand();
158 - command.FileTable = this.Output.Tables["File"];
159 - command.WixFileTable = this.Output.Tables["WixFile"];
160 - command.WixDeltaPatchFileTable = this.Output.Tables["WixDeltaPatchFile"];
161 - command.WixDeltaPatchSymbolPathsTable = this.Output.Tables["WixDeltaPatchSymbolPaths"];
160 + var command = new SequenceActionsCommand(section);
161 + command.Messaging = Messaging.Instance;
162 command.Execute();
163 + }
164
164 - fileFacades = command.FileFacades;
165 + {
166 + var command = new CreateSpecialPropertiesCommand(section);
167 + command.Execute();
168 }
169
170 +#if TODO_FINISH_PATCH
171 ////if (OutputType.Patch == this.Output.Type)
172 ////{
173 //// foreach (SubStorage substorage in this.Output.SubStorages)
@@ -183,87 +187,72 @@ namespace WixToolset.Core.WindowsInstaller.Bind
187 //// this.MergeUnrealTables(transform.Tables);
188 //// }
189 ////}
186 -
187 - {
188 - CreateSpecialPropertiesCommand command = new CreateSpecialPropertiesCommand();
189 - command.PropertyTable = this.Output.Tables["Property"];
190 - command.WixPropertyTable = this.Output.Tables["WixProperty"];
191 - command.Execute();
192 - }
190 +#endif
191
192 if (Messaging.Instance.EncounteredError)
193 {
194 return;
195 }
196
199 - // Add binder variables for all properties.
200 - Table propertyTable = this.Output.Tables["Property"];
201 - if (null != propertyTable)
197 + Messaging.Instance.OnMessage(WixVerboses.UpdatingFileInformation());
198 +
199 + // This must occur after all variables and source paths have been resolved.
200 + List<FileFacade> fileFacades;
201 {
203 - foreach (PropertyRow propertyRow in propertyTable.Rows)
204 - {
205 - // Set the ProductCode if it is to be generated.
206 - if (OutputType.Product == this.Output.Type && "ProductCode".Equals(propertyRow.Property, StringComparison.Ordinal) && "*".Equals(propertyRow.Value, StringComparison.Ordinal))
207 - {
208 - propertyRow.Value = Common.GenerateGuid();
202 + var command = new GetFileFacadesCommand(section);
203 + command.Execute();
204
210 - // Update the target ProductCode in any instance transforms.
211 - foreach (SubStorage subStorage in this.Output.SubStorages)
212 - {
213 - Output subStorageOutput = subStorage.Data;
214 - if (OutputType.Transform != subStorageOutput.Type)
215 - {
216 - continue;
217 - }
205 + fileFacades = command.FileFacades;
206 + }
207
219 - Table instanceSummaryInformationTable = subStorageOutput.Tables["_SummaryInformation"];
220 - foreach (Row row in instanceSummaryInformationTable.Rows)
221 - {
222 - if ((int)SummaryInformation.Transform.ProductCodes == row.FieldAsInteger(0))
223 - {
224 - row[1] = row.FieldAsString(1).Replace("*", propertyRow.Value);
225 - break;
226 - }
227 - }
228 - }
229 - }
208 + // Extract files that come from binary .wixlibs and WixExtensions (this does not extract files from merge modules).
209 + {
210 + var command = new ExtractEmbeddedFilesCommand(this.ExpectedEmbeddedFiles);
211 + command.Execute();
212 + }
213
231 - // Add the property name and value to the variableCache.
232 - if (null != variableCache)
233 - {
234 - string key = String.Concat("property.", Common.Demodularize(this.Output.Type, modularizationGuid, propertyRow.Property));
235 - variableCache[key] = propertyRow.Value;
236 - }
237 - }
214 + // Gather information about files that did not come from merge modules (i.e. rows with a reference to the File table).
215 + {
216 + var command = new UpdateFileFacadesCommand(section);
217 + command.FileFacades = fileFacades;
218 + command.UpdateFileFacades = fileFacades.Where(f => !f.FromModule);
219 + command.OverwriteHash = true;
220 + command.TableDefinitions = this.TableDefinitions;
221 + command.VariableCache = variableCache;
222 + command.Execute();
223 }
224
240 - // Extract files that come from cabinet files (this does not extract files from merge modules).
225 + // Now that the variable cache is populated, resolve any delayed fields.
226 + if (this.DelayedFields.Any())
227 {
242 - ExtractEmbeddedFilesCommand command = new ExtractEmbeddedFilesCommand();
243 - command.FilesWithEmbeddedFiles = this.ExpectedEmbeddedFiles;
228 + var command = new ResolveDelayedFieldsCommand(this.DelayedFields, variableCache);
229 command.Execute();
230 }
231
247 - if (OutputType.Product == this.Output.Type)
232 + // Set generated component guids.
233 + {
234 + var command = new CalculateComponentGuids(section);
235 + command.Execute();
236 + }
237 +
238 + if (SectionType.Product == section.Type)
239 {
240 // Retrieve files and their information from merge modules.
250 - Table wixMergeTable = this.Output.Tables["WixMerge"];
241 + var wixMergeTuples = section.Tuples.OfType<WixMergeTuple>().ToList();
242
252 - if (null != wixMergeTable)
243 + if (wixMergeTuples.Any())
244 {
254 - ExtractMergeModuleFilesCommand command = new ExtractMergeModuleFilesCommand();
245 + var command = new ExtractMergeModuleFilesCommand(section, wixMergeTuples);
246 command.FileFacades = fileFacades;
256 - command.FileTable = this.Output.Tables["File"];
257 - command.WixFileTable = this.Output.Tables["WixFile"];
258 - command.WixMergeTable = wixMergeTable;
247 command.OutputInstallerVersion = installerVersion;
248 command.SuppressLayout = this.SuppressLayout;
261 - command.TempFilesLocation = this.IntermediateFolder;
249 + command.IntermediateFolder = this.IntermediateFolder;
250 command.Execute();
251
252 fileFacades.AddRange(command.MergeModulesFileFacades);
253 }
254 }
255 +#if TODO_FINISH_PATCH
256 else if (OutputType.Patch == this.Output.Type)
257 {
258 // Merge transform data into the output object.
@@ -271,6 +260,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
260
261 fileFacades.AddRange(filesFromTransform);
262 }
263 +#endif
264
265 // stop processing if an error previously occurred
266 if (Messaging.Instance.EncounteredError)
@@ -278,51 +268,19 @@ namespace WixToolset.Core.WindowsInstaller.Bind
268 return;
269 }
270
281 - Messaging.Instance.OnMessage(WixVerboses.UpdatingFileInformation());
282 -
283 - // Gather information about files that did not come from merge modules (i.e. rows with a reference to the File table).
284 - {
285 - UpdateFileFacadesCommand command = new UpdateFileFacadesCommand();
286 - command.FileFacades = fileFacades;
287 - command.UpdateFileFacades = fileFacades.Where(f => !f.FromModule);
288 - command.ModularizationGuid = modularizationGuid;
289 - command.Output = this.Output;
290 - command.OverwriteHash = true;
291 - command.TableDefinitions = this.TableDefinitions;
292 - command.VariableCache = variableCache;
293 - command.Execute();
294 - }
295 -
296 - // Set generated component guids.
297 - this.SetComponentGuids(this.Output);
298 -
271 +#if TODO_FIX_INSTANCE_TRANSFORM
272 // With the Component Guids set now we can create instance transforms.
273 this.CreateInstanceTransforms(this.Output);
301 -
302 - this.ValidateComponentGuids(this.Output);
303 -
304 - this.UpdateControlText(this.Output);
305 -
306 - if (this.DelayedFields.Any())
307 - {
308 - ResolveDelayedFieldsCommand command = new ResolveDelayedFieldsCommand();
309 - command.OutputType = this.Output.Type;
310 - command.DelayedFields = this.DelayedFields;
311 - command.ModularizationGuid = null;
312 - command.VariableCache = variableCache;
313 - command.Execute();
314 - }
274 +#endif
275
276 // Assign files to media.
317 - RowDictionary<MediaRow> assignedMediaRows;
318 - Dictionary<MediaRow, IEnumerable<FileFacade>> filesByCabinetMedia;
277 + Dictionary<int, MediaTuple> assignedMediaRows;
278 + Dictionary<MediaTuple, IEnumerable<FileFacade>> filesByCabinetMedia;
279 IEnumerable<FileFacade> uncompressedFiles;
280 {
321 - AssignMediaCommand command = new AssignMediaCommand();
322 - command.FilesCompressed = compressed;
281 + var command = new AssignMediaCommand(section);
282 command.FileFacades = fileFacades;
324 - command.Output = this.Output;
325 - command.TableDefinitions = this.TableDefinitions;
283 + command.FilesCompressed = compressed;
284 command.Execute();
285
286 assignedMediaRows = command.MediaRows;
@@ -330,15 +288,40 @@ namespace WixToolset.Core.WindowsInstaller.Bind
288 uncompressedFiles = command.UncompressedFileFacades;
289 }
290
333 - // Update file sequence.
334 - this.UpdateMediaSequences(this.Output.Type, fileFacades, assignedMediaRows);
335 -
291 // stop processing if an error previously occurred
292 if (Messaging.Instance.EncounteredError)
293 {
294 return;
295 }
296
297 + // Try to put as much above here as possible, updating the IR is better.
298 + Output output;
299 + {
300 + var command = new CreateOutputFromIRCommand(section, this.TableDefinitions);
301 + command.Execute();
302 +
303 + output = command.Output;
304 + }
305 +
306 + // Update file sequence.
307 + {
308 + var command = new UpdateMediaSequencesCommand(output, fileFacades, assignedMediaRows);
309 + command.Execute();
310 + }
311 +
312 + // Modularize identifiers and add tables with real streams to the import tables.
313 + if (OutputType.Module == output.Type)
314 + {
315 + // Gather all the suppress modularization identifiers
316 + var suppressModularizationIdentifiers = new HashSet<string>(section.Tuples.OfType<WixSuppressModularizationTuple>().Select(s => s.WixSuppressModularization));
317 +
318 + foreach (var table in output.Tables)
319 + {
320 + table.Modularize(modularizationGuid, suppressModularizationIdentifiers);
321 + }
322 + }
323 +
324 +#if TODO_FINISH_UPDATE
325 // Extended binder extensions can be called now that fields are resolved.
326 {
327 Table updatedFiles = this.Output.EnsureTable(this.TableDefinitions["WixBindUpdatedFiles"]);
@@ -372,27 +355,27 @@ namespace WixToolset.Core.WindowsInstaller.Bind
355 command.Execute();
356 }
357 }
358 +#endif
359
376 - // stop processing if an error previously occurred
360 + // Stop processing if an error previously occurred.
361 if (Messaging.Instance.EncounteredError)
362 {
363 return;
364 }
365
366 + // Ensure the intermediate folder is created since delta patches will be
367 + // created there.
368 Directory.CreateDirectory(this.IntermediateFolder);
369
384 - if (OutputType.Patch == this.Output.Type && this.DeltaBinaryPatch)
370 + if (SectionType.Patch == section.Type && this.DeltaBinaryPatch)
371 {
386 - CreateDeltaPatchesCommand command = new CreateDeltaPatchesCommand();
387 - command.FileFacades = fileFacades;
388 - command.WixPatchIdTable = this.Output.Tables["WixPatchId"];
389 - command.TempFilesLocation = this.IntermediateFolder;
372 + var command = new CreateDeltaPatchesCommand(fileFacades, this.IntermediateFolder, section.Tuples.OfType<WixPatchIdTuple>().FirstOrDefault());
373 command.Execute();
374 }
375
376 // create cabinet files and process uncompressed files
377 string layoutDirectory = Path.GetDirectoryName(this.OutputPath);
395 - if (!this.SuppressLayout || OutputType.Module == this.Output.Type)
378 + if (!this.SuppressLayout || OutputType.Module == output.Type)
379 {
380 Messaging.Instance.OnMessage(WixVerboses.CreatingCabinetFiles());
381
@@ -400,7 +383,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
383 command.CabbingThreadCount = this.CabbingThreadCount;
384 command.CabCachePath = this.CabCachePath;
385 command.DefaultCompressionLevel = this.DefaultCompressionLevel;
403 - command.Output = this.Output;
386 + command.Output = output;
387 command.BackendExtensions = this.BackendExtensions;
388 command.LayoutDirectory = layoutDirectory;
389 command.Compressed = compressed;
@@ -408,39 +391,35 @@ namespace WixToolset.Core.WindowsInstaller.Bind
391 command.ResolveMedia = this.ResolveMedia;
392 command.TableDefinitions = this.TableDefinitions;
393 command.TempFilesLocation = this.IntermediateFolder;
411 - command.WixMediaTable = this.Output.Tables["WixMedia"];
394 + command.WixMediaTable = output.Tables["WixMedia"];
395 command.Execute();
396
397 fileTransfers.AddRange(command.FileTransfers);
398 }
399
400 +#if TODO_FINISH_PATCH
401 if (OutputType.Patch == this.Output.Type)
402 {
403 // copy output data back into the transforms
404 this.CopyToTransformData(this.Output);
405 }
406 +#endif
407
423 - // stop processing if an error previously occurred
424 - if (Messaging.Instance.EncounteredError)
425 - {
426 - return;
427 - }
428 -
429 - // add back suppressed tables which must be present prior to merging in modules
430 - if (OutputType.Product == this.Output.Type)
408 + // Add back suppressed tables which must be present prior to merging in modules.
409 + if (OutputType.Product == output.Type)
410 {
432 - Table wixMergeTable = this.Output.Tables["WixMerge"];
411 + Table wixMergeTable = output.Tables["WixMerge"];
412
413 if (null != wixMergeTable && 0 < wixMergeTable.Rows.Count)
414 {
415 foreach (SequenceTable sequence in Enum.GetValues(typeof(SequenceTable)))
416 {
417 string sequenceTableName = sequence.ToString();
439 - Table sequenceTable = this.Output.Tables[sequenceTableName];
418 + Table sequenceTable = output.Tables[sequenceTableName];
419
420 if (null == sequenceTable)
421 {
443 - sequenceTable = this.Output.EnsureTable(this.TableDefinitions[sequenceTableName]);
422 + sequenceTable = output.EnsureTable(this.TableDefinitions[sequenceTableName]);
423 }
424
425 if (0 == sequenceTable.Rows.Count)
@@ -456,67 +435,59 @@ namespace WixToolset.Core.WindowsInstaller.Bind
435 // extension.PostBind(this.Context);
436 //}
437
459 - // generate database file
438 + this.ValidateComponentGuids(output);
439 +
440 + // stop processing if an error previously occurred
441 + if (Messaging.Instance.EncounteredError)
442 + {
443 + return;
444 + }
445 +
446 + // Generate database file.
447 Messaging.Instance.OnMessage(WixVerboses.GeneratingDatabase());
448 string tempDatabaseFile = Path.Combine(this.IntermediateFolder, Path.GetFileName(this.OutputPath));
462 - this.GenerateDatabase(this.Output, tempDatabaseFile, false, false);
449 + this.GenerateDatabase(output, tempDatabaseFile, false, false);
450
464 - FileTransfer transfer;
465 - if (FileTransfer.TryCreate(tempDatabaseFile, this.OutputPath, true, this.Output.Type.ToString(), null, out transfer)) // note where this database needs to move in the future
451 + if (FileTransfer.TryCreate(tempDatabaseFile, this.OutputPath, true, output.Type.ToString(), null, out var transfer)) // note where this database needs to move in the future
452 {
453 transfer.Built = true;
454 fileTransfers.Add(transfer);
455 }
456
471 - // stop processing if an error previously occurred
457 + // Stop processing if an error previously occurred.
458 if (Messaging.Instance.EncounteredError)
459 {
460 return;
461 }
462
477 - // Output the output to a file
463 + // Output the output to a file.
464 Pdb pdb = new Pdb();
479 - pdb.Output = this.Output;
465 + pdb.Output = output;
466 if (!String.IsNullOrEmpty(this.PdbFile))
467 {
468 pdb.Save(this.PdbFile);
469 }
470
471 // Merge modules.
486 - if (OutputType.Product == this.Output.Type)
472 + if (OutputType.Product == output.Type)
473 {
474 Messaging.Instance.OnMessage(WixVerboses.MergingModules());
475
490 - MergeModulesCommand command = new MergeModulesCommand();
476 + var command = new MergeModulesCommand();
477 command.FileFacades = fileFacades;
492 - command.Output = this.Output;
478 + command.Output = output;
479 command.OutputPath = tempDatabaseFile;
480 command.SuppressedTableNames = suppressedTableNames;
481 command.Execute();
496 -
497 - // stop processing if an error previously occurred
498 - if (Messaging.Instance.EncounteredError)
499 - {
500 - return;
501 - }
482 }
483
504 - // inspect the MSI prior to running ICEs
505 - //InspectorCore inspectorCore = new InspectorCore();
506 - //foreach (InspectorExtension inspectorExtension in this.InspectorExtensions)
507 - //{
508 - // inspectorExtension.Core = inspectorCore;
509 - // inspectorExtension.InspectDatabase(tempDatabaseFile, pdb);
510 -
511 - // inspectorExtension.Core = null; // reset.
512 - //}
513 -
484 if (Messaging.Instance.EncounteredError)
485 {
486 return;
487 }
488
519 - // validate the output if there is an MSI validator
489 +#if TODO_FINISH_VALIDATION
490 + // Validate the output if there is an MSI validator.
491 if (null != this.Validator)
492 {
493 Stopwatch stopwatch = Stopwatch.StartNew();
@@ -537,19 +508,18 @@ namespace WixToolset.Core.WindowsInstaller.Bind
508 return;
509 }
510 }
511 +#endif
512
513 // Process uncompressed files.
514 if (!Messaging.Instance.EncounteredError && !this.SuppressLayout && uncompressedFiles.Any())
515 {
544 - var command = new ProcessUncompressedFilesCommand();
516 + var command = new ProcessUncompressedFilesCommand(section);
517 command.Compressed = compressed;
518 command.FileFacades = uncompressedFiles;
519 command.LayoutDirectory = layoutDirectory;
520 command.LongNamesInImage = longNames;
549 - command.MediaRows = assignedMediaRows;
521 command.ResolveMedia = this.ResolveMedia;
522 command.DatabasePath = tempDatabaseFile;
552 - command.WixMediaTable = this.Output.Tables["WixMedia"];
523 command.Execute();
524
525 fileTransfers.AddRange(command.FileTransfers);
@@ -557,94 +527,92 @@ namespace WixToolset.Core.WindowsInstaller.Bind
527
528 this.FileTransfers = fileTransfers;
529 this.ContentFilePaths = fileFacades.Select(r => r.WixFile.Source).ToList();
530 +
531 + // TODO: Eventually this gets removed
532 + var intermediate = new Intermediate(this.Intermediate.Id, new[] { section }, this.Intermediate.Localizations.ToDictionary(l => l.Culture, StringComparer.OrdinalIgnoreCase), this.Intermediate.EmbedFilePaths);
533 + intermediate.Save(Path.ChangeExtension(this.OutputPath, "wir"));
534 }
535
536 /// <summary>
537 /// Localize dialogs and controls.
538 /// </summary>
539 /// <param name="tables">The tables to localize.</param>
566 - private void LocalizeUI(TableIndexedCollection tables)
540 + private void LocalizeUI(IntermediateSection section)
541 {
568 - Table dialogTable = tables["Dialog"];
569 - if (null != dialogTable)
542 + foreach (var row in section.Tuples.OfType<DialogTuple>())
543 {
571 - foreach (Row row in dialogTable.Rows)
572 - {
573 - string dialog = (string)row[0];
544 + string dialog = row.Dialog;
545
575 - if (this.WixVariableResolver.TryGetLocalizedControl(dialog, null, out LocalizedControl localizedControl))
546 + if (this.WixVariableResolver.TryGetLocalizedControl(dialog, null, out LocalizedControl localizedControl))
547 + {
548 + if (CompilerConstants.IntegerNotSet != localizedControl.X)
549 {
577 - if (CompilerConstants.IntegerNotSet != localizedControl.X)
578 - {
579 - row[1] = localizedControl.X;
580 - }
550 + row.HCentering = localizedControl.X;
551 + }
552
582 - if (CompilerConstants.IntegerNotSet != localizedControl.Y)
583 - {
584 - row[2] = localizedControl.Y;
585 - }
553 + if (CompilerConstants.IntegerNotSet != localizedControl.Y)
554 + {
555 + row.VCentering = localizedControl.Y;
556 + }
557
587 - if (CompilerConstants.IntegerNotSet != localizedControl.Width)
588 - {
589 - row[3] = localizedControl.Width;
590 - }
558 + if (CompilerConstants.IntegerNotSet != localizedControl.Width)
559 + {
560 + row.Width = localizedControl.Width;
561 + }
562
592 - if (CompilerConstants.IntegerNotSet != localizedControl.Height)
593 - {
594 - row[4] = localizedControl.Height;
595 - }
563 + if (CompilerConstants.IntegerNotSet != localizedControl.Height)
564 + {
565 + row.Height = localizedControl.Height;
566 + }
567
597 - row[5] = (int)row[5] | localizedControl.Attributes;
568 + row.Attributes = row.Attributes | localizedControl.Attributes;
569
599 - if (!String.IsNullOrEmpty(localizedControl.Text))
600 - {
601 - row[6] = localizedControl.Text;
602 - }
570 + if (!String.IsNullOrEmpty(localizedControl.Text))
571 + {
572 + row.Title = localizedControl.Text;
573 }
574 }
575 }
576
607 - Table controlTable = tables["Control"];
608 - if (null != controlTable)
577 +
578 + foreach (var row in section.Tuples.OfType<ControlTuple>())
579 {
610 - foreach (Row row in controlTable.Rows)
611 - {
612 - string dialog = (string)row[0];
613 - string control = (string)row[1];
580 + string dialog = row.Dialog_;
581 + string control = row.Control;
582
615 - if (this.WixVariableResolver.TryGetLocalizedControl(dialog, control, out LocalizedControl localizedControl))
583 + if (this.WixVariableResolver.TryGetLocalizedControl(dialog, control, out LocalizedControl localizedControl))
584 + {
585 + if (CompilerConstants.IntegerNotSet != localizedControl.X)
586 {
617 - if (CompilerConstants.IntegerNotSet != localizedControl.X)
618 - {
619 - row[3] = localizedControl.X.ToString();
620 - }
587 + row.X = localizedControl.X;
588 + }
589
622 - if (CompilerConstants.IntegerNotSet != localizedControl.Y)
623 - {
624 - row[4] = localizedControl.Y.ToString();
625 - }
590 + if (CompilerConstants.IntegerNotSet != localizedControl.Y)
591 + {
592 + row.Y = localizedControl.Y;
593 + }
594
627 - if (CompilerConstants.IntegerNotSet != localizedControl.Width)
628 - {
629 - row[5] = localizedControl.Width.ToString();
630 - }
595 + if (CompilerConstants.IntegerNotSet != localizedControl.Width)
596 + {
597 + row.Width = localizedControl.Width;
598 + }
599
632 - if (CompilerConstants.IntegerNotSet != localizedControl.Height)
633 - {
634 - row[6] = localizedControl.Height.ToString();
635 - }
600 + if (CompilerConstants.IntegerNotSet != localizedControl.Height)
601 + {
602 + row.Height = localizedControl.Height;
603 + }
604
637 - row[7] = (int)row[7] | localizedControl.Attributes;
605 + row.Attributes = row.Attributes | localizedControl.Attributes;
606
639 - if (!String.IsNullOrEmpty(localizedControl.Text))
640 - {
641 - row[9] = localizedControl.Text;
642 - }
607 + if (!String.IsNullOrEmpty(localizedControl.Text))
608 + {
609 + row.Text = localizedControl.Text;
610 }
611 }
612 }
613 }
614
615 +#if TODO_FINISH_PATCH
616 /// <summary>
617 /// Copy file data between transform substorages and the patch output object
618 /// </summary>
@@ -674,269 +642,10 @@ namespace WixToolset.Core.WindowsInstaller.Bind
642 command.TableDefinitions = this.TableDefinitions;
643 command.Execute();
644 }
645 +#endif
646
678 - private void UpdateMediaSequences(OutputType outputType, IEnumerable<FileFacade> fileFacades, RowDictionary<MediaRow> mediaRows)
679 - {
680 - // Calculate sequence numbers and media disk id layout for all file media information objects.
681 - if (OutputType.Module == outputType)
682 - {
683 - int lastSequence = 0;
684 - foreach (FileFacade facade in fileFacades) // TODO: Sort these rows directory path and component id and maybe file size or file extension and other creative ideas to get optimal install speed out of MSI.
685 - {
686 - facade.File.Sequence = ++lastSequence;
687 - }
688 - }
689 - else
690 - {
691 - int lastSequence = 0;
692 - MediaRow mediaRow = null;
693 - Dictionary<int, List<FileFacade>> patchGroups = new Dictionary<int, List<FileFacade>>();
694 -
695 - // sequence the non-patch-added files
696 - foreach (FileFacade facade in fileFacades) // TODO: Sort these rows directory path and component id and maybe file size or file extension and other creative ideas to get optimal install speed out of MSI.
697 - {
698 - if (null == mediaRow)
699 - {
700 - mediaRow = mediaRows.Get(facade.WixFile.DiskId);
701 - if (OutputType.Patch == outputType)
702 - {
703 - // patch Media cannot start at zero
704 - lastSequence = mediaRow.LastSequence;
705 - }
706 - }
707 - else if (mediaRow.DiskId != facade.WixFile.DiskId)
708 - {
709 - mediaRow.LastSequence = lastSequence;
710 - mediaRow = mediaRows.Get(facade.WixFile.DiskId);
711 - }
712 -
713 - if (0 < facade.WixFile.PatchGroup)
714 - {
715 - List<FileFacade> patchGroup = patchGroups[facade.WixFile.PatchGroup];
716 -
717 - if (null == patchGroup)
718 - {
719 - patchGroup = new List<FileFacade>();
720 - patchGroups.Add(facade.WixFile.PatchGroup, patchGroup);
721 - }
722 -
723 - patchGroup.Add(facade);
724 - }
725 - else
726 - {
727 - facade.File.Sequence = ++lastSequence;
728 - }
729 - }
730 -
731 - if (null != mediaRow)
732 - {
733 - mediaRow.LastSequence = lastSequence;
734 - mediaRow = null;
735 - }
736 -
737 - // sequence the patch-added files
738 - foreach (List<FileFacade> patchGroup in patchGroups.Values)
739 - {
740 - foreach (FileFacade facade in patchGroup)
741 - {
742 - if (null == mediaRow)
743 - {
744 - mediaRow = mediaRows.Get(facade.WixFile.DiskId);
745 - }
746 - else if (mediaRow.DiskId != facade.WixFile.DiskId)
747 - {
748 - mediaRow.LastSequence = lastSequence;
749 - mediaRow = mediaRows.Get(facade.WixFile.DiskId);
750 - }
751 -
752 - facade.File.Sequence = ++lastSequence;
753 - }
754 - }
755 -
756 - if (null != mediaRow)
757 - {
758 - mediaRow.LastSequence = lastSequence;
759 - }
760 - }
761 - }
762 -
763 - /// <summary>
764 - /// Set the guids for components with generatable guids.
765 - /// </summary>
766 - /// <param name="output">Internal representation of the database to operate on.</param>
767 - private void SetComponentGuids(Output output)
768 - {
769 - Table componentTable = output.Tables["Component"];
770 - if (null != componentTable)
771 - {
772 - Hashtable registryKeyRows = null;
773 - Hashtable directories = null;
774 - Hashtable componentIdGenSeeds = null;
775 - Dictionary<string, List<FileRow>> fileRows = null;
776 -
777 - // find components with generatable guids
778 - foreach (ComponentRow componentRow in componentTable.Rows)
779 - {
780 - // component guid will be generated
781 - if ("*" == componentRow.Guid)
782 - {
783 - if (null == componentRow.KeyPath || componentRow.IsOdbcDataSourceKeyPath)
784 - {
785 - Messaging.Instance.OnMessage(WixErrors.IllegalComponentWithAutoGeneratedGuid(componentRow.SourceLineNumbers));
786 - }
787 - else if (componentRow.IsRegistryKeyPath)
788 - {
789 - if (null == registryKeyRows)
790 - {
791 - Table registryTable = output.Tables["Registry"];
792 -
793 - registryKeyRows = new Hashtable(registryTable.Rows.Count);
794 -
795 - foreach (Row registryRow in registryTable.Rows)
796 - {
797 - registryKeyRows.Add((string)registryRow[0], registryRow);
798 - }
799 - }
800 -
801 - Row foundRow = registryKeyRows[componentRow.KeyPath] as Row;
802 -
803 - string bitness = componentRow.Is64Bit ? "64" : String.Empty;
804 - if (null != foundRow)
805 - {
806 - string regkey = String.Concat(bitness, foundRow[1], "\\", foundRow[2], "\\", foundRow[3]);
807 - componentRow.Guid = Uuid.NewUuid(BindDatabaseCommand.WixComponentGuidNamespace, regkey.ToLowerInvariant()).ToString("B").ToUpperInvariant();
808 - }
809 - }
810 - else // must be a File KeyPath
811 - {
812 - // if the directory table hasn't been loaded into an indexed hash
813 - // of directory ids to target names do that now.
814 - if (null == directories)
815 - {
816 - Table directoryTable = output.Tables["Directory"];
817 -
818 - int numDirectoryTableRows = (null != directoryTable) ? directoryTable.Rows.Count : 0;
819 -
820 - directories = new Hashtable(numDirectoryTableRows);
821 -
822 - // get the target paths for all directories
823 - if (null != directoryTable)
824 - {
825 - foreach (Row row in directoryTable.Rows)
826 - {
827 - // if the directory Id already exists, we will skip it here since
828 - // checking for duplicate primary keys is done later when importing tables
829 - // into database
830 - if (directories.ContainsKey(row[0]))
831 - {
832 - continue;
833 - }
834 -
835 - string targetName = Common.GetName((string)row[2], false, true);
836 - directories.Add(row[0], new ResolvedDirectory((string)row[1], targetName));
837 - }
838 - }
839 - }
840 -
841 - // if the component id generation seeds have not been indexed
842 - // from the WixDirectory table do that now.
843 - if (null == componentIdGenSeeds)
844 - {
845 - Table wixDirectoryTable = output.Tables["WixDirectory"];
846 -
847 - int numWixDirectoryRows = (null != wixDirectoryTable) ? wixDirectoryTable.Rows.Count : 0;
848 -
849 - componentIdGenSeeds = new Hashtable(numWixDirectoryRows);
850 -
851 - // if there are any WixDirectory rows, build up the Component Guid
852 - // generation seeds indexed by Directory/@Id.
853 - if (null != wixDirectoryTable)
854 - {
855 - foreach (Row row in wixDirectoryTable.Rows)
856 - {
857 - componentIdGenSeeds.Add(row[0], (string)row[1]);
858 - }
859 - }
860 - }
861 -
862 - // if the file rows have not been indexed by File.Component yet
863 - // then do that now
864 - if (null == fileRows)
865 - {
866 - Table fileTable = output.Tables["File"];
867 -
868 - int numFileRows = (null != fileTable) ? fileTable.Rows.Count : 0;
869 -
870 - fileRows = new Dictionary<string, List<FileRow>>(numFileRows);
871 -
872 - if (null != fileTable)
873 - {
874 - foreach (FileRow file in fileTable.Rows)
875 - {
876 - List<FileRow> files;
877 - if (!fileRows.TryGetValue(file.Component, out files))
878 - {
879 - files = new List<FileRow>();
880 - fileRows.Add(file.Component, files);
881 - }
882 -
883 - files.Add(file);
884 - }
885 - }
886 - }
887 -
888 - // validate component meets all the conditions to have a generated guid
889 - List<FileRow> currentComponentFiles = fileRows[componentRow.Component];
890 - int numFilesInComponent = currentComponentFiles.Count;
891 - string path = null;
892 -
893 - foreach (FileRow fileRow in currentComponentFiles)
894 - {
895 - if (fileRow.File == componentRow.KeyPath)
896 - {
897 - // calculate the key file's canonical target path
898 - string directoryPath = Binder.GetDirectoryPath(directories, componentIdGenSeeds, componentRow.Directory, true);
899 - string fileName = Common.GetName(fileRow.FileName, false, true).ToLower(CultureInfo.InvariantCulture);
900 - path = Path.Combine(directoryPath, fileName);
901 -
902 - // find paths that are not canonicalized
903 - if (path.StartsWith(@"PersonalFolder\my pictures", StringComparison.Ordinal) ||
904 - path.StartsWith(@"ProgramFilesFolder\common files", StringComparison.Ordinal) ||
905 - path.StartsWith(@"ProgramMenuFolder\startup", StringComparison.Ordinal) ||
906 - path.StartsWith("TARGETDIR", StringComparison.Ordinal) ||
907 - path.StartsWith(@"StartMenuFolder\programs", StringComparison.Ordinal) ||
908 - path.StartsWith(@"WindowsFolder\fonts", StringComparison.Ordinal))
909 - {
910 - Messaging.Instance.OnMessage(WixErrors.IllegalPathForGeneratedComponentGuid(componentRow.SourceLineNumbers, fileRow.Component, path));
911 - }
912 -
913 - // if component has more than one file, the key path must be versioned
914 - if (1 < numFilesInComponent && String.IsNullOrEmpty(fileRow.Version))
915 - {
916 - Messaging.Instance.OnMessage(WixErrors.IllegalGeneratedGuidComponentUnversionedKeypath(componentRow.SourceLineNumbers));
917 - }
918 - }
919 - else
920 - {
921 - // not a key path, so it must be an unversioned file if component has more than one file
922 - if (1 < numFilesInComponent && !String.IsNullOrEmpty(fileRow.Version))
923 - {
924 - Messaging.Instance.OnMessage(WixErrors.IllegalGeneratedGuidComponentVersionedNonkeypath(componentRow.SourceLineNumbers));
925 - }
926 - }
927 - }
928 -
929 - // if the rules were followed, reward with a generated guid
930 - if (!Messaging.Instance.EncounteredError)
931 - {
932 - componentRow.Guid = Uuid.NewUuid(BindDatabaseCommand.WixComponentGuidNamespace, path).ToString("B").ToUpperInvariant();
933 - }
934 - }
935 - }
936 - }
937 - }
938 - }
647
648 +#if TODO_FIX_INSTANCE_TRANSFORM
649 /// <summary>
650 /// Creates instance transform substorages in the output.
651 /// </summary>
@@ -1171,6 +880,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
880 }
881 }
882 }
883 +#endif
884
885 /// <summary>
886 /// Validate that there are no duplicate GUIDs in the output.
@@ -1186,7 +896,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
896 {
897 Dictionary<string, bool> componentGuidConditions = new Dictionary<string, bool>(componentTable.Rows.Count);
898
1189 - foreach (ComponentRow row in componentTable.Rows)
899 + foreach (Data.Rows.ComponentRow row in componentTable.Rows)
900 {
901 // we don't care about unmanaged components and if there's a * GUID remaining,
902 // there's already an error that prevented it from being replaced with a real GUID.
@@ -1221,7 +931,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
931 /// <param name="output">Internal representation of the msi database to operate upon.</param>
932 private void UpdateControlText(Output output)
933 {
1224 - UpdateControlTextCommand command = new UpdateControlTextCommand();
934 + var command = new UpdateControlTextCommand();
935 command.BBControlTable = output.Tables["BBControl"];
936 command.WixBBControlTable = output.Tables["WixBBControl"];
937 command.ControlTable = output.Tables["Control"];
@@ -1229,7 +939,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
939 command.Execute();
940 }
941
1232 - private string ResolveMedia(MediaRow mediaRow, string mediaLayoutDirectory, string layoutDirectory)
942 + private string ResolveMedia(MediaTuple mediaRow, string mediaLayoutDirectory, string layoutDirectory)
943 {
944 string layout = null;
945
@@ -1282,7 +992,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind
992 command.TempFilesLocation = this.IntermediateFolder;
993 command.Codepage = this.Codepage;
994 command.Execute();
1285 -#endif
995 }
996 }
997 }
src/WixToolset.Core.WindowsInstaller/Bind/BindSummaryInfoCommand.cs
+92 -86
@@ -1,20 +1,24 @@
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.WindowsInstaller.Databases
3 +namespace WixToolset.Core.WindowsInstaller.Bind
4 {
5 using System;
6 using System.Globalization;
7 + using System.Linq;
8 using WixToolset.Data;
9 + using WixToolset.Data.Tuples;
10
11 /// <summary>
12 /// Binds the summary information table of a database.
13 /// </summary>
14 internal class BindSummaryInfoCommand
15 {
14 - /// <summary>
15 - /// The output to bind.
16 - /// </summary>
17 - public Output Output { private get; set; }
16 + public BindSummaryInfoCommand(IntermediateSection section)
17 + {
18 + this.Section = section;
19 + }
20 +
21 + private IntermediateSection Section { get; }
22
23 /// <summary>
24 /// Returns a flag indicating if files are compressed by default.
@@ -40,95 +44,97 @@ namespace WixToolset.Core.WindowsInstaller.Databases
44 this.InstallerVersion = 0;
45 this.ModularizationGuid = null;
46
43 - Table summaryInformationTable = this.Output.Tables["_SummaryInformation"];
47 + bool foundCreateDataTime = false;
48 + bool foundLastSaveDataTime = false;
49 + bool foundCreatingApplication = false;
50 + string now = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss", CultureInfo.InvariantCulture);
51
45 - if (null != summaryInformationTable)
52 + foreach (var summaryInformationRow in this.Section.Tuples.OfType<_SummaryInformationTuple>())
53 {
47 - bool foundCreateDataTime = false;
48 - bool foundLastSaveDataTime = false;
49 - bool foundCreatingApplication = false;
50 - string now = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss", CultureInfo.InvariantCulture);
51 -
52 - foreach (Row summaryInformationRow in summaryInformationTable.Rows)
54 + switch (summaryInformationRow.PropertyId)
55 {
54 - switch (summaryInformationRow.FieldAsInteger(0))
55 - {
56 - case 1: // PID_CODEPAGE
56 + case 1: // PID_CODEPAGE
57 // make sure the code page is an int and not a web name or null
58 - string codepage = summaryInformationRow.FieldAsString(1);
59 -
60 - if (null == codepage)
61 - {
62 - codepage = "0";
63 - }
64 - else
65 - {
66 - summaryInformationRow[1] = Common.GetValidCodePage(codepage, false, false, summaryInformationRow.SourceLineNumbers).ToString(CultureInfo.InvariantCulture);
67 - }
68 - break;
69 - case 9: // PID_REVNUMBER
70 - string packageCode = (string)summaryInformationRow[1];
71 -
72 - if (OutputType.Module == this.Output.Type)
73 - {
74 - this.ModularizationGuid = packageCode.Substring(1, 36).Replace('-', '_');
75 - }
76 - else if ("*" == packageCode)
77 - {
78 - // set the revision number (package/patch code) if it should be automatically generated
79 - summaryInformationRow[1] = Common.GenerateGuid();
80 - }
81 - break;
82 - case 12: // PID_CREATE_DTM
83 - foundCreateDataTime = true;
84 - break;
85 - case 13: // PID_LASTSAVE_DTM
86 - foundLastSaveDataTime = true;
87 - break;
88 - case 14:
89 - this.InstallerVersion = summaryInformationRow.FieldAsInteger(1);
90 - break;
91 - case 15: // PID_WORDCOUNT
92 - if (OutputType.Patch == this.Output.Type)
93 - {
94 - this.LongNames = true;
95 - this.Compressed = true;
96 - }
97 - else
98 - {
99 - this.LongNames = (0 == (summaryInformationRow.FieldAsInteger(1) & 1));
100 - this.Compressed = (2 == (summaryInformationRow.FieldAsInteger(1) & 2));
101 - }
102 - break;
103 - case 18: // PID_APPNAME
104 - foundCreatingApplication = true;
105 - break;
106 - }
107 - }
58 + var codepage = summaryInformationRow.Value;
59
109 - // add a summary information row for the create time/date property if its not already set
110 - if (!foundCreateDataTime)
111 - {
112 - Row createTimeDateRow = summaryInformationTable.CreateRow(null);
113 - createTimeDateRow[0] = 12;
114 - createTimeDateRow[1] = now;
115 - }
60 + if (String.IsNullOrEmpty(codepage))
61 + {
62 + codepage = "0";
63 + }
64 + else
65 + {
66 + summaryInformationRow.Value = Common.GetValidCodePage(codepage, false, false, summaryInformationRow.SourceLineNumbers).ToString(CultureInfo.InvariantCulture);
67 + }
68 + break;
69 + case 9: // PID_REVNUMBER
70 + var packageCode = summaryInformationRow.Value;
71
117 - // add a summary information row for the last save time/date property if its not already set
118 - if (!foundLastSaveDataTime)
119 - {
120 - Row lastSaveTimeDateRow = summaryInformationTable.CreateRow(null);
121 - lastSaveTimeDateRow[0] = 13;
122 - lastSaveTimeDateRow[1] = now;
72 + if (SectionType.Module == this.Section.Type)
73 + {
74 + this.ModularizationGuid = packageCode.Substring(1, 36).Replace('-', '_');
75 + }
76 + else if ("*" == packageCode)
77 + {
78 + // set the revision number (package/patch code) if it should be automatically generated
79 + summaryInformationRow.Value = Common.GenerateGuid();
80 + }
81 + break;
82 + case 12: // PID_CREATE_DTM
83 + foundCreateDataTime = true;
84 + break;
85 + case 13: // PID_LASTSAVE_DTM
86 + foundLastSaveDataTime = true;
87 + break;
88 + case 14:
89 + this.InstallerVersion = summaryInformationRow[_SummaryInformationTupleFields.Value].AsNumber();
90 + break;
91 + case 15: // PID_WORDCOUNT
92 + if (SectionType.Patch == this.Section.Type)
93 + {
94 + this.LongNames = true;
95 + this.Compressed = true;
96 + }
97 + else
98 + {
99 + var attributes = summaryInformationRow[_SummaryInformationTupleFields.Value].AsNumber();
100 + this.LongNames = (0 == (attributes & 1));
101 + this.Compressed = (2 == (attributes & 2));
102 + }
103 + break;
104 + case 18: // PID_APPNAME
105 + foundCreatingApplication = true;
106 + break;
107 }
108 + }
109
125 - // add a summary information row for the creating application property if its not already set
126 - if (!foundCreatingApplication)
127 - {
128 - Row creatingApplicationRow = summaryInformationTable.CreateRow(null);
129 - creatingApplicationRow[0] = 18;
130 - creatingApplicationRow[1] = String.Format(CultureInfo.InvariantCulture, AppCommon.GetCreatingApplicationString());
131 - }
110 + // add a summary information row for the create time/date property if its not already set
111 + if (!foundCreateDataTime)
112 + {
113 + var createTimeDateRow = new _SummaryInformationTuple(null, new Identifier(12, AccessModifier.Private));
114 + createTimeDateRow.PropertyId = 12;
115 + createTimeDateRow.Value = now;
116 +
117 + this.Section.Tuples.Add(createTimeDateRow);
118 + }
119 +
120 + // add a summary information row for the last save time/date property if its not already set
121 + if (!foundLastSaveDataTime)
122 + {
123 + var lastSaveTimeDateRow = new _SummaryInformationTuple(null, new Identifier(13, AccessModifier.Private));
124 + lastSaveTimeDateRow.PropertyId = 13;
125 + lastSaveTimeDateRow.Value = now;
126 +
127 + this.Section.Tuples.Add(lastSaveTimeDateRow);
128 + }
129 +
130 + // add a summary information row for the creating application property if its not already set
131 + if (!foundCreatingApplication)
132 + {
133 + var creatingApplicationRow = new _SummaryInformationTuple(null, new Identifier(18, AccessModifier.Private));
134 + creatingApplicationRow.PropertyId = 18;
135 + creatingApplicationRow.Value = String.Format(CultureInfo.InvariantCulture, AppCommon.GetCreatingApplicationString());
136 +
137 + this.Section.Tuples.Add(creatingApplicationRow);
138 }
139 }
140 }
src/WixToolset.Core.WindowsInstaller/Bind/BindTransformCommand.cs
+1 -1
@@ -1,6 +1,6 @@
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.WindowsInstaller.Databases
3 +namespace WixToolset.Core.WindowsInstaller.Bind
4 {
5 using System;
6 using System.Collections.Generic;
src/WixToolset.Core.WindowsInstaller/Bind/CabinetBuilder.cs
+1 -1
@@ -1,6 +1,6 @@
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.WindowsInstaller.Databases
3 +namespace WixToolset.Core.WindowsInstaller.Bind
4 {
5 using System;
6 using System.Collections;
src/WixToolset.Core.WindowsInstaller/Bind/CabinetWorkItem.cs
+1 -2
@@ -1,11 +1,10 @@
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.WindowsInstaller.Databases
3 +namespace WixToolset.Core.WindowsInstaller.Bind
4 {
5 using System.Collections.Generic;
6 using WixToolset.Core.Bind;
7 using WixToolset.Data;
8 - using WixToolset.Data.Rows;
8
9 /// <summary>
10 /// A cabinet builder work item.
src/WixToolset.Core.WindowsInstaller/Bind/CalculateComponentGuids.cs new
+174
@@ -0,0 +1,174 @@
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.WindowsInstaller.Bind
4 +{
5 + using System;
6 + using System.Collections.Generic;
7 + using System.IO;
8 + using System.Linq;
9 + using WixToolset.Bind;
10 + using WixToolset.Core.Native;
11 + using WixToolset.Data;
12 + using WixToolset.Data.Tuples;
13 +
14 + /// <summary>
15 + /// Set the guids for components with generatable guids.
16 + /// </summary>
17 + internal class CalculateComponentGuids
18 + {
19 + public CalculateComponentGuids(IntermediateSection section)
20 + {
21 + this.Section = section;
22 + }
23 +
24 + private IntermediateSection Section { get; }
25 +
26 + public void Execute()
27 + {
28 + Dictionary<string, RegistryTuple> registryKeyRows = null;
29 + Dictionary<string, ResolvedDirectory> targetPathsByDirectoryId = null;
30 + Dictionary<string, string> componentIdGenSeeds = null;
31 + Dictionary<string, List<FileTuple>> filesByComponentId = null;
32 +
33 + // Find components with generatable guids.
34 + foreach (var componentRow in this.Section.Tuples.OfType<ComponentTuple>())
35 + {
36 + // Skip components that do not specify generate guid.
37 + if (componentRow.ComponentId != "*")
38 + {
39 + continue;
40 + }
41 +
42 + var odbcDataSourceKeyPath = (componentRow.Attributes & MsiInterop.MsidbComponentAttributesODBCDataSource) != 0;
43 +
44 + if (String.IsNullOrEmpty(componentRow.KeyPath) || odbcDataSourceKeyPath)
45 + {
46 + Messaging.Instance.OnMessage(WixErrors.IllegalComponentWithAutoGeneratedGuid(componentRow.SourceLineNumbers));
47 + continue;
48 + }
49 +
50 + var registryKeyPath = (componentRow.Attributes & MsiInterop.MsidbComponentAttributesRegistryKeyPath) != 0;
51 +
52 + if (registryKeyPath)
53 + {
54 + if (registryKeyRows is null)
55 + {
56 + registryKeyRows = this.Section.Tuples.OfType<RegistryTuple>().ToDictionary(t => t.Registry);
57 + }
58 +
59 + if (registryKeyRows.TryGetValue(componentRow.KeyPath, out var foundRow))
60 + {
61 + var is64Bit = (componentRow.Attributes & MsiInterop.MsidbComponentAttributes64bit) != 0;
62 + var bitness = is64Bit ? "64" : String.Empty;
63 + var regkey = String.Concat(bitness, foundRow[1], "\\", foundRow[2], "\\", foundRow[3]);
64 + componentRow.ComponentId = Uuid.NewUuid(BindDatabaseCommand.WixComponentGuidNamespace, regkey.ToLowerInvariant()).ToString("B").ToUpperInvariant();
65 + }
66 + }
67 + else // must be a File KeyPath.
68 + {
69 + // If the directory table hasn't been loaded into an indexed hash
70 + // of directory ids to target names do that now.
71 + if (targetPathsByDirectoryId is null)
72 + {
73 + var directories = this.Section.Tuples.OfType<DirectoryTuple>().ToList();
74 +
75 + targetPathsByDirectoryId = new Dictionary<string, ResolvedDirectory>(directories.Count);
76 +
77 + // Get the target paths for all directories.
78 + foreach (var row in directories)
79 + {
80 + // If the directory Id already exists, we will skip it here since
81 + // checking for duplicate primary keys is done later when importing tables
82 + // into database
83 + if (targetPathsByDirectoryId.ContainsKey(row.Directory))
84 + {
85 + continue;
86 + }
87 +
88 + var targetName = Common.GetName(row.DefaultDir, false, true);
89 + targetPathsByDirectoryId.Add(row.Directory, new ResolvedDirectory(row.Directory_Parent, targetName));
90 + }
91 + }
92 +
93 + // If the component id generation seeds have not been indexed
94 + // from the WixDirectory table do that now.
95 + if (componentIdGenSeeds is null)
96 + {
97 + // If there are any WixDirectory rows, build up the Component Guid
98 + // generation seeds indexed by Directory/@Id.
99 + componentIdGenSeeds = this.Section.Tuples.OfType<WixDirectoryTuple>()
100 + .Where(t => !String.IsNullOrEmpty(t.ComponentGuidGenerationSeed))
101 + .ToDictionary(t => t.Directory_, t => t.ComponentGuidGenerationSeed);
102 + }
103 +
104 + // if the file rows have not been indexed by File.Component yet
105 + // then do that now
106 + if (filesByComponentId is null)
107 + {
108 + var files = this.Section.Tuples.OfType<FileTuple>().ToList();
109 +
110 + filesByComponentId = new Dictionary<string, List<FileTuple>>(files.Count);
111 +
112 + foreach (var file in files)
113 + {
114 + if (!filesByComponentId.TryGetValue(file.Component_, out var componentFiles))
115 + {
116 + componentFiles = new List<FileTuple>();
117 + filesByComponentId.Add(file.Component_, componentFiles);
118 + }
119 +
120 + componentFiles.Add(file);
121 + }
122 + }
123 +
124 + // validate component meets all the conditions to have a generated guid
125 + var currentComponentFiles = filesByComponentId[componentRow.Component];
126 + var numFilesInComponent = currentComponentFiles.Count;
127 + string path = null;
128 +
129 + foreach (var fileRow in currentComponentFiles)
130 + {
131 + if (fileRow.File == componentRow.KeyPath)
132 + {
133 + // calculate the key file's canonical target path
134 + string directoryPath = Binder.GetDirectoryPath(targetPathsByDirectoryId, componentIdGenSeeds, componentRow.Directory_, true);
135 + string fileName = Common.GetName(fileRow.LongFileName, false, true).ToLowerInvariant();
136 + path = Path.Combine(directoryPath, fileName);
137 +
138 + // find paths that are not canonicalized
139 + if (path.StartsWith(@"PersonalFolder\my pictures", StringComparison.Ordinal) ||
140 + path.StartsWith(@"ProgramFilesFolder\common files", StringComparison.Ordinal) ||
141 + path.StartsWith(@"ProgramMenuFolder\startup", StringComparison.Ordinal) ||
142 + path.StartsWith("TARGETDIR", StringComparison.Ordinal) ||
143 + path.StartsWith(@"StartMenuFolder\programs", StringComparison.Ordinal) ||
144 + path.StartsWith(@"WindowsFolder\fonts", StringComparison.Ordinal))
145 + {
146 + Messaging.Instance.OnMessage(WixErrors.IllegalPathForGeneratedComponentGuid(componentRow.SourceLineNumbers, fileRow.Component_, path));
147 + }
148 +
149 + // if component has more than one file, the key path must be versioned
150 + if (1 < numFilesInComponent && String.IsNullOrEmpty(fileRow.Version))
151 + {
152 + Messaging.Instance.OnMessage(WixErrors.IllegalGeneratedGuidComponentUnversionedKeypath(componentRow.SourceLineNumbers));
153 + }
154 + }
155 + else
156 + {
157 + // not a key path, so it must be an unversioned file if component has more than one file
158 + if (1 < numFilesInComponent && !String.IsNullOrEmpty(fileRow.Version))
159 + {
160 + Messaging.Instance.OnMessage(WixErrors.IllegalGeneratedGuidComponentVersionedNonkeypath(componentRow.SourceLineNumbers));
161 + }
162 + }
163 + }
164 +
165 + // if the rules were followed, reward with a generated guid
166 + if (!Messaging.Instance.EncounteredError)
167 + {
168 + componentRow.ComponentId = Uuid.NewUuid(BindDatabaseCommand.WixComponentGuidNamespace, path).ToString("B").ToUpperInvariant();
169 + }
170 + }
171 + }
172 + }
173 + }
174 +}
src/WixToolset.Core.WindowsInstaller/Bind/ConfigurationCallback.cs
+1 -1
@@ -1,6 +1,6 @@
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.WindowsInstaller.Databases
3 +namespace WixToolset.Core.WindowsInstaller.Bind
4 {
5 using System;
6 using System.Collections;
src/WixToolset.Core.WindowsInstaller/Bind/CopyTransformDataCommand.cs
+4 -3
@@ -1,6 +1,6 @@
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.WindowsInstaller.Databases
3 +namespace WixToolset.Core.WindowsInstaller.Bind
4 {
5 using System;
6 using System.Collections.Generic;
@@ -10,6 +10,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases
10 using WixToolset.Extensibility;
11 using WixToolset.Core.Native;
12 using WixToolset.Core.Bind;
13 + using WixToolset.Data.Tuples;
14
15 internal class CopyTransformDataCommand
16 {
@@ -29,7 +30,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases
30
31 List<FileFacade> allFileRows = this.CopyOutFileRows ? new List<FileFacade>() : null;
32
32 -#if false // TODO: Fix this patching related code to work correctly with FileFacades.
33 +#if REVISIT_FOR_PATCHING // TODO: Fix this patching related code to work correctly with FileFacades.
34 bool copyToPatch = (allFileRows != null);
35 bool copyFromPatch = !copyToPatch;
36
@@ -454,7 +455,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases
455 }
456
457 Row patchAction = iesTable.CreateRow(null);
457 - WixActionRow wixPatchAction = WindowsInstallerStandard.GetStandardActions()[table, "PatchFiles"];
458 + WixActionRow wixPatchAction = WindowsInstallerStandardInternal.GetStandardActionRows()[table, "PatchFiles"];
459 int sequence = wixPatchAction.Sequence;
460 // Test for default sequence value's appropriateness
461 if (seqInstallFiles >= sequence || (0 != seqDuplicateFiles && seqDuplicateFiles <= sequence))
src/WixToolset.Core.WindowsInstaller/Bind/CreateCabinetsCommand.cs
+10 -14
@@ -1,6 +1,6 @@
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.WindowsInstaller.Databases
3 +namespace WixToolset.Core.WindowsInstaller.Bind
4 {
5 using System;
6 using System.Collections.Generic;
@@ -10,10 +10,10 @@ namespace WixToolset.Core.WindowsInstaller.Databases
10 using System.Runtime.InteropServices;
11 using System.Threading;
12 using WixToolset.Core.Bind;
13 - using WixToolset.Core.WindowsInstaller.Bind;
13 using WixToolset.Data;
14 using WixToolset.Data.Bind;
15 using WixToolset.Data.Rows;
16 + using WixToolset.Data.Tuples;
17 using WixToolset.Extensibility;
18
19 /// <summary>
@@ -60,9 +60,9 @@ namespace WixToolset.Core.WindowsInstaller.Databases
60
61 public bool Compressed { private get; set; }
62
63 - public Dictionary<MediaRow, IEnumerable<FileFacade>> FileRowsByCabinet { private get; set; }
63 + public Dictionary<MediaTuple, IEnumerable<FileFacade>> FileRowsByCabinet { private get; set; }
64
65 - public Func<MediaRow, string, string, string> ResolveMedia { private get; set; }
65 + public Func<MediaTuple, string, string, string> ResolveMedia { private get; set; }
66
67 public TableDefinitionCollection TableDefinitions { private get; set; }
68
@@ -77,7 +77,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases
77 /// <returns>The uncompressed file rows.</returns>
78 public void Execute()
79 {
80 - RowDictionary<WixMediaRow> wixMediaRows = new RowDictionary<WixMediaRow>(this.WixMediaTable);
80 + var wixMediaRows = new RowDictionary<WixMediaRow>(this.WixMediaTable);
81
82 this.lastCabinetAddedToMediaTable = new Dictionary<string, string>();
83
@@ -87,22 +87,19 @@ namespace WixToolset.Core.WindowsInstaller.Databases
87 CabinetBuilder cabinetBuilder = new CabinetBuilder(this.CabbingThreadCount, Marshal.GetFunctionPointerForDelegate(this.newCabNamesCallBack));
88
89 // Supply Compile MediaTemplate Attributes to Cabinet Builder
90 - int MaximumCabinetSizeForLargeFileSplitting;
91 - int MaximumUncompressedMediaSize;
92 - this.GetMediaTemplateAttributes(out MaximumCabinetSizeForLargeFileSplitting, out MaximumUncompressedMediaSize);
90 + this.GetMediaTemplateAttributes(out var MaximumCabinetSizeForLargeFileSplitting, out var MaximumUncompressedMediaSize);
91 cabinetBuilder.MaximumCabinetSizeForLargeFileSplitting = MaximumCabinetSizeForLargeFileSplitting;
92 cabinetBuilder.MaximumUncompressedMediaSize = MaximumUncompressedMediaSize;
93
94 foreach (var entry in this.FileRowsByCabinet)
95 {
98 - MediaRow mediaRow = entry.Key;
96 + var mediaRow = entry.Key;
97 IEnumerable<FileFacade> files = entry.Value;
98 CompressionLevel compressionLevel = this.DefaultCompressionLevel;
99
102 - WixMediaRow wixMediaRow = null;
100 string mediaLayoutFolder = null;
101
105 - if (wixMediaRows.TryGetValue(mediaRow.GetKey(), out wixMediaRow))
102 + if (wixMediaRows.TryGetValue(mediaRow.Id.Id, out var wixMediaRow))
103 {
104 mediaLayoutFolder = wixMediaRow.Layout;
105
@@ -185,7 +182,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases
182 /// <param name="fileFacades">Collection of files in this cabinet.</param>
183 /// <param name="fileTransfers">Array of files to be transfered.</param>
184 /// <returns>created CabinetWorkItem object</returns>
188 - private CabinetWorkItem CreateCabinetWorkItem(Output output, string cabinetDir, MediaRow mediaRow, CompressionLevel compressionLevel, IEnumerable<FileFacade> fileFacades, List<FileTransfer> fileTransfers)
185 + private CabinetWorkItem CreateCabinetWorkItem(Output output, string cabinetDir, MediaTuple mediaRow, CompressionLevel compressionLevel, IEnumerable<FileFacade> fileFacades, List<FileTransfer> fileTransfers)
186 {
187 CabinetWorkItem cabinetWorkItem = null;
188 string tempCabinetFileX = Path.Combine(this.TempFilesLocation, mediaRow.Cabinet);
@@ -254,8 +251,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases
251 else
252 {
253 string destinationPath = Path.Combine(cabinetDir, mediaRow.Cabinet);
257 - FileTransfer transfer;
258 - if (FileTransfer.TryCreate(resolvedCabinet.Path, destinationPath, CabinetBuildOption.BuildAndMove == resolvedCabinet.BuildOption, "Cabinet", mediaRow.SourceLineNumbers, out transfer))
254 + if (FileTransfer.TryCreate(resolvedCabinet.Path, destinationPath, CabinetBuildOption.BuildAndMove == resolvedCabinet.BuildOption, "Cabinet", mediaRow.SourceLineNumbers, out var transfer))
255 {
256 transfer.Built = true;
257 fileTransfers.Add(transfer);
src/WixToolset.Core.WindowsInstaller/Bind/CreateDeltaPatchesCommand.cs
+18 -26
@@ -1,6 +1,6 @@
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.WindowsInstaller.Databases
3 +namespace WixToolset.Core.WindowsInstaller.Bind
4 {
5 using System;
6 using System.Collections.Generic;
@@ -9,49 +9,40 @@ namespace WixToolset.Core.WindowsInstaller.Databases
9 using WixToolset.Core.Bind;
10 using WixToolset.Data;
11 using WixToolset.Data.Rows;
12 + using WixToolset.Data.Tuples;
13
14 /// <summary>
15 /// Creates delta patches and updates the appropriate rows to point to the newly generated patches.
16 /// </summary>
17 internal class CreateDeltaPatchesCommand
18 {
18 - public IEnumerable<FileFacade> FileFacades { private get; set; }
19 + public CreateDeltaPatchesCommand(List<FileFacade> fileFacades, string intermediateFolder, WixPatchIdTuple wixPatchId)
20 + {
21 + this.FileFacades = fileFacades;
22 + this.IntermediateFolder = intermediateFolder;
23 + this.WixPatchId = wixPatchId;
24 + }
25
20 - public Table WixPatchIdTable { private get; set; }
26 + private IEnumerable<FileFacade> FileFacades { get; }
27
22 - public string TempFilesLocation { private get; set; }
28 + private WixPatchIdTuple WixPatchId { get; }
29 +
30 + private string IntermediateFolder { get; }
31
32 public void Execute()
33 {
26 -#if REVISIT_FOR_PATCHING
27 - bool optimizePatchSizeForLargeFiles = false;
28 - PatchSymbolFlagsType apiPatchingSymbolFlags = 0;
29 -
30 - if (null != this.WixPatchIdTable)
31 - {
32 - Row row = this.WixPatchIdTable.Rows[0];
33 - if (null != row)
34 - {
35 - if (null != row[2])
36 - {
37 - optimizePatchSizeForLargeFiles = (1 == Convert.ToUInt32(row[2], CultureInfo.InvariantCulture));
38 - }
39 -
40 - if (null != row[3])
41 - {
42 - apiPatchingSymbolFlags = (PatchSymbolFlagsType)Convert.ToUInt32(row[3], CultureInfo.InvariantCulture);
43 - }
44 - }
45 - }
34 + var optimizePatchSizeForLargeFiles = this.WixPatchId?.OptimizePatchSizeForLargeFiles ?? false;
35 + var apiPatchingSymbolFlags = (PatchSymbolFlagsType)(this.WixPatchId?.ApiPatchingSymbolFlags ?? 0);
36
37 +#if REVISIT_FOR_PATCHING
38 foreach (FileFacade facade in this.FileFacades)
39 {
40 if (RowOperation.Modify == facade.File.Operation &&
41 0 != (facade.WixFile.PatchAttributes & PatchAttributeType.IncludeWholeFile))
42 {
43 string deltaBase = String.Concat("delta_", facade.File.File);
53 - string deltaFile = Path.Combine(this.TempFilesLocation, String.Concat(deltaBase, ".dpf"));
54 - string headerFile = Path.Combine(this.TempFilesLocation, String.Concat(deltaBase, ".phd"));
44 + string deltaFile = Path.Combine(this.IntermediateFolder, String.Concat(deltaBase, ".dpf"));
45 + string headerFile = Path.Combine(this.IntermediateFolder, String.Concat(deltaBase, ".phd"));
46
47 bool retainRangeWarning = false;
48
@@ -84,6 +75,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases
75 }
76 }
77 #endif
78 +
79 throw new NotImplementedException();
80 }
81 }
src/WixToolset.Core.WindowsInstaller/Bind/CreateOutputFromIRCommand.cs new
+230
@@ -0,0 +1,230 @@
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.WindowsInstaller.Bind
4 +{
5 + using System;
6 + using System.Linq;
7 + using WixToolset.Core.Native;
8 + using WixToolset.Data;
9 + using WixToolset.Data.Rows;
10 + using WixToolset.Data.Tuples;
11 +
12 + internal class CreateOutputFromIRCommand
13 + {
14 + public CreateOutputFromIRCommand(IntermediateSection section, TableDefinitionCollection tableDefinitions)
15 + {
16 + this.Section = section;
17 + this.TableDefinitions = tableDefinitions;
18 + }
19 +
20 + private TableDefinitionCollection TableDefinitions { get; }
21 +
22 + private IntermediateSection Section { get; }
23 +
24 + public Output Output { get; private set; }
25 +
26 + public void Execute()
27 + {
28 + var output = new Output(this.Section.Tuples.First().SourceLineNumbers);
29 + output.Codepage = this.Section.Codepage;
30 + output.Type = SectionTypeToOutputType(this.Section.Type);
31 +
32 + this.AddSectionToOutput(this.Section, output);
33 +
34 + this.Output = output;
35 + }
36 +
37 + private void AddSectionToOutput(IntermediateSection section, Output output)
38 + {
39 + foreach (var tuple in section.Tuples)
40 + {
41 + switch (tuple.Definition.Type)
42 + {
43 + case TupleDefinitionType.File:
44 + this.AddFileTuple((FileTuple)tuple, output);
45 + break;
46 +
47 + case TupleDefinitionType.WixAction:
48 + this.AddWixActionTuple((WixActionTuple)tuple, output);
49 + break;
50 +
51 + default:
52 + this.AddTupleDefaultly(tuple, output);
53 + break;
54 + }
55 + }
56 + }
57 +
58 + private void AddFileTuple(FileTuple tuple, Output output)
59 + {
60 + var table = output.EnsureTable(this.TableDefinitions["File"]);
61 + var row = (FileRow)table.CreateRow(tuple.SourceLineNumbers);
62 + row.File = tuple.File;
63 + row.Component = tuple.Component_;
64 + row.FileName = GetMsiFilenameValue(tuple.ShortFileName, tuple.LongFileName);
65 + row.FileSize = tuple.FileSize;
66 + row.Version = tuple.Version;
67 + row.Language = tuple.Language;
68 +
69 + var attributes = tuple.Checksum ? MsiInterop.MsidbFileAttributesChecksum : 0;
70 + attributes |= (tuple.Compressed.HasValue && tuple.Compressed.Value) ? MsiInterop.MsidbFileAttributesCompressed : 0;
71 + attributes |= (tuple.Compressed.HasValue && !tuple.Compressed.Value) ? MsiInterop.MsidbFileAttributesNoncompressed : 0;
72 + attributes |= tuple.Hidden ? MsiInterop.MsidbFileAttributesHidden : 0;
73 + attributes |= tuple.ReadOnly ? MsiInterop.MsidbFileAttributesReadOnly : 0;
74 + attributes |= tuple.System ? MsiInterop.MsidbFileAttributesSystem : 0;
75 + attributes |= tuple.Vital ? MsiInterop.MsidbFileAttributesVital : 0;
76 + row.Attributes = attributes;
77 + }
78 +
79 + private void AddWixActionTuple(WixActionTuple actionRow, Output output)
80 + {
81 + // Get the table definition for the action (and ensure the proper table exists for a module).
82 + TableDefinition sequenceTableDefinition = null;
83 + switch (actionRow.SequenceTable)
84 + {
85 + case SequenceTable.AdminExecuteSequence:
86 + if (OutputType.Module == output.Type)
87 + {
88 + output.EnsureTable(this.TableDefinitions["AdminExecuteSequence"]);
89 + sequenceTableDefinition = this.TableDefinitions["ModuleAdminExecuteSequence"];
90 + }
91 + else
92 + {
93 + sequenceTableDefinition = this.TableDefinitions["AdminExecuteSequence"];
94 + }
95 + break;
96 + case SequenceTable.AdminUISequence:
97 + if (OutputType.Module == output.Type)
98 + {
99 + output.EnsureTable(this.TableDefinitions["AdminUISequence"]);
100 + sequenceTableDefinition = this.TableDefinitions["ModuleAdminUISequence"];
101 + }
102 + else
103 + {
104 + sequenceTableDefinition = this.TableDefinitions["AdminUISequence"];
105 + }
106 + break;
107 + case SequenceTable.AdvtExecuteSequence:
108 + if (OutputType.Module == output.Type)
109 + {
110 + output.EnsureTable(this.TableDefinitions["AdvtExecuteSequence"]);
111 + sequenceTableDefinition = this.TableDefinitions["ModuleAdvtExecuteSequence"];
112 + }
113 + else
114 + {
115 + sequenceTableDefinition = this.TableDefinitions["AdvtExecuteSequence"];
116 + }
117 + break;
118 + case SequenceTable.InstallExecuteSequence:
119 + if (OutputType.Module == output.Type)
120 + {
121 + output.EnsureTable(this.TableDefinitions["InstallExecuteSequence"]);
122 + sequenceTableDefinition = this.TableDefinitions["ModuleInstallExecuteSequence"];
123 + }
124 + else
125 + {
126 + sequenceTableDefinition = this.TableDefinitions["InstallExecuteSequence"];
127 + }
128 + break;
129 + case SequenceTable.InstallUISequence:
130 + if (OutputType.Module == output.Type)
131 + {
132 + output.EnsureTable(this.TableDefinitions["InstallUISequence"]);
133 + sequenceTableDefinition = this.TableDefinitions["ModuleInstallUISequence"];
134 + }
135 + else
136 + {
137 + sequenceTableDefinition = this.TableDefinitions["InstallUISequence"];
138 + }
139 + break;
140 + }
141 +
142 + // create the action sequence row in the output
143 + var sequenceTable = output.EnsureTable(sequenceTableDefinition);
144 + var row = sequenceTable.CreateRow(actionRow.SourceLineNumbers);
145 +
146 + if (SectionType.Module == this.Section.Type)
147 + {
148 + row[0] = actionRow.Action;
149 + if (0 != actionRow.Sequence)
150 + {
151 + row[1] = actionRow.Sequence;
152 + }
153 + else
154 + {
155 + bool after = (null == actionRow.Before);
156 + row[2] = after ? actionRow.After : actionRow.Before;
157 + row[3] = after ? 1 : 0;
158 + }
159 + row[4] = actionRow.Condition;
160 + }
161 + else
162 + {
163 + row[0] = actionRow.Action;
164 + row[1] = actionRow.Condition;
165 + row[2] = actionRow.Sequence;
166 + }
167 + }
168 +
169 + private void AddTupleDefaultly(IntermediateTuple tuple, Output output)
170 + {
171 + if (!this.TableDefinitions.TryGet(tuple.Definition.Name, out var tableDefinition))
172 + {
173 + return;
174 + }
175 +
176 + var table = output.EnsureTable(tableDefinition);
177 + var row = table.CreateRow(tuple.SourceLineNumbers);
178 + for (var i = 0; i < tuple.Fields.Length; ++i)
179 + {
180 + if (i < tableDefinition.Columns.Count)
181 + {
182 + var column = tableDefinition.Columns[i];
183 +
184 + switch (column.Type)
185 + {
186 + case ColumnType.Number:
187 + row[i] = tuple.AsNumber(i);
188 + break;
189 +
190 + default:
191 + row[i] = tuple.AsString(i);
192 + break;
193 + }
194 + }
195 + }
196 + }
197 +
198 + private static OutputType SectionTypeToOutputType(SectionType type)
199 + {
200 + switch (type)
201 + {
202 + case SectionType.Bundle:
203 + return OutputType.Bundle;
204 + case SectionType.Module:
205 + return OutputType.Module;
206 + case SectionType.Product:
207 + return OutputType.Product;
208 + case SectionType.PatchCreation:
209 + return OutputType.PatchCreation;
210 + case SectionType.Patch:
211 + return OutputType.Patch;
212 +
213 + default:
214 + throw new ArgumentOutOfRangeException(nameof(type));
215 + }
216 + }
217 +
218 + private static string GetMsiFilenameValue(string shortName, string longName)
219 + {
220 + if (String.IsNullOrEmpty(shortName))
221 + {
222 + return longName;
223 + }
224 + else
225 + {
226 + return shortName + "|" + longName;
227 + }
228 + }
229 + }
230 +}
src/WixToolset.Core.WindowsInstaller/Bind/CreateSpecialPropertiesCommand.cs
+46 -41
@@ -1,67 +1,72 @@
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.WindowsInstaller.Databases
3 +namespace WixToolset.Core.WindowsInstaller.Bind
4 {
5 using System;
6 using System.Collections.Generic;
7 + using System.Linq;
8 using WixToolset.Data;
8 - using WixToolset.Data.Rows;
9 + using WixToolset.Data.Tuples;
10
11 internal class CreateSpecialPropertiesCommand
12 {
12 - public Table PropertyTable { private get; set; }
13 + public CreateSpecialPropertiesCommand(IntermediateSection section)
14 + {
15 + this.Section = section;
16 + }
17
14 - public Table WixPropertyTable { private get; set; }
18 + private IntermediateSection Section { get; }
19
20 public void Execute()
21 {
18 - // Create the special properties.
19 - if (null != this.WixPropertyTable)
20 - {
21 - // Create lists of the properties that contribute to the special lists of properties.
22 - SortedSet<string> adminProperties = new SortedSet<string>();
23 - SortedSet<string> secureProperties = new SortedSet<string>();
24 - SortedSet<string> hiddenProperties = new SortedSet<string>();
22 + // Create lists of the properties that contribute to the special lists of properties.
23 + SortedSet<string> adminProperties = new SortedSet<string>();
24 + SortedSet<string> secureProperties = new SortedSet<string>();
25 + SortedSet<string> hiddenProperties = new SortedSet<string>();
26
26 - foreach (WixPropertyRow wixPropertyRow in this.WixPropertyTable.Rows)
27 + foreach (var wixPropertyRow in this.Section.Tuples.OfType<WixPropertyTuple>())
28 + {
29 + if (wixPropertyRow.Admin)
30 {
28 - if (wixPropertyRow.Admin)
29 - {
30 - adminProperties.Add(wixPropertyRow.Id);
31 - }
32 -
33 - if (wixPropertyRow.Hidden)
34 - {
35 - hiddenProperties.Add(wixPropertyRow.Id);
36 - }
37 -
38 - if (wixPropertyRow.Secure)
39 - {
40 - secureProperties.Add(wixPropertyRow.Id);
41 - }
31 + adminProperties.Add(wixPropertyRow.Property_);
32 }
33
44 - Table propertyTable = this.PropertyTable;
45 - if (0 < adminProperties.Count)
34 + if (wixPropertyRow.Hidden)
35 {
47 - PropertyRow row = (PropertyRow)propertyTable.CreateRow(null);
48 - row.Property = "AdminProperties";
49 - row.Value = String.Join(";", adminProperties);
36 + hiddenProperties.Add(wixPropertyRow.Property_);
37 }
38
52 - if (0 < secureProperties.Count)
39 + if (wixPropertyRow.Secure)
40 {
54 - PropertyRow row = (PropertyRow)propertyTable.CreateRow(null);
55 - row.Property = "SecureCustomProperties";
56 - row.Value = String.Join(";", secureProperties);
41 + secureProperties.Add(wixPropertyRow.Property_);
42 }
43 + }
44
59 - if (0 < hiddenProperties.Count)
60 - {
61 - PropertyRow row = (PropertyRow)propertyTable.CreateRow(null);
62 - row.Property = "MsiHiddenProperties";
63 - row.Value = String.Join(";", hiddenProperties);
64 - }
45 + if (0 < adminProperties.Count)
46 + {
47 + var tuple = new PropertyTuple(null, new Identifier("AdminProperties", AccessModifier.Private));
48 + tuple.Property = "AdminProperties";
49 + tuple.Value = String.Join(";", adminProperties);
50 +
51 + this.Section.Tuples.Add(tuple);
52 + }
53 +
54 + if (0 < secureProperties.Count)
55 + {
56 + var tuple = new PropertyTuple(null, new Identifier("SecureCustomProperties", AccessModifier.Private));
57 + tuple.Property = "SecureCustomProperties";
58 + tuple.Value = String.Join(";", secureProperties);
59 +
60 + this.Section.Tuples.Add(tuple);
61 + }
62 +
63 + if (0 < hiddenProperties.Count)
64 + {
65 + var tuple = new PropertyTuple(null, new Identifier("MsiHiddenProperties", AccessModifier.Private));
66 + tuple.Property = "MsiHiddenProperties";
67 + tuple.Value = String.Join(";", hiddenProperties);
68 +
69 + this.Section.Tuples.Add(tuple);
70 }
71 }
72 }
src/WixToolset.Core.WindowsInstaller/Bind/ExtractMergeModuleFilesCommand.cs
+27 -24
@@ -1,6 +1,6 @@
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.WindowsInstaller.Databases
3 +namespace WixToolset.Core.WindowsInstaller.Bind
4 {
5 using System;
6 using System.Collections.Generic;
@@ -10,7 +10,6 @@ namespace WixToolset.Core.WindowsInstaller.Databases
10 using System.Linq;
11 using System.Runtime.InteropServices;
12 using WixToolset.Data;
13 - using WixToolset.Data.Rows;
13 using WixToolset.MergeMod;
14 using WixToolset.Msi;
15 using WixToolset.Core.Native;
@@ -23,13 +22,17 @@ namespace WixToolset.Core.WindowsInstaller.Databases
22 /// </summary>
23 internal class ExtractMergeModuleFilesCommand
24 {
26 - public IEnumerable<FileFacade> FileFacades { private get; set; }
25 + public ExtractMergeModuleFilesCommand(IntermediateSection section, List<WixMergeTuple> wixMergeTuples)
26 + {
27 + this.Section = section;
28 + this.WixMergeTuples = wixMergeTuples;
29 + }
30
28 - public Table FileTable { private get; set; }
31 + private IntermediateSection Section { get; }
32
30 - public Table WixFileTable { private get; set; }
33 + private List<WixMergeTuple> WixMergeTuples { get; }
34
32 - public Table WixMergeTable { private get; set; }
35 + public IEnumerable<FileFacade> FileFacades { private get; set; }
36
37 public int OutputInstallerVersion { private get; set; }
38
@@ -41,7 +44,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases
44
45 public void Execute()
46 {
44 - List<FileFacade> mergeModulesFileFacades = new List<FileFacade>();
47 + var mergeModulesFileFacades = new List<FileFacade>();
48
49 IMsmMerge2 merge = MsmInterop.GetMsmMerge();
50
@@ -52,9 +55,9 @@ namespace WixToolset.Core.WindowsInstaller.Databases
55 // Now since Merge Modules are already slow and generally less desirable than .wixlibs we'll let
56 // this case be slightly more expensive because the cost of maintaining an indexed file row collection
57 // is a lot more costly for the common cases.
55 - Dictionary<string, FileFacade> indexedFileFacades = this.FileFacades.ToDictionary(f => f.File.File, StringComparer.Ordinal);
58 + var indexedFileFacades = this.FileFacades.ToDictionary(f => f.File.File, StringComparer.Ordinal);
59
57 - foreach (WixMergeRow wixMergeRow in this.WixMergeTable.Rows)
60 + foreach (var wixMergeRow in this.WixMergeTuples)
61 {
62 bool containsFiles = this.CreateFacadesForMergeModuleFiles(wixMergeRow, mergeModulesFileFacades, indexedFileFacades);
63
@@ -68,7 +71,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases
71 this.MergeModulesFileFacades = mergeModulesFileFacades;
72 }
73
71 - private bool CreateFacadesForMergeModuleFiles(WixMergeRow wixMergeRow, List<FileFacade> mergeModulesFileFacades, Dictionary<string, FileFacade> indexedFileFacades)
74 + private bool CreateFacadesForMergeModuleFiles(WixMergeTuple wixMergeRow, List<FileFacade> mergeModulesFileFacades, Dictionary<string, FileFacade> indexedFileFacades)
75 {
76 bool containsFiles = false;
77
@@ -98,7 +101,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases
101 // rows are created by merging in the actual modules.
102 var fileRow = new FileTuple(wixMergeRow.SourceLineNumbers, new Identifier(record[1], AccessModifier.Private));
103 fileRow.File = record[1];
101 - fileRow.Compressed = (wixMergeRow.FileCompression == YesNoType.Yes) ? true : (wixMergeRow.FileCompression == YesNoType.No) ? (bool?)false : null;
104 + fileRow.Compressed = wixMergeRow.FileCompression;
105 //FileRow fileRow = (FileRow)this.FileTable.CreateRow(wixMergeRow.SourceLineNumbers, false);
106 //fileRow.File = record[1];
107 //fileRow.Compressed = wixMergeRow.FileCompression;
@@ -107,7 +110,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases
110 wixFileRow.Directory_ = record[2];
111 wixFileRow.DiskId = wixMergeRow.DiskId;
112 wixFileRow.PatchGroup = -1;
110 - wixFileRow.Source = Path.Combine(this.IntermediateFolder, "MergeId.", wixMergeRow.Number.ToString(CultureInfo.InvariantCulture), record[1]);
113 + wixFileRow.Source = Path.Combine(this.IntermediateFolder, wixMergeRow.Id.Id, record[1]);
114 //WixFileRow wixFileRow = (WixFileRow)this.WixFileTable.CreateRow(wixMergeRow.SourceLineNumbers, false);
115 //wixFileRow.Directory = record[2];
116 //wixFileRow.DiskId = wixMergeRow.DiskId;
@@ -119,11 +122,11 @@ namespace WixToolset.Core.WindowsInstaller.Databases
122 // If case-sensitive collision with another merge module or a user-authored file identifier.
123 if (indexedFileFacades.TryGetValue(mergeModuleFileFacade.File.File, out var collidingFacade))
124 {
122 - Messaging.Instance.OnMessage(WixErrors.DuplicateModuleFileIdentifier(wixMergeRow.SourceLineNumbers, wixMergeRow.Id, collidingFacade.File.File));
125 + Messaging.Instance.OnMessage(WixErrors.DuplicateModuleFileIdentifier(wixMergeRow.SourceLineNumbers, wixMergeRow.Id.Id, collidingFacade.File.File));
126 }
127 else if (uniqueModuleFileIdentifiers.TryGetValue(mergeModuleFileFacade.File.File, out collidingFacade)) // case-insensitive collision with another file identifier in the same merge module
128 {
126 - Messaging.Instance.OnMessage(WixErrors.DuplicateModuleCaseInsensitiveFileIdentifier(wixMergeRow.SourceLineNumbers, wixMergeRow.Id, mergeModuleFileFacade.File.File, collidingFacade.File.File));
129 + Messaging.Instance.OnMessage(WixErrors.DuplicateModuleCaseInsensitiveFileIdentifier(wixMergeRow.SourceLineNumbers, wixMergeRow.Id.Id, mergeModuleFileFacade.File.File, collidingFacade.File.File));
130 }
131 else // no collision
132 {
@@ -150,12 +153,12 @@ namespace WixToolset.Core.WindowsInstaller.Databases
153 int moduleInstallerVersion = Convert.ToInt32(moduleInstallerVersionString, CultureInfo.InvariantCulture);
154 if (moduleInstallerVersion > this.OutputInstallerVersion)
155 {
153 - Messaging.Instance.OnMessage(WixWarnings.InvalidHigherInstallerVersionInModule(wixMergeRow.SourceLineNumbers, wixMergeRow.Id, moduleInstallerVersion, this.OutputInstallerVersion));
156 + Messaging.Instance.OnMessage(WixWarnings.InvalidHigherInstallerVersionInModule(wixMergeRow.SourceLineNumbers, wixMergeRow.Id.Id, moduleInstallerVersion, this.OutputInstallerVersion));
157 }
158 }
159 catch (FormatException)
160 {
158 - throw new WixException(WixErrors.MissingOrInvalidModuleInstallerVersion(wixMergeRow.SourceLineNumbers, wixMergeRow.Id, wixMergeRow.SourceFile, moduleInstallerVersionString));
161 + throw new WixException(WixErrors.MissingOrInvalidModuleInstallerVersion(wixMergeRow.SourceLineNumbers, wixMergeRow.Id.Id, wixMergeRow.SourceFile, moduleInstallerVersionString));
162 }
163 }
164 }
@@ -166,24 +169,26 @@ namespace WixToolset.Core.WindowsInstaller.Databases
169 }
170 catch (Win32Exception)
171 {
169 - throw new WixException(WixErrors.CannotOpenMergeModule(wixMergeRow.SourceLineNumbers, wixMergeRow.Id, wixMergeRow.SourceFile));
172 + throw new WixException(WixErrors.CannotOpenMergeModule(wixMergeRow.SourceLineNumbers, wixMergeRow.Id.Id, wixMergeRow.SourceFile));
173 }
174
175 return containsFiles;
176 }
177
175 - private void ExtractFilesFromMergeModule(IMsmMerge2 merge, WixMergeRow wixMergeRow)
178 + private void ExtractFilesFromMergeModule(IMsmMerge2 merge, WixMergeTuple wixMergeRow)
179 {
180 bool moduleOpen = false;
181 short mergeLanguage;
182
183 + var mergeId = wixMergeRow.Id.Id;
184 +
185 try
186 {
187 mergeLanguage = Convert.ToInt16(wixMergeRow.Language, CultureInfo.InvariantCulture);
188 }
184 - catch (System.FormatException)
189 + catch (FormatException)
190 {
186 - Messaging.Instance.OnMessage(WixErrors.InvalidMergeLanguage(wixMergeRow.SourceLineNumbers, wixMergeRow.Id, wixMergeRow.Language));
191 + Messaging.Instance.OnMessage(WixErrors.InvalidMergeLanguage(wixMergeRow.SourceLineNumbers, mergeId, wixMergeRow.Language.ToString()));
192 return;
193 }
194
@@ -192,13 +197,11 @@ namespace WixToolset.Core.WindowsInstaller.Databases
197 merge.OpenModule(wixMergeRow.SourceFile, mergeLanguage);
198 moduleOpen = true;
199
195 - string safeMergeId = wixMergeRow.Number.ToString(CultureInfo.InvariantCulture.NumberFormat);
196 -
200 // extract the module cabinet, then explode all of the files to a temp directory
198 - string moduleCabPath = String.Concat(this.IntermediateFolder, Path.DirectorySeparatorChar, safeMergeId, ".module.cab");
201 + string moduleCabPath = Path.Combine(this.IntermediateFolder, mergeId + ".cab");
202 merge.ExtractCAB(moduleCabPath);
203
201 - string mergeIdPath = String.Concat(this.IntermediateFolder, Path.DirectorySeparatorChar, "MergeId.", safeMergeId);
204 + string mergeIdPath = Path.Combine(this.IntermediateFolder, mergeId);
205 Directory.CreateDirectory(mergeIdPath);
206
207 using (var extractCab = new WixExtractCab())
src/WixToolset.Core.WindowsInstaller/Bind/GenerateDatabaseCommand.cs
+1 -1
@@ -1,6 +1,6 @@
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.WindowsInstaller.Databases
3 +namespace WixToolset.Core.WindowsInstaller.Bind
4 {
5 using System;
6 using System.Collections.Generic;
src/WixToolset.Core.WindowsInstaller/Bind/GetFileFacadesCommand.cs
+27 -34
@@ -1,6 +1,6 @@
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.WindowsInstaller.Databases
3 +namespace WixToolset.Core.WindowsInstaller.Bind
4 {
5 using System;
6 using System.Collections.Generic;
@@ -8,57 +8,50 @@ namespace WixToolset.Core.WindowsInstaller.Databases
8 using System.Linq;
9 using WixToolset.Core.Bind;
10 using WixToolset.Data;
11 - using WixToolset.Data.Rows;
11 + using WixToolset.Data.Tuples;
12
13 internal class GetFileFacadesCommand
14 {
15 - public Table FileTable { private get; set; }
16 -
17 - public Table WixFileTable { private get; set; }
18 -
19 - public Table WixDeltaPatchFileTable { private get; set; }
15 + public GetFileFacadesCommand(IntermediateSection section)
16 + {
17 + this.Section = section;
18 + }
19
21 - public Table WixDeltaPatchSymbolPathsTable { private get; set; }
20 + private IntermediateSection Section { get; }
21
22 public List<FileFacade> FileFacades { get; private set; }
23
24 public void Execute()
25 {
27 - throw new NotImplementedException();
28 -#if TODO
29 - List<FileFacade> facades = new List<FileFacade>(this.FileTable.Rows.Count);
26 + var facades = new List<FileFacade>();
27
31 - RowDictionary<WixFileRow> wixFiles = new RowDictionary<WixFileRow>(this.WixFileTable);
32 - RowDictionary<WixDeltaPatchFileRow> deltaPatchFiles = new RowDictionary<WixDeltaPatchFileRow>(this.WixDeltaPatchFileTable);
28 + var wixFiles = this.Section.Tuples.OfType<WixFileTuple>().ToDictionary(t => t.File_);
29 + var deltaPatchFiles = this.Section.Tuples.OfType<WixDeltaPatchFileTuple>().ToDictionary(t => t.File_);
30
34 - foreach (FileRow file in this.FileTable.Rows)
31 + foreach (var file in this.Section.Tuples.OfType<FileTuple>())
32 {
36 - WixDeltaPatchFileRow deltaPatchFile = null;
33 + var wixFile = wixFiles[file.File];
34
38 - deltaPatchFiles.TryGetValue(file.File, out deltaPatchFile);
35 + deltaPatchFiles.TryGetValue(file.File, out var deltaPatchFile);
36
40 - facades.Add(new FileFacade(file, wixFiles[file.File], deltaPatchFile));
37 + facades.Add(new FileFacade(file, wixFile, deltaPatchFile));
38 }
39
43 - if (null != this.WixDeltaPatchSymbolPathsTable)
44 - {
45 - this.ResolveDeltaPatchSymbolPaths(deltaPatchFiles, facades);
46 - }
40 + this.ResolveDeltaPatchSymbolPaths(deltaPatchFiles, facades);
41
42 this.FileFacades = facades;
49 -#endif
43 }
44
45 /// <summary>
46 /// Merge data from the WixPatchSymbolPaths rows into the WixDeltaPatchFile rows.
47 /// </summary>
55 - public RowDictionary<WixDeltaPatchFileRow> ResolveDeltaPatchSymbolPaths(RowDictionary<WixDeltaPatchFileRow> deltaPatchFiles, IEnumerable<FileFacade> facades)
48 + public void ResolveDeltaPatchSymbolPaths(Dictionary<string, WixDeltaPatchFileTuple> deltaPatchFiles, IEnumerable<FileFacade> facades)
49 {
50 ILookup<string, FileFacade> filesByComponent = null;
51 ILookup<string, FileFacade> filesByDirectory = null;
52 ILookup<string, FileFacade> filesByDiskId = null;
53
61 - foreach (WixDeltaPatchSymbolPathsRow row in this.WixDeltaPatchSymbolPathsTable.RowsAs<WixDeltaPatchSymbolPathsRow>().OrderBy(r => r.Type))
54 + foreach (var row in this.Section.Tuples.OfType<WixDeltaPatchSymbolPathsTuple>().OrderBy(r => r.Type))
55 {
56 switch (row.Type)
57 {
@@ -72,7 +65,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases
65 filesByComponent = facades.ToLookup(f => f.File.Component_);
66 }
67
75 - foreach (FileFacade facade in filesByComponent[row.Id])
68 + foreach (var facade in filesByComponent[row.Id])
69 {
70 this.MergeSymbolPaths(row, deltaPatchFiles[facade.File.File]);
71 }
@@ -84,7 +77,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases
77 filesByDirectory = facades.ToLookup(f => f.WixFile.Directory_);
78 }
79
87 - foreach (FileFacade facade in filesByDirectory[row.Id])
80 + foreach (var facade in filesByDirectory[row.Id])
81 {
82 this.MergeSymbolPaths(row, deltaPatchFiles[facade.File.File]);
83 }
@@ -96,14 +89,14 @@ namespace WixToolset.Core.WindowsInstaller.Databases
89 filesByDiskId = facades.ToLookup(f => f.WixFile.DiskId.ToString(CultureInfo.InvariantCulture));
90 }
91
99 - foreach (FileFacade facade in filesByDiskId[row.Id])
92 + foreach (var facade in filesByDiskId[row.Id])
93 {
94 this.MergeSymbolPaths(row, deltaPatchFiles[facade.File.File]);
95 }
96 break;
97
98 case SymbolPathType.Product:
106 - foreach (WixDeltaPatchFileRow fileRow in deltaPatchFiles.Values)
99 + foreach (var fileRow in deltaPatchFiles.Values)
100 {
101 this.MergeSymbolPaths(row, fileRow);
102 }
@@ -114,8 +107,6 @@ namespace WixToolset.Core.WindowsInstaller.Databases
107 break;
108 }
109 }
117 -
118 - return deltaPatchFiles;
110 }
111
112 /// <summary>
@@ -124,17 +115,18 @@ namespace WixToolset.Core.WindowsInstaller.Databases
115 /// <param name="row">Row from the WixPatchSymbolsPaths table.</param>
116 /// <param name="file">FileRow into which to set symbol information.</param>
117 /// <comment>This includes PreviousData as well.</comment>
127 - private void MergeSymbolPaths(WixDeltaPatchSymbolPathsRow row, WixDeltaPatchFileRow file)
118 + private void MergeSymbolPaths(WixDeltaPatchSymbolPathsTuple row, WixDeltaPatchFileTuple file)
119 {
129 - if (null == file.Symbols)
120 + if (file.SymbolPaths is null)
121 {
131 - file.Symbols = row.SymbolPaths;
122 + file.SymbolPaths = row.SymbolPaths;
123 }
124 else
125 {
135 - file.Symbols = String.Concat(file.Symbols, ";", row.SymbolPaths);
126 + file.SymbolPaths = String.Concat(file.SymbolPaths, ";", row.SymbolPaths);
127 }
128
129 +#if REVISIT_FOR_PATCHING
130 Field field = row.Fields[2];
131 if (null != field.PreviousData)
132 {
@@ -147,6 +139,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases
139 file.PreviousSymbols = String.Concat(file.PreviousSymbols, ";", field.PreviousData);
140 }
141 }
142 +#endif
143 }
144 }
145 }
src/WixToolset.Core.WindowsInstaller/Bind/MergeModulesCommand.cs
+10 -22
@@ -1,20 +1,13 @@
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.WindowsInstaller.Databases
3 +namespace WixToolset.Core.WindowsInstaller.Bind
4 {
5 using System;
6 using System.Collections.Generic;
7 - using System.Collections.Specialized;
8 - using System.ComponentModel;
9 - using System.Diagnostics;
7 using System.Globalization;
8 using System.IO;
12 - using System.Linq;
9 using System.Runtime.InteropServices;
10 using System.Text;
15 - using System.Xml;
16 - using System.Xml.XPath;
17 - using WixToolset.Clr.Interop;
11 using WixToolset.Data;
12 using WixToolset.Data.Rows;
13 using WixToolset.MergeMod;
@@ -35,12 +28,10 @@ namespace WixToolset.Core.WindowsInstaller.Databases
28
29 public IEnumerable<string> SuppressedTableNames { private get; set; }
30
38 - public string TempFilesLocation { private get; set; }
31 + public string IntermediateFolder { private get; set; }
32
33 public void Execute()
34 {
42 - Debug.Assert(OutputType.Product == this.Output.Type);
43 -
35 Table wixMergeTable = this.Output.Tables["WixMerge"];
36 Table wixFeatureModulesTable = this.Output.Tables["WixFeatureModules"];
37
@@ -59,7 +50,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases
50 {
51 merge = MsmInterop.GetMsmMerge();
52
62 - logPath = Path.Combine(this.TempFilesLocation, "merge.log");
53 + logPath = Path.Combine(this.IntermediateFolder, "merge.log");
54 merge.OpenLog(logPath);
55 logOpen = true;
56
@@ -79,7 +70,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases
70 {
71 mergeLanguage = Convert.ToInt16(wixMergeRow.Language, CultureInfo.InvariantCulture);
72 }
82 - catch (System.FormatException)
73 + catch (FormatException)
74 {
75 Messaging.Instance.OnMessage(WixErrors.InvalidMergeLanguage(wixMergeRow.SourceLineNumbers, wixMergeRow.Id, wixMergeRow.Language));
76 continue;
@@ -284,7 +275,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases
275 Messaging.Instance.OnMessage(WixVerboses.ResequencingMergeModuleFiles());
276 using (View view = db.OpenView("SELECT `Sequence`, `Attributes` FROM `File` WHERE `File`=?"))
277 {
287 - foreach (FileFacade file in this.FileFacades)
278 + foreach (var file in this.FileFacades)
279 {
280 if (!file.FromModule)
281 {
@@ -307,32 +298,29 @@ namespace WixToolset.Core.WindowsInstaller.Databases
298 //recordUpdate.SetInteger(1, file.File.Sequence);
299 throw new NotImplementedException();
300
310 - // update the file attributes to match the compression specified
311 - // on the Merge element or on the Package element
312 - int attributes = 0;
301 + // Update the file attributes to match the compression specified
302 + // on the Merge element or on the Package element.
303 + var attributes = 0;
304
314 - // get the current value if its not null
305 + // Get the current value if its not null.
306 if (!recordUpdate.IsNull(2))
307 {
308 attributes = recordUpdate.GetInteger(2);
309 }
310
320 - // not specified
311 if (!file.File.Compressed.HasValue)
312 {
323 - // clear any compression bits
313 + // Clear all compression bits.
314 attributes &= ~MsiInterop.MsidbFileAttributesCompressed;
315 attributes &= ~MsiInterop.MsidbFileAttributesNoncompressed;
316 }
317 else if (file.File.Compressed.Value)
318 {
329 - // these are mutually exclusive
319 attributes |= MsiInterop.MsidbFileAttributesCompressed;
320 attributes &= ~MsiInterop.MsidbFileAttributesNoncompressed;
321 }
322 else if (!file.File.Compressed.Value)
323 {
335 - // these are mutually exclusive
324 attributes |= MsiInterop.MsidbFileAttributesNoncompressed;
325 attributes &= ~MsiInterop.MsidbFileAttributesCompressed;
326 }
src/WixToolset.Core.WindowsInstaller/Bind/ProcessUncompressedFilesCommand.cs
+19 -17
@@ -1,39 +1,42 @@
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.WindowsInstaller.Databases
3 +namespace WixToolset.Core.WindowsInstaller.Bind
4 {
5 using System;
6 - using System.Collections;
6 using System.Collections.Generic;
7 using System.IO;
8 using WixToolset.Data;
10 - using WixToolset.Data.Rows;
9 using WixToolset.Msi;
10 using WixToolset.Core.Native;
11 using WixToolset.Bind;
12 using WixToolset.Core.Bind;
13 using WixToolset.Data.Bind;
14 + using WixToolset.Data.Tuples;
15 + using System.Linq;
16
17 /// <summary>
18 /// Defines the file transfers necessary to layout the uncompressed files.
19 /// </summary>
20 internal class ProcessUncompressedFilesCommand
21 {
22 + public ProcessUncompressedFilesCommand(IntermediateSection section)
23 + {
24 + this.Section = section;
25 + }
26 +
27 + private IntermediateSection Section { get; }
28 +
29 public string DatabasePath { private get; set; }
30
31 public IEnumerable<FileFacade> FileFacades { private get; set; }
32
26 - public RowDictionary<MediaRow> MediaRows { private get; set; }
27 -
33 public string LayoutDirectory { private get; set; }
34
35 public bool Compressed { private get; set; }
36
37 public bool LongNamesInImage { private get; set; }
38
34 - public Func<MediaRow, string, string, string> ResolveMedia { private get; set; }
35 -
36 - public Table WixMediaTable { private get; set; }
39 + public Func<MediaTuple, string, string, string> ResolveMedia { private get; set; }
40
41 public IEnumerable<FileTransfer> FileTransfers { get; private set; }
42
@@ -41,9 +44,11 @@ namespace WixToolset.Core.WindowsInstaller.Databases
44 {
45 List<FileTransfer> fileTransfers = new List<FileTransfer>();
46
44 - Hashtable directories = new Hashtable();
47 + var directories = new Dictionary<string, ResolvedDirectory>();
48
46 - RowDictionary<WixMediaRow> wixMediaRows = new RowDictionary<WixMediaRow>(this.WixMediaTable);
49 + var mediaRows = this.Section.Tuples.OfType<MediaTuple>().ToDictionary(t => t.DiskId);
50 +
51 + var wixMediaRows = this.Section.Tuples.OfType<WixMediaTuple>().ToDictionary(t => t.DiskId_);
52
53 using (Database db = new Database(this.DatabasePath, OpenDatabase.ReadOnly))
54 {
@@ -72,18 +77,16 @@ namespace WixToolset.Core.WindowsInstaller.Databases
77 // for each file in the array of uncompressed files
78 foreach (FileFacade facade in this.FileFacades)
79 {
75 - MediaRow mediaRow = this.MediaRows.Get(facade.WixFile.DiskId);
80 + var mediaTuple = mediaRows[facade.WixFile.DiskId];
81 string relativeFileLayoutPath = null;
77 -
78 - WixMediaRow wixMediaRow = null;
82 string mediaLayoutFolder = null;
83
81 - if (wixMediaRows.TryGetValue(mediaRow.GetKey(), out wixMediaRow))
84 + if (wixMediaRows.TryGetValue(facade.WixFile.DiskId, out var wixMediaRow))
85 {
86 mediaLayoutFolder = wixMediaRow.Layout;
87 }
88
86 - string mediaLayoutDirectory = this.ResolveMedia(mediaRow, mediaLayoutFolder, this.LayoutDirectory);
89 + var mediaLayoutDirectory = this.ResolveMedia(mediaTuple, mediaLayoutFolder, this.LayoutDirectory);
90
91 // setup up the query record and find the appropriate file in the
92 // previously executed file view
@@ -102,8 +105,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases
105
106 // finally put together the base media layout path and the relative file layout path
107 string fileLayoutPath = Path.Combine(mediaLayoutDirectory, relativeFileLayoutPath);
105 - FileTransfer transfer;
106 - if (FileTransfer.TryCreate(facade.WixFile.Source, fileLayoutPath, false, "File", facade.File.SourceLineNumbers, out transfer))
108 + if (FileTransfer.TryCreate(facade.WixFile.Source, fileLayoutPath, false, "File", facade.File.SourceLineNumbers, out var transfer))
109 {
110 fileTransfers.Add(transfer);
111 }
src/WixToolset.Core.WindowsInstaller/Bind/SequenceActionsCommand.cs new
+671
@@ -0,0 +1,671 @@
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.WindowsInstaller.Bind
4 +{
5 + using System;
6 + using System.Collections.Generic;
7 + using System.Globalization;
8 + using System.Linq;
9 + using WixToolset.Core.Native;
10 + using WixToolset.Data;
11 + using WixToolset.Data.Tuples;
12 +
13 + internal class SequenceActionsCommand
14 + {
15 + public SequenceActionsCommand(IntermediateSection section)
16 + {
17 + this.Section = section;
18 +
19 + this.RelativeActionsForActions = new Dictionary<string, RelativeActions>();
20 +
21 + this.StandardActionsById = WindowsInstallerStandard.StandardActions().ToDictionary(a => a.Id.Id);
22 + }
23 +
24 + private IntermediateSection Section { get; }
25 +
26 + private Dictionary<string, RelativeActions> RelativeActionsForActions { get; }
27 +
28 + private Dictionary<string, WixActionTuple> StandardActionsById { get; }
29 +
30 + public Messaging Messaging { private get; set; }
31 +
32 + public void Execute()
33 + {
34 + var actions = this.Section.Tuples.OfType<WixActionTuple>().ToList();
35 + var suppressActions = this.Section.Tuples.OfType<WixSuppressActionTuple>().ToList();
36 +
37 + this.SequenceActions(actions, suppressActions);
38 + }
39 +
40 + /// <summary>
41 + /// Set sequence numbers for all the actions and create rows in the output object.
42 + /// </summary>
43 + /// <param name="actionRows">Collection of actions to schedule.</param>
44 + /// <param name="suppressActionRows">Collection of actions to suppress.</param>
45 + private void SequenceActions(List<WixActionTuple> actionRows, List<WixSuppressActionTuple> suppressActionRows)
46 + {
47 + var overridableActionRows = new Dictionary<string, WixActionTuple>();
48 + var requiredActionRows = new Dictionary<string, WixActionTuple>();
49 +
50 + // Get the standard actions required based on tuples in the section.
51 + var requiredActionIds = this.GetRequiredActionIds();
52 +
53 + foreach (var actionId in requiredActionIds)
54 + {
55 + var standardAction = this.StandardActionsById[actionId];
56 +
57 + overridableActionRows.Add(standardAction.Id.Id, standardAction);
58 + }
59 +
60 + // Index all the action rows and look for collisions.
61 + foreach (var actionRow in this.Section.Tuples.OfType<WixActionTuple>())
62 + {
63 + if (actionRow.Overridable) // overridable action
64 + {
65 + if (overridableActionRows.TryGetValue(actionRow.Id.Id, out var collidingActionRow))
66 + {
67 + this.Messaging.OnMessage(WixErrors.OverridableActionCollision(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action));
68 + if (null != collidingActionRow.SourceLineNumbers)
69 + {
70 + this.Messaging.OnMessage(WixErrors.OverridableActionCollision2(collidingActionRow.SourceLineNumbers));
71 + }
72 + }
73 + else
74 + {
75 + overridableActionRows.Add(actionRow.Id.Id, actionRow);
76 + }
77 + }
78 + else // unsequenced or sequenced action.
79 + {
80 + // Unsequenced action (allowed for certain standard actions).
81 + if (null == actionRow.Before && null == actionRow.After && 0 == actionRow.Sequence)
82 + {
83 + if (this.StandardActionsById.TryGetValue(actionRow.Id.Id, out var standardAction))
84 + {
85 + // Populate the sequence from the standard action
86 + actionRow.Sequence = standardAction.Sequence;
87 + }
88 + else // not a supported unscheduled action.
89 + {
90 + throw new InvalidOperationException(WixStrings.EXP_FoundActionRowWithNoSequenceBeforeOrAfterColumnSet);
91 + }
92 + }
93 +
94 + if (overridableActionRows.TryGetValue(actionRow.Id.Id, out var collidingActionRow))
95 + {
96 + this.Messaging.OnMessage(WixErrors.ActionCollision(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action));
97 + if (null != collidingActionRow.SourceLineNumbers)
98 + {
99 + this.Messaging.OnMessage(WixErrors.ActionCollision2(collidingActionRow.SourceLineNumbers));
100 + }
101 + }
102 + else
103 + {
104 + requiredActionRows.Add(actionRow.Id.Id, actionRow);
105 + }
106 + }
107 + }
108 +
109 + // Add the overridable action rows that are not overridden to the required action rows.
110 + foreach (var actionRow in overridableActionRows.Values)
111 + {
112 + if (!requiredActionRows.ContainsKey(actionRow.Id.Id))
113 + {
114 + requiredActionRows.Add(actionRow.Id.Id, actionRow);
115 + }
116 + }
117 +
118 + // Suppress the required actions that are overridable.
119 + foreach (var suppressActionRow in suppressActionRows)
120 + {
121 + var key = suppressActionRow.Id.Id;
122 +
123 + // If there is an overridable row to suppress; suppress it. There is no warning if there
124 + // is no action to suppress because the action may be suppressed from a merge module in
125 + // the binder.
126 + if (requiredActionRows.TryGetValue(key, out var requiredActionRow))
127 + {
128 + if (requiredActionRow.Overridable)
129 + {
130 + this.Messaging.OnMessage(WixWarnings.SuppressAction(suppressActionRow.SourceLineNumbers, suppressActionRow.Action, suppressActionRow.SequenceTable.ToString()));
131 + if (null != requiredActionRow.SourceLineNumbers)
132 + {
133 + this.Messaging.OnMessage(WixWarnings.SuppressAction2(requiredActionRow.SourceLineNumbers));
134 + }
135 +
136 + requiredActionRows.Remove(key);
137 + }
138 + else // suppressing a non-overridable action row
139 + {
140 + this.Messaging.OnMessage(WixErrors.SuppressNonoverridableAction(suppressActionRow.SourceLineNumbers, suppressActionRow.SequenceTable.ToString(), suppressActionRow.Action));
141 + if (null != requiredActionRow.SourceLineNumbers)
142 + {
143 + this.Messaging.OnMessage(WixErrors.SuppressNonoverridableAction2(requiredActionRow.SourceLineNumbers));
144 + }
145 + }
146 + }
147 + }
148 +
149 + // Build up dependency trees of the relatively scheduled actions.
150 + // Use ToList() to create a copy of the required action rows so that new tuples can
151 + // be added while enumerating.
152 + foreach (var actionRow in requiredActionRows.Values.ToList())
153 + {
154 + if (0 == actionRow.Sequence)
155 + {
156 + // check for standard actions that don't have a sequence number in a merge module
157 + if (SectionType.Module == this.Section.Type && WindowsInstallerStandard.IsStandardAction(actionRow.Action))
158 + {
159 + this.Messaging.OnMessage(WixErrors.StandardActionRelativelyScheduledInModule(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action));
160 + }
161 +
162 + this.SequenceActionRow(actionRow, requiredActionRows);
163 + }
164 + else if (SectionType.Module == this.Section.Type && 0 < actionRow.Sequence && !WindowsInstallerStandard.IsStandardAction(actionRow.Action)) // check for custom actions and dialogs that have a sequence number
165 + {
166 + this.Messaging.OnMessage(WixErrors.CustomActionSequencedInModule(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action));
167 + }
168 + }
169 +
170 + // Look for standard actions with sequence restrictions that aren't necessarily scheduled based
171 + // on the presence of a particular table.
172 + if (requiredActionRows.ContainsKey("InstallExecuteSequence/DuplicateFiles") && !requiredActionRows.ContainsKey("InstallExecuteSequence/InstallFiles"))
173 + {
174 + var standardAction = this.StandardActionsById["InstallExecuteSequence/InstallFiles"];
175 + requiredActionRows.Add(standardAction.Id.Id, standardAction);
176 + }
177 +
178 + // Schedule actions.
179 + List<WixActionTuple> scheduledActionRows;
180 + if (SectionType.Module == this.Section.Type)
181 + {
182 + scheduledActionRows = requiredActionRows.Values.ToList();
183 + }
184 + else
185 + {
186 + scheduledActionRows = ScheduleActions(requiredActionRows);
187 + }
188 +
189 + // Remove all existing WixActionTuples from the section then add the
190 + // scheduled actions back to the section. Note: we add the indices in
191 + // reverse order to make it easy to remove them from the list later.
192 + var removeIndices = new List<int>();
193 + for (var i = this.Section.Tuples.Count - 1; i >= 0; --i)
194 + {
195 + var tuple = this.Section.Tuples[i];
196 + if (tuple.Definition.Type == TupleDefinitionType.WixAction)
197 + {
198 + removeIndices.Add(i);
199 + }
200 + }
201 +
202 + foreach (var removeIndex in removeIndices)
203 + {
204 + this.Section.Tuples.RemoveAt(removeIndex);
205 + }
206 +
207 + foreach (var action in scheduledActionRows)
208 + {
209 + this.Section.Tuples.Add(action);
210 + }
211 + }
212 +
213 + private List<WixActionTuple> ScheduleActions(Dictionary<string, WixActionTuple> requiredActionRows)
214 + {
215 + var scheduledActionRows = new List<WixActionTuple>();
216 +
217 + // Process each sequence table individually.
218 + foreach (SequenceTable sequenceTable in Enum.GetValues(typeof(SequenceTable)))
219 + {
220 + // Create a collection of just the action rows in this sequence
221 + var sequenceActionRows = requiredActionRows.Values.Where(a => a.SequenceTable == sequenceTable).ToList();
222 +
223 + // Schedule the absolutely scheduled actions (by sorting them by their sequence numbers).
224 + var absoluteActionRows = new List<WixActionTuple>();
225 + foreach (var actionRow in sequenceActionRows)
226 + {
227 + if (0 != actionRow.Sequence)
228 + {
229 + // Look for sequence number collisions
230 + foreach (var sequenceScheduledActionRow in absoluteActionRows)
231 + {
232 + if (sequenceScheduledActionRow.Sequence == actionRow.Sequence)
233 + {
234 + this.Messaging.OnMessage(WixWarnings.ActionSequenceCollision(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action, sequenceScheduledActionRow.Action, actionRow.Sequence));
235 + if (null != sequenceScheduledActionRow.SourceLineNumbers)
236 + {
237 + this.Messaging.OnMessage(WixWarnings.ActionSequenceCollision2(sequenceScheduledActionRow.SourceLineNumbers));
238 + }
239 + }
240 + }
241 +
242 + absoluteActionRows.Add(actionRow);
243 + }
244 + }
245 +
246 + absoluteActionRows.Sort((x, y) => x.Sequence.CompareTo(y.Sequence));
247 +
248 + // Schedule the relatively scheduled actions (by resolving the dependency trees).
249 + var previousUsedSequence = 0;
250 + var relativeActionRows = new List<WixActionTuple>();
251 + for (int j = 0; j < absoluteActionRows.Count; j++)
252 + {
253 + var absoluteActionRow = absoluteActionRows[j];
254 +
255 + // Get all the relatively scheduled action rows occuring before and after this absolutely scheduled action row.
256 + var relativeActions = this.GetAllRelativeActionsForSequenceType(sequenceTable, absoluteActionRow);
257 +
258 + // Check for relatively scheduled actions occuring before/after a special action
259 + // (those actions with a negative sequence number).
260 + if (absoluteActionRow.Sequence < 0 && (relativeActions.PreviousActions.Any() || relativeActions.NextActions.Any()))
261 + {
262 + // Create errors for all the before actions.
263 + foreach (var actionRow in relativeActions.PreviousActions)
264 + {
265 + this.Messaging.OnMessage(WixErrors.ActionScheduledRelativeToTerminationAction(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action, absoluteActionRow.Action));
266 + }
267 +
268 + // Create errors for all the after actions.
269 + foreach (var actionRow in relativeActions.NextActions)
270 + {
271 + this.Messaging.OnMessage(WixErrors.ActionScheduledRelativeToTerminationAction(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action, absoluteActionRow.Action));
272 + }
273 +
274 + // If there is source line information for the absolutely scheduled action display it
275 + if (absoluteActionRow.SourceLineNumbers != null)
276 + {
277 + this.Messaging.OnMessage(WixErrors.ActionScheduledRelativeToTerminationAction2(absoluteActionRow.SourceLineNumbers));
278 + }
279 +
280 + continue;
281 + }
282 +
283 + // Schedule the action rows before this one.
284 + var unusedSequence = absoluteActionRow.Sequence - 1;
285 + for (var i = relativeActions.PreviousActions.Count - 1; i >= 0; i--)
286 + {
287 + var relativeActionRow = relativeActions.PreviousActions[i];
288 +
289 + // look for collisions
290 + if (unusedSequence == previousUsedSequence)
291 + {
292 + this.Messaging.OnMessage(WixErrors.NoUniqueActionSequenceNumber(relativeActionRow.SourceLineNumbers, relativeActionRow.SequenceTable.ToString(), relativeActionRow.Action, absoluteActionRow.Action));
293 + if (absoluteActionRow.SourceLineNumbers != null)
294 + {
295 + this.Messaging.OnMessage(WixErrors.NoUniqueActionSequenceNumber2(absoluteActionRow.SourceLineNumbers));
296 + }
297 +
298 + unusedSequence++;
299 + }
300 +
301 + relativeActionRow.Sequence = unusedSequence;
302 + relativeActionRows.Add(relativeActionRow);
303 +
304 + unusedSequence--;
305 + }
306 +
307 + // Determine the next used action sequence number.
308 + var nextUsedSequence = Int16.MaxValue + 1;
309 + if (absoluteActionRows.Count > j + 1)
310 + {
311 + nextUsedSequence = absoluteActionRows[j + 1].Sequence;
312 + }
313 +
314 + // Schedule the action rows after this one.
315 + unusedSequence = absoluteActionRow.Sequence + 1;
316 + for (var i = 0; i < relativeActions.NextActions.Count; i++)
317 + {
318 + var relativeActionRow = relativeActions.NextActions[i];
319 +
320 + if (unusedSequence == nextUsedSequence)
321 + {
322 + this.Messaging.OnMessage(WixErrors.NoUniqueActionSequenceNumber(relativeActionRow.SourceLineNumbers, relativeActionRow.SequenceTable.ToString(), relativeActionRow.Action, absoluteActionRow.Action));
323 + if (absoluteActionRow.SourceLineNumbers != null)
324 + {
325 + this.Messaging.OnMessage(WixErrors.NoUniqueActionSequenceNumber2(absoluteActionRow.SourceLineNumbers));
326 + }
327 +
328 + unusedSequence--;
329 + }
330 +
331 + relativeActionRow.Sequence = unusedSequence;
332 + relativeActionRows.Add(relativeActionRow);
333 +
334 + unusedSequence++;
335 + }
336 +
337 + // keep track of this sequence number as the previous used sequence number for the next iteration
338 + previousUsedSequence = absoluteActionRow.Sequence;
339 + }
340 +
341 + // add the absolutely and relatively scheduled actions to the list of scheduled actions
342 + scheduledActionRows.AddRange(absoluteActionRows);
343 + scheduledActionRows.AddRange(relativeActionRows);
344 + }
345 +
346 + return scheduledActionRows;
347 + }
348 +
349 + private IEnumerable<string> GetRequiredActionIds()
350 + {
351 + var set = new HashSet<string>();
352 +
353 + // gather the required actions for the output type
354 + if (SectionType.Product == this.Section.Type)
355 + {
356 + // AdminExecuteSequence table
357 + set.Add("AdminExecuteSequence/CostFinalize");
358 + set.Add("AdminExecuteSequence/CostInitialize");
359 + set.Add("AdminExecuteSequence/FileCost");
360 + set.Add("AdminExecuteSequence/InstallAdminPackage");
361 + set.Add("AdminExecuteSequence/InstallFiles");
362 + set.Add("AdminExecuteSequence/InstallFinalize");
363 + set.Add("AdminExecuteSequence/InstallInitialize");
364 + set.Add("AdminExecuteSequence/InstallValidate");
365 +
366 + // AdminUISequence table
367 + set.Add("AdminUISequence/CostFinalize");
368 + set.Add("AdminUISequence/CostInitialize");
369 + set.Add("AdminUISequence/ExecuteAction");
370 + set.Add("AdminUISequence/FileCost");
371 +
372 + // AdvtExecuteSequence table
373 + set.Add("AdvtExecuteSequence/CostFinalize");
374 + set.Add("AdvtExecuteSequence/CostInitialize");
375 + set.Add("AdvtExecuteSequence/InstallFinalize");
376 + set.Add("AdvtExecuteSequence/InstallValidate");
377 + set.Add("AdvtExecuteSequence/PublishFeatures");
378 + set.Add("AdvtExecuteSequence/PublishProduct");
379 +
380 + // InstallExecuteSequence table
381 + set.Add("InstallExecuteSequence/CostFinalize");
382 + set.Add("InstallExecuteSequence/CostInitialize");
383 + set.Add("InstallExecuteSequence/FileCost");
384 + set.Add("InstallExecuteSequence/InstallFinalize");
385 + set.Add("InstallExecuteSequence/InstallInitialize");
386 + set.Add("InstallExecuteSequence/InstallValidate");
387 + set.Add("InstallExecuteSequence/ProcessComponents");
388 + set.Add("InstallExecuteSequence/PublishFeatures");
389 + set.Add("InstallExecuteSequence/PublishProduct");
390 + set.Add("InstallExecuteSequence/RegisterProduct");
391 + set.Add("InstallExecuteSequence/RegisterUser");
392 + set.Add("InstallExecuteSequence/UnpublishFeatures");
393 + set.Add("InstallExecuteSequence/ValidateProductID");
394 +
395 + // InstallUISequence table
396 + set.Add("InstallUISequence/CostFinalize");
397 + set.Add("InstallUISequence/CostInitialize");
398 + set.Add("InstallUISequence/ExecuteAction");
399 + set.Add("InstallUISequence/FileCost");
400 + set.Add("InstallUISequence/ValidateProductID");
401 + }
402 +
403 + // Gather the required actions for each tuple type.
404 + foreach (var tupleType in this.Section.Tuples.Select(t => t.Definition.Type).Distinct())
405 + {
406 + switch (tupleType)
407 + {
408 + case TupleDefinitionType.AppSearch:
409 + set.Add("InstallExecuteSequence/AppSearch");
410 + set.Add("InstallUISequence/AppSearch");
411 + break;
412 + case TupleDefinitionType.BindImage:
413 + set.Add("InstallExecuteSequence/BindImage");
414 + break;
415 + case TupleDefinitionType.CCPSearch:
416 + set.Add("InstallExecuteSequence/AppSearch");
417 + set.Add("InstallExecuteSequence/CCPSearch");
418 + set.Add("InstallExecuteSequence/RMCCPSearch");
419 + set.Add("InstallUISequence/AppSearch");
420 + set.Add("InstallUISequence/CCPSearch");
421 + set.Add("InstallUISequence/RMCCPSearch");
422 + break;
423 + case TupleDefinitionType.Class:
424 + set.Add("AdvtExecuteSequence/RegisterClassInfo");
425 + set.Add("InstallExecuteSequence/RegisterClassInfo");
426 + set.Add("InstallExecuteSequence/UnregisterClassInfo");
427 + break;
428 + case TupleDefinitionType.Complus:
429 + set.Add("InstallExecuteSequence/RegisterComPlus");
430 + set.Add("InstallExecuteSequence/UnregisterComPlus");
431 + break;
432 + case TupleDefinitionType.CreateFolder:
433 + set.Add("InstallExecuteSequence/CreateFolders");
434 + set.Add("InstallExecuteSequence/RemoveFolders");
435 + break;
436 + case TupleDefinitionType.DuplicateFile:
437 + set.Add("InstallExecuteSequence/DuplicateFiles");
438 + set.Add("InstallExecuteSequence/RemoveDuplicateFiles");
439 + break;
440 + case TupleDefinitionType.Environment:
441 + set.Add("InstallExecuteSequence/WriteEnvironmentStrings");
442 + set.Add("InstallExecuteSequence/RemoveEnvironmentStrings");
443 + break;
444 + case TupleDefinitionType.Extension:
445 + set.Add("AdvtExecuteSequence/RegisterExtensionInfo");
446 + set.Add("InstallExecuteSequence/RegisterExtensionInfo");
447 + set.Add("InstallExecuteSequence/UnregisterExtensionInfo");
448 + break;
449 + case TupleDefinitionType.File:
450 + set.Add("InstallExecuteSequence/InstallFiles");
451 + set.Add("InstallExecuteSequence/RemoveFiles");
452 + break;
453 + case TupleDefinitionType.Font:
454 + set.Add("InstallExecuteSequence/RegisterFonts");
455 + set.Add("InstallExecuteSequence/UnregisterFonts");
456 + break;
457 + case TupleDefinitionType.IniFile:
458 + case TupleDefinitionType.RemoveIniFile:
459 + set.Add("InstallExecuteSequence/WriteIniValues");
460 + set.Add("InstallExecuteSequence/RemoveIniValues");
461 + break;
462 + case TupleDefinitionType.IsolatedComponent:
463 + set.Add("InstallExecuteSequence/IsolateComponents");
464 + break;
465 + case TupleDefinitionType.LaunchCondition:
466 + set.Add("InstallExecuteSequence/LaunchConditions");
467 + set.Add("InstallUISequence/LaunchConditions");
468 + break;
469 + case TupleDefinitionType.MIME:
470 + set.Add("AdvtExecuteSequence/RegisterMIMEInfo");
471 + set.Add("InstallExecuteSequence/RegisterMIMEInfo");
472 + set.Add("InstallExecuteSequence/UnregisterMIMEInfo");
473 + break;
474 + case TupleDefinitionType.MoveFile:
475 + set.Add("InstallExecuteSequence/MoveFiles");
476 + break;
477 + case TupleDefinitionType.MsiAssembly:
478 + set.Add("AdvtExecuteSequence/MsiPublishAssemblies");
479 + set.Add("InstallExecuteSequence/MsiPublishAssemblies");
480 + set.Add("InstallExecuteSequence/MsiUnpublishAssemblies");
481 + break;
482 + case TupleDefinitionType.MsiServiceConfig:
483 + case TupleDefinitionType.MsiServiceConfigFailureActions:
484 + set.Add("InstallExecuteSequence/MsiConfigureServices");
485 + break;
486 + case TupleDefinitionType.ODBCDataSource:
487 + case TupleDefinitionType.ODBCTranslator:
488 + case TupleDefinitionType.ODBCDriver:
489 + set.Add("InstallExecuteSequence/SetODBCFolders");
490 + set.Add("InstallExecuteSequence/InstallODBC");
491 + set.Add("InstallExecuteSequence/RemoveODBC");
492 + break;
493 + case TupleDefinitionType.ProgId:
494 + set.Add("AdvtExecuteSequence/RegisterProgIdInfo");
495 + set.Add("InstallExecuteSequence/RegisterProgIdInfo");
496 + set.Add("InstallExecuteSequence/UnregisterProgIdInfo");
497 + break;
498 + case TupleDefinitionType.PublishComponent:
499 + set.Add("AdvtExecuteSequence/PublishComponents");
500 + set.Add("InstallExecuteSequence/PublishComponents");
501 + set.Add("InstallExecuteSequence/UnpublishComponents");
502 + break;
503 + case TupleDefinitionType.Registry:
504 + case TupleDefinitionType.RemoveRegistry:
505 + set.Add("InstallExecuteSequence/WriteRegistryValues");
506 + set.Add("InstallExecuteSequence/RemoveRegistryValues");
507 + break;
508 + case TupleDefinitionType.RemoveFile:
509 + set.Add("InstallExecuteSequence/RemoveFiles");
510 + break;
511 + case TupleDefinitionType.SelfReg:
512 + set.Add("InstallExecuteSequence/SelfRegModules");
513 + set.Add("InstallExecuteSequence/SelfUnregModules");
514 + break;
515 + case TupleDefinitionType.ServiceControl:
516 + set.Add("InstallExecuteSequence/StartServices");
517 + set.Add("InstallExecuteSequence/StopServices");
518 + set.Add("InstallExecuteSequence/DeleteServices");
519 + break;
520 + case TupleDefinitionType.ServiceInstall:
521 + set.Add("InstallExecuteSequence/InstallServices");
522 + break;
523 + case TupleDefinitionType.Shortcut:
524 + set.Add("AdvtExecuteSequence/CreateShortcuts");
525 + set.Add("InstallExecuteSequence/CreateShortcuts");
526 + set.Add("InstallExecuteSequence/RemoveShortcuts");
527 + break;
528 + case TupleDefinitionType.TypeLib:
529 + set.Add("InstallExecuteSequence/RegisterTypeLibraries");
530 + set.Add("InstallExecuteSequence/UnregisterTypeLibraries");
531 + break;
532 + case TupleDefinitionType.Upgrade:
533 + set.Add("InstallExecuteSequence/FindRelatedProducts");
534 + set.Add("InstallUISequence/FindRelatedProducts");
535 +
536 + // Only add the MigrateFeatureStates action if MigrateFeature attribute is set on
537 + // at least one UpgradeVersion element.
538 + if (this.Section.Tuples.OfType<UpgradeTuple>().Any(t => (t.Attributes & MsiInterop.MsidbUpgradeAttributesMigrateFeatures) == MsiInterop.MsidbUpgradeAttributesMigrateFeatures))
539 + {
540 + set.Add("InstallExecuteSequence/MigrateFeatureStates");
541 + set.Add("InstallUISequence/MigrateFeatureStates");
542 + }
543 + break;
544 + }
545 + }
546 +
547 + return set;
548 + }
549 +
550 + private IEnumerable<WixActionTuple> GetActions(SequenceTable sequence, string[] actionNames)
551 + {
552 + foreach (var action in WindowsInstallerStandard.StandardActions())
553 + {
554 + if (action.SequenceTable == sequence && actionNames.Contains(action.Action))
555 + {
556 + yield return action;
557 + }
558 + }
559 + }
560 +
561 + /// <summary>
562 + /// Sequence an action before or after a standard action.
563 + /// </summary>
564 + /// <param name="actionRow">The action row to be sequenced.</param>
565 + /// <param name="requiredActionRows">Collection of actions which must be included.</param>
566 + private void SequenceActionRow(WixActionTuple actionRow, Dictionary<string, WixActionTuple> requiredActionRows)
567 + {
568 + var after = false;
569 +
570 + if (actionRow.After != null)
571 + {
572 + after = true;
573 + }
574 + else if (actionRow.Before == null)
575 + {
576 + throw new InvalidOperationException(WixStrings.EXP_FoundActionRowWithNoSequenceBeforeOrAfterColumnSet);
577 + }
578 +
579 + var parentActionName = (after ? actionRow.After : actionRow.Before);
580 + var parentActionKey = actionRow.SequenceTable.ToString() + "/" + parentActionName;
581 +
582 + if (!requiredActionRows.TryGetValue(parentActionKey, out var parentActionRow))
583 + {
584 + // If the missing parent action is a standard action (with a suggested sequence number), add it.
585 + if (this.StandardActionsById.TryGetValue(parentActionKey, out parentActionRow))
586 + {
587 + // Create a clone to avoid modifying the static copy of the object.
588 + // TODO: consider this: parentActionRow = parentActionRow.Clone();
589 +
590 + requiredActionRows.Add(parentActionRow.Id.Id, parentActionRow);
591 + }
592 + else
593 + {
594 + throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_FoundActionRowWinNonExistentAction, (after ? "After" : "Before"), parentActionName));
595 + }
596 + }
597 + else if (actionRow == parentActionRow || this.ContainsChildActionRow(actionRow, parentActionRow)) // cycle detected
598 + {
599 + throw new WixException(WixErrors.ActionCircularDependency(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action, parentActionRow.Action));
600 + }
601 +
602 + // Add this action to the appropriate list of dependent action rows.
603 + var relativeActions = this.GetRelativeActions(parentActionRow);
604 + var relatedRows = (after ? relativeActions.NextActions : relativeActions.PreviousActions);
605 + relatedRows.Add(actionRow);
606 + }
607 +
608 + private bool ContainsChildActionRow(WixActionTuple childTuple, WixActionTuple parentTuple)
609 + {
610 + var result = false;
611 +
612 + if (this.RelativeActionsForActions.TryGetValue(childTuple.Id.Id, out var relativeActions))
613 + {
614 + result = relativeActions.NextActions.Any(a => a.SequenceTable == parentTuple.SequenceTable && a.Id.Id == parentTuple.Id.Id) ||
615 + relativeActions.PreviousActions.Any(a => a.SequenceTable == parentTuple.SequenceTable && a.Id.Id == parentTuple.Id.Id);
616 + }
617 +
618 + return result;
619 + }
620 +
621 + private RelativeActions GetRelativeActions(WixActionTuple action)
622 + {
623 + if (!this.RelativeActionsForActions.TryGetValue(action.Id.Id, out var relativeActions))
624 + {
625 + relativeActions = new RelativeActions();
626 + this.RelativeActionsForActions.Add(action.Id.Id, relativeActions);
627 + }
628 +
629 + return relativeActions;
630 + }
631 +
632 + private RelativeActions GetAllRelativeActionsForSequenceType(SequenceTable sequenceType, WixActionTuple action)
633 + {
634 + var relativeActions = new RelativeActions();
635 +
636 + if (this.RelativeActionsForActions.TryGetValue(action.Id.Id, out var actionRelatives))
637 + {
638 + this.RecurseRelativeActionsForSequenceType(sequenceType, actionRelatives.PreviousActions, relativeActions.PreviousActions);
639 +
640 + this.RecurseRelativeActionsForSequenceType(sequenceType, actionRelatives.NextActions, relativeActions.NextActions);
641 + }
642 +
643 + return relativeActions;
644 + }
645 +
646 + private void RecurseRelativeActionsForSequenceType(SequenceTable sequenceType, List<WixActionTuple> actions, List<WixActionTuple> visitedActions)
647 + {
648 + foreach (var action in actions.Where(a => a.SequenceTable == sequenceType))
649 + {
650 + if (this.RelativeActionsForActions.TryGetValue(action.Id.Id, out var actionRelatives))
651 + {
652 + this.RecurseRelativeActionsForSequenceType(sequenceType, actionRelatives.PreviousActions, visitedActions);
653 + }
654 +
655 + visitedActions.Add(action);
656 +
657 + if (actionRelatives != null)
658 + {
659 + this.RecurseRelativeActionsForSequenceType(sequenceType, actionRelatives.NextActions, visitedActions);
660 + }
661 + }
662 + }
663 +
664 + private class RelativeActions
665 + {
666 + public List<WixActionTuple> PreviousActions { get; } = new List<WixActionTuple>();
667 +
668 + public List<WixActionTuple> NextActions { get; } = new List<WixActionTuple>();
669 + }
670 + }
671 +}
src/WixToolset.Core.WindowsInstaller/Bind/UpdateControlTextCommand.cs
+1 -1
@@ -1,6 +1,6 @@
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.WindowsInstaller.Databases
3 +namespace WixToolset.Core.WindowsInstaller.Bind
4 {
5 using System;
6 using System.IO;
src/WixToolset.Core.WindowsInstaller/Bind/UpdateFileFacadesCommand.cs
+49 -63
@@ -1,10 +1,9 @@
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.WindowsInstaller.Databases
3 +namespace WixToolset.Core.WindowsInstaller.Bind
4 {
5 using System;
6 using System.Collections.Generic;
7 - using System.Collections.Specialized;
7 using System.ComponentModel;
8 using System.Globalization;
9 using System.IO;
@@ -14,7 +13,6 @@ namespace WixToolset.Core.WindowsInstaller.Databases
13 using WixToolset.Clr.Interop;
14 using WixToolset.Core.Bind;
15 using WixToolset.Data;
17 - using WixToolset.Data.Rows;
16 using WixToolset.Data.Tuples;
17 using WixToolset.Msi;
18
@@ -23,13 +21,16 @@ namespace WixToolset.Core.WindowsInstaller.Databases
21 /// </summary>
22 internal class UpdateFileFacadesCommand
23 {
26 - public IEnumerable<FileFacade> FileFacades { private get; set; }
24 + public UpdateFileFacadesCommand(IntermediateSection section)
25 + {
26 + this.Section = section;
27 + }
28
28 - public IEnumerable<FileFacade> UpdateFileFacades { private get; set; }
29 + private IntermediateSection Section { get; }
30
30 - public string ModularizationGuid { private get; set; }
31 + public IEnumerable<FileFacade> FileFacades { private get; set; }
32
32 - public Output Output { private get; set; }
33 + public IEnumerable<FileFacade> UpdateFileFacades { private get; set; }
34
35 public bool OverwriteHash { private get; set; }
36
@@ -47,6 +48,12 @@ namespace WixToolset.Core.WindowsInstaller.Databases
48
49 private void UpdateFileFacade(FileFacade file)
50 {
51 + var assemblyNameTuples = new Dictionary<string, MsiAssemblyNameTuple>();
52 + foreach (var assemblyTuple in this.Section.Tuples.OfType<MsiAssemblyNameTuple>())
53 + {
54 + assemblyNameTuples.Add(assemblyTuple.Component_ + "/" + assemblyTuple.Name, assemblyTuple);
55 + }
56 +
57 FileInfo fileInfo = null;
58 try
59 {
@@ -149,9 +156,8 @@ namespace WixToolset.Core.WindowsInstaller.Databases
156
157 if (null == file.Hash)
158 {
152 - //Table msiFileHashTable = this.Output.EnsureTable(this.TableDefinitions["MsiFileHash"]);
153 - //file.Hash = msiFileHashTable.CreateRow(file.File.SourceLineNumbers);
154 - throw new NotImplementedException();
159 + file.Hash = new MsiFileHashTuple(file.File.SourceLineNumbers, file.File.Id);
160 + this.Section.Tuples.Add(file.Hash);
161 }
162
163 file.Hash.File_ = file.File.File;
@@ -198,13 +204,13 @@ namespace WixToolset.Core.WindowsInstaller.Databases
204 {
205 if (!String.IsNullOrEmpty(file.File.Version))
206 {
201 - string key = String.Format(CultureInfo.InvariantCulture, "fileversion.{0}", Common.Demodularize(this.Output.Type, this.ModularizationGuid, file.File.File));
207 + var key = String.Format(CultureInfo.InvariantCulture, "fileversion.{0}", file.File.File);
208 this.VariableCache[key] = file.File.Version;
209 }
210
211 if (!String.IsNullOrEmpty(file.File.Language))
212 {
207 - string key = String.Format(CultureInfo.InvariantCulture, "filelanguage.{0}", Common.Demodularize(this.Output.Type, ModularizationGuid, file.File.File));
213 + var key = String.Format(CultureInfo.InvariantCulture, "filelanguage.{0}", file.File.File);
214 this.VariableCache[key] = file.File.Language;
215 }
216 }
@@ -214,14 +220,13 @@ namespace WixToolset.Core.WindowsInstaller.Databases
220 if (FileAssemblyType.DotNetAssembly == file.WixFile.AssemblyType)
221 {
222 bool targetNetfx1 = false;
217 - StringDictionary assemblyNameValues = new StringDictionary();
223 + var assemblyNameValues = new Dictionary<string, string>();
224
219 - ClrInterop.IReferenceIdentity referenceIdentity = null;
225 Guid referenceIdentityGuid = ClrInterop.ReferenceIdentityGuid;
221 - uint result = ClrInterop.GetAssemblyIdentityFromFile(fileInfo.FullName, ref referenceIdentityGuid, out referenceIdentity);
226 + var result = ClrInterop.GetAssemblyIdentityFromFile(fileInfo.FullName, ref referenceIdentityGuid, out var referenceIdentity);
227 if (0 == result && null != referenceIdentity)
228 {
224 - string imageRuntimeVersion = referenceIdentity.GetAttribute(null, "ImageRuntimeVersion");
229 + var imageRuntimeVersion = referenceIdentity.GetAttribute(null, "ImageRuntimeVersion");
230 if (null != imageRuntimeVersion)
231 {
232 targetNetfx1 = imageRuntimeVersion.StartsWith("v1", StringComparison.OrdinalIgnoreCase);
@@ -269,15 +274,14 @@ namespace WixToolset.Core.WindowsInstaller.Databases
274 return;
275 }
276
272 - Table assemblyNameTable = this.Output.EnsureTable(this.TableDefinitions["MsiAssemblyName"]);
273 - if (assemblyNameValues.ContainsKey("name"))
277 + if (assemblyNameValues.TryGetValue("name", out var value))
278 {
275 - this.SetMsiAssemblyName(assemblyNameTable, file, "name", assemblyNameValues["name"]);
279 + this.SetMsiAssemblyName(assemblyNameTuples, file, "name", value);
280 }
281
282 if (!String.IsNullOrEmpty(version))
283 {
280 - this.SetMsiAssemblyName(assemblyNameTable, file, "fileVersion", version);
284 + this.SetMsiAssemblyName(assemblyNameTuples, file, "fileVersion", version);
285 }
286
287 if (assemblyNameValues.ContainsKey("version"))
@@ -303,33 +307,33 @@ namespace WixToolset.Core.WindowsInstaller.Databases
307 }
308 }
309
306 - this.SetMsiAssemblyName(assemblyNameTable, file, "version", assemblyVersion);
310 + this.SetMsiAssemblyName(assemblyNameTuples, file, "version", assemblyVersion);
311 }
312
313 if (assemblyNameValues.ContainsKey("culture"))
314 {
311 - this.SetMsiAssemblyName(assemblyNameTable, file, "culture", assemblyNameValues["culture"]);
315 + this.SetMsiAssemblyName(assemblyNameTuples, file, "culture", assemblyNameValues["culture"]);
316 }
317
318 if (assemblyNameValues.ContainsKey("publicKeyToken"))
319 {
316 - this.SetMsiAssemblyName(assemblyNameTable, file, "publicKeyToken", assemblyNameValues["publicKeyToken"]);
320 + this.SetMsiAssemblyName(assemblyNameTuples, file, "publicKeyToken", assemblyNameValues["publicKeyToken"]);
321 }
322
323 if (!String.IsNullOrEmpty(file.WixFile.ProcessorArchitecture))
324 {
321 - this.SetMsiAssemblyName(assemblyNameTable, file, "processorArchitecture", file.WixFile.ProcessorArchitecture);
325 + this.SetMsiAssemblyName(assemblyNameTuples, file, "processorArchitecture", file.WixFile.ProcessorArchitecture);
326 }
327
328 if (assemblyNameValues.ContainsKey("processorArchitecture"))
329 {
326 - this.SetMsiAssemblyName(assemblyNameTable, file, "processorArchitecture", assemblyNameValues["processorArchitecture"]);
330 + this.SetMsiAssemblyName(assemblyNameTuples, file, "processorArchitecture", assemblyNameValues["processorArchitecture"]);
331 }
332
333 // add the assembly name to the information cache
334 if (null != this.VariableCache)
335 {
332 - string fileId = Common.Demodularize(this.Output.Type, this.ModularizationGuid, file.File.File);
336 + string fileId = file.File.File;
337 string key = String.Concat("assemblyfullname.", fileId);
338 string assemblyName = String.Concat(assemblyNameValues["name"], ", version=", assemblyNameValues["version"], ", culture=", assemblyNameValues["culture"], ", publicKeyToken=", String.IsNullOrEmpty(assemblyNameValues["publicKeyToken"]) ? "null" : assemblyNameValues["publicKeyToken"]);
339 if (assemblyNameValues.ContainsKey("processorArchitecture"))
@@ -437,30 +441,29 @@ namespace WixToolset.Core.WindowsInstaller.Databases
441 Messaging.Instance.OnMessage(WixErrors.InvalidXml(new SourceLineNumber(fileManifest.WixFile.Source), "manifest", xe.Message));
442 }
443
440 - Table assemblyNameTable = this.Output.EnsureTable(this.TableDefinitions["MsiAssemblyName"]);
444 if (!String.IsNullOrEmpty(win32Name))
445 {
443 - this.SetMsiAssemblyName(assemblyNameTable, file, "name", win32Name);
446 + this.SetMsiAssemblyName(assemblyNameTuples, file, "name", win32Name);
447 }
448
449 if (!String.IsNullOrEmpty(win32Version))
450 {
448 - this.SetMsiAssemblyName(assemblyNameTable, file, "version", win32Version);
451 + this.SetMsiAssemblyName(assemblyNameTuples, file, "version", win32Version);
452 }
453
454 if (!String.IsNullOrEmpty(win32Type))
455 {
453 - this.SetMsiAssemblyName(assemblyNameTable, file, "type", win32Type);
456 + this.SetMsiAssemblyName(assemblyNameTuples, file, "type", win32Type);
457 }
458
459 if (!String.IsNullOrEmpty(win32ProcessorArchitecture))
460 {
458 - this.SetMsiAssemblyName(assemblyNameTable, file, "processorArchitecture", win32ProcessorArchitecture);
461 + this.SetMsiAssemblyName(assemblyNameTuples, file, "processorArchitecture", win32ProcessorArchitecture);
462 }
463
464 if (!String.IsNullOrEmpty(win32PublicKeyToken))
465 {
463 - this.SetMsiAssemblyName(assemblyNameTable, file, "publicKeyToken", win32PublicKeyToken);
466 + this.SetMsiAssemblyName(assemblyNameTuples, file, "publicKeyToken", win32PublicKeyToken);
467 }
468 }
469 }
@@ -469,11 +472,11 @@ namespace WixToolset.Core.WindowsInstaller.Databases
472 /// Set an MsiAssemblyName row. If it was directly authored, override the value, otherwise
473 /// create a new row.
474 /// </summary>
472 - /// <param name="assemblyNameTable">MsiAssemblyName table.</param>
475 + /// <param name="assemblyNameTuples">MsiAssemblyName table.</param>
476 /// <param name="file">FileFacade containing the assembly read for the MsiAssemblyName row.</param>
477 /// <param name="name">MsiAssemblyName name.</param>
478 /// <param name="value">MsiAssemblyName value.</param>
476 - private void SetMsiAssemblyName(Table assemblyNameTable, FileFacade file, string name, string value)
479 + private void SetMsiAssemblyName(Dictionary<string, MsiAssemblyNameTuple> assemblyNameTuples, FileFacade file, string name, string value)
480 {
481 // check for null value (this can occur when grabbing the file version from an assembly without one)
482 if (String.IsNullOrEmpty(value))
@@ -482,18 +485,6 @@ namespace WixToolset.Core.WindowsInstaller.Databases
485 }
486 else
487 {
485 - Row assemblyNameRow = null;
486 -
487 - // override directly authored value
488 - foreach (Row row in assemblyNameTable.Rows)
489 - {
490 - if ((string)row[0] == file.File.Component_ && (string)row[1] == name)
491 - {
492 - assemblyNameRow = row;
493 - break;
494 - }
495 - }
496 -
488 // if the assembly will be GAC'd and the name in the file table doesn't match the name in the MsiAssemblyName table, error because the install will fail.
489 if ("name" == name && FileAssemblyType.DotNetAssembly == file.WixFile.AssemblyType &&
490 String.IsNullOrEmpty(file.WixFile.File_AssemblyApplication) &&
@@ -502,17 +493,14 @@ namespace WixToolset.Core.WindowsInstaller.Databases
493 Messaging.Instance.OnMessage(WixErrors.GACAssemblyIdentityWarning(file.File.SourceLineNumbers, Path.GetFileNameWithoutExtension(file.File.LongFileName), value));
494 }
495
505 - if (null == assemblyNameRow)
496 + // override directly authored value
497 + var lookup = String.Concat(file.File.Component_, "/", name);
498 + if (assemblyNameTuples.TryGetValue(lookup, out var assemblyNameRow))
499 {
507 - throw new NotImplementedException();
508 -#if TODO
509 - assemblyNameRow = assemblyNameTable.CreateRow(file.File.SourceLineNumbers);
510 - assemblyNameRow[0] = file.File.Component_;
511 - assemblyNameRow[1] = name;
512 - assemblyNameRow[2] = value;
513 -
514 - // put the MsiAssemblyName row in the same section as the related File row
515 - assemblyNameRow.SectionId = file.File.SectionId;
500 + assemblyNameRow = new MsiAssemblyNameTuple(file.File.SourceLineNumbers);
501 + assemblyNameRow.Component_ = file.File.Component_;
502 + assemblyNameRow.Name = name;
503 + assemblyNameRow.Value = value;
504
505 if (null == file.AssemblyNames)
506 {
@@ -520,17 +508,15 @@ namespace WixToolset.Core.WindowsInstaller.Databases
508 }
509
510 file.AssemblyNames.Add(assemblyNameRow);
523 -#endif
524 - }
525 - else
526 - {
527 - assemblyNameRow[2] = value;
511 + this.Section.Tuples.Add(assemblyNameRow);
512 }
513
514 + assemblyNameRow.Value = value;
515 +
516 if (this.VariableCache != null)
517 {
532 - string key = String.Format(CultureInfo.InvariantCulture, "assembly{0}.{1}", name, Common.Demodularize(this.Output.Type, this.ModularizationGuid, file.File.File)).ToLowerInvariant();
533 - this.VariableCache[key] = (string)assemblyNameRow[2];
518 + var key = String.Format(CultureInfo.InvariantCulture, "assembly{0}.{1}", name, file.File.File).ToLowerInvariant();
519 + this.VariableCache[key] = value;
520 }
521 }
522 }
src/WixToolset.Core.WindowsInstaller/Bind/UpdateMediaSequencesCommand.cs new
+126
@@ -0,0 +1,126 @@
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.WindowsInstaller.Bind
4 +{
5 + using System;
6 + using System.Collections.Generic;
7 + using System.Linq;
8 + using WixToolset.Core.Bind;
9 + using WixToolset.Data;
10 + using WixToolset.Data.Rows;
11 + using WixToolset.Data.Tuples;
12 +
13 + internal class UpdateMediaSequencesCommand
14 + {
15 + public UpdateMediaSequencesCommand(Output output, List<FileFacade> fileFacades, Dictionary<int, MediaTuple> assignedMediaRows)
16 + {
17 + this.Output = output;
18 + this.FileFacades = fileFacades;
19 + }
20 +
21 + private Output Output { get; }
22 +
23 + private List<FileFacade> FileFacades { get; }
24 +
25 + public void Execute()
26 + {
27 + var fileRows = new RowDictionary<FileRow>(this.Output.Tables["File"]);
28 + var mediaRows = new RowDictionary<MediaRow>(this.Output.Tables["Media"]);
29 +
30 + // Calculate sequence numbers and media disk id layout for all file media information objects.
31 + if (OutputType.Module == this.Output.Type)
32 + {
33 + var lastSequence = 0;
34 +
35 + // Order by Component to group the files by directory.
36 + var optimized = this.OptimizedFileFacades();
37 + foreach (var fileId in optimized.Select(f => f.File.File))
38 + {
39 + var fileRow = fileRows.Get(fileId);
40 + fileRow.Sequence = ++lastSequence;
41 + }
42 + }
43 + else
44 + {
45 + int lastSequence = 0;
46 + MediaRow mediaRow = null;
47 + Dictionary<int, List<FileFacade>> patchGroups = new Dictionary<int, List<FileFacade>>();
48 +
49 + // sequence the non-patch-added files
50 + var optimized = this.OptimizedFileFacades();
51 + foreach (FileFacade facade in optimized)
52 + {
53 + if (null == mediaRow)
54 + {
55 + mediaRow = mediaRows.Get(facade.WixFile.DiskId);
56 + if (OutputType.Patch == this.Output.Type)
57 + {
58 + // patch Media cannot start at zero
59 + lastSequence = mediaRow.LastSequence;
60 + }
61 + }
62 + else if (mediaRow.DiskId != facade.WixFile.DiskId)
63 + {
64 + mediaRow.LastSequence = lastSequence;
65 + mediaRow = mediaRows.Get(facade.WixFile.DiskId);
66 + }
67 +
68 + if (0 < facade.WixFile.PatchGroup)
69 + {
70 + if (patchGroups.TryGetValue(facade.WixFile.PatchGroup, out var patchGroup))
71 + {
72 + patchGroup = new List<FileFacade>();
73 + patchGroups.Add(facade.WixFile.PatchGroup, patchGroup);
74 + }
75 +
76 + patchGroup.Add(facade);
77 + }
78 + else
79 + {
80 + var fileRow = fileRows.Get(facade.File.File);
81 + fileRow.Sequence = ++lastSequence;
82 + }
83 + }
84 +
85 + if (null != mediaRow)
86 + {
87 + mediaRow.LastSequence = lastSequence;
88 + mediaRow = null;
89 + }
90 +
91 + // sequence the patch-added files
92 + foreach (var patchGroup in patchGroups.Values)
93 + {
94 + foreach (var facade in patchGroup)
95 + {
96 + if (null == mediaRow)
97 + {
98 + mediaRow = mediaRows.Get(facade.WixFile.DiskId);
99 + }
100 + else if (mediaRow.DiskId != facade.WixFile.DiskId)
101 + {
102 + mediaRow.LastSequence = lastSequence;
103 + mediaRow = mediaRows.Get(facade.WixFile.DiskId);
104 + }
105 +
106 + var fileRow = fileRows.Get(facade.File.File);
107 + fileRow.Sequence = ++lastSequence;
108 + }
109 + }
110 +
111 + if (null != mediaRow)
112 + {
113 + mediaRow.LastSequence = lastSequence;
114 + }
115 + }
116 + }
117 +
118 + private IEnumerable<FileFacade> OptimizedFileFacades()
119 + {
120 + // TODO: Sort these facades even smarter by directory path and component id
121 + // and maybe file size or file extension and other creative ideas to
122 + // get optimal install speed out of MSI.
123 + return this.FileFacades.OrderBy(f => f.File.Component_);
124 + }
125 + }
126 +}
src/WixToolset.Core.WindowsInstaller/Inscribe/InscribeMsiPackageCommand.cs
+1 -1
@@ -18,7 +18,7 @@ namespace WixToolset.Core.WindowsInstaller.Inscribe
18 public InscribeMsiPackageCommand(IInscribeContext context)
19 {
20 this.Context = context;
21 - this.TableDefinitions = WindowsInstallerStandard.GetTableDefinitions();
21 + this.TableDefinitions = WindowsInstallerStandardInternal.GetTableDefinitions();
22 }
23
24 private IInscribeContext Context { get; }
src/WixToolset.Core.WindowsInstaller/MstBackend.cs
-1
@@ -3,7 +3,6 @@
3 namespace WixToolset.Core.WindowsInstaller
4 {
5 using System;
6 - using WixToolset.Core.WindowsInstaller.Databases;
6 using WixToolset.Core.WindowsInstaller.Unbind;
7 using WixToolset.Data;
8 using WixToolset.Data.Bind;
src/WixToolset.Core.WindowsInstaller/Patch.cs
+1 -1
@@ -29,7 +29,7 @@ namespace WixToolset.Data
29 public Patch()
30 {
31 this.inspectorExtensions = new List<IInspectorExtension>();
32 - this.tableDefinitions = new TableDefinitionCollection(WindowsInstallerStandard.GetTableDefinitions());
32 + this.tableDefinitions = new TableDefinitionCollection(WindowsInstallerStandardInternal.GetTableDefinitions());
33 }
34
35 /// <summary>
src/WixToolset.Core.WindowsInstaller/Unbind/UnbindDatabaseCommand.cs
+1 -1
@@ -27,7 +27,7 @@ namespace WixToolset.Core.WindowsInstaller.Unbind
27 this.SuppressDemodularization = suppressDemodularization;
28 this.SkipSummaryInfo = skipSummaryInfo;
29
30 - this.TableDefinitions = WindowsInstallerStandard.GetTableDefinitions();
30 + this.TableDefinitions = WindowsInstallerStandardInternal.GetTableDefinitions();
31 }
32
33 public Messaging Messaging { get; }
src/WixToolset.Core.WindowsInstaller/Unbind/UnbindTranformCommand.cs
+2 -5
@@ -4,16 +4,13 @@ namespace WixToolset.Core.WindowsInstaller.Unbind
4 {
5 using System;
6 using System.Collections;
7 - using System.Collections.Generic;
7 using System.ComponentModel;
8 using System.Globalization;
9 using System.IO;
10 using System.Linq;
12 - using System.Text.RegularExpressions;
11 using WixToolset.Core.Native;
14 - using WixToolset.Core.WindowsInstaller.Databases;
12 + using WixToolset.Core.WindowsInstaller.Bind;
13 using WixToolset.Data;
16 - using WixToolset.Data.Rows;
14 using WixToolset.Extensibility;
15 using WixToolset.Msi;
16
@@ -26,7 +23,7 @@ namespace WixToolset.Core.WindowsInstaller.Unbind
23 this.ExportBasePath = exportBasePath;
24 this.IntermediateFolder = intermediateFolder;
25
29 - this.TableDefinitions = WindowsInstallerStandard.GetTableDefinitions();
26 + this.TableDefinitions = WindowsInstallerStandardInternal.GetTableDefinitions();
27 }
28
29 private Messaging Messaging { get; }
src/WixToolset.Core/Bind/ExtractEmbeddedFilesCommand.cs
+10 -5
@@ -11,7 +11,12 @@ namespace WixToolset.Core.Bind
11
12 public class ExtractEmbeddedFilesCommand
13 {
14 - public IEnumerable<IExpectedExtractFile> FilesWithEmbeddedFiles { private get; set; }
14 + public ExtractEmbeddedFilesCommand(IEnumerable<IExpectedExtractFile> embeddedFiles)
15 + {
16 + this.FilesWithEmbeddedFiles = embeddedFiles;
17 + }
18 +
19 + private IEnumerable<IExpectedExtractFile> FilesWithEmbeddedFiles { get; }
20
21 public void Execute()
22 {
@@ -28,10 +33,10 @@ namespace WixToolset.Core.Bind
33 // a .wixlib embedded in a WixExtension).
34 if ("embeddedresource" == baseUri.Scheme)
35 {
31 - string assemblyPath = Path.GetFullPath(baseUri.LocalPath);
32 - string resourceName = baseUri.Fragment.TrimStart('#');
36 + var assemblyPath = Path.GetFullPath(baseUri.LocalPath);
37 + var resourceName = baseUri.Fragment.TrimStart('#');
38
34 - Assembly assembly = Assembly.LoadFile(assemblyPath);
39 + var assembly = Assembly.LoadFile(assemblyPath);
40 stream = assembly.GetManifestResourceStream(resourceName);
41 }
42 else // normal file (usually a binary .wixlib on disk).
@@ -39,7 +44,7 @@ namespace WixToolset.Core.Bind
44 stream = File.OpenRead(baseUri.LocalPath);
45 }
46
42 - using (FileStructure fs = FileStructure.Read(stream))
47 + using (var fs = FileStructure.Read(stream))
48 {
49 var uniqueIndicies = new SortedSet<int>();
50
src/WixToolset.Core/Bind/ResolveDelayedFieldsCommand.cs
+34 -44
@@ -12,25 +12,28 @@ namespace WixToolset.Core.Bind
12 /// Resolves the fields which had variables that needed to be resolved after the file information
13 /// was loaded.
14 /// </summary>
15 - public class ResolveDelayedFieldsCommand : ICommand
15 + public class ResolveDelayedFieldsCommand
16 {
17 - public OutputType OutputType { private get; set;}
18 -
19 - public IEnumerable<IDelayedField> DelayedFields { private get; set;}
17 + /// <summary>
18 + /// Resolve delayed fields.
19 + /// </summary>
20 + /// <param name="delayedFields">The fields which had resolution delayed.</param>
21 + /// <param name="variableCache">The file information to use when resolving variables.</param>
22 + public ResolveDelayedFieldsCommand(IEnumerable<IDelayedField> delayedFields, Dictionary<string, string> variableCache)
23 + {
24 + this.DelayedFields = delayedFields;
25 + this.VariableCache = variableCache;
26 + }
27
21 - public IDictionary<string, string> VariableCache { private get; set; }
28 + private IEnumerable<IDelayedField> DelayedFields { get;}
29
23 - public string ModularizationGuid { private get; set; }
30 + private IDictionary<string, string> VariableCache { get; }
31
25 - /// <param name="output">Internal representation of the msi database to operate upon.</param>
26 - /// <param name="delayedFields">The fields which had resolution delayed.</param>
27 - /// <param name="variableCache">The file information to use when resolving variables.</param>
28 - /// <param name="modularizationGuid">The modularization guid (used in case of a merge module).</param>
32 public void Execute()
33 {
34 var deferredFields = new List<IDelayedField>();
35
33 - foreach (IDelayedField delayedField in this.DelayedFields)
36 + foreach (var delayedField in this.DelayedFields)
37 {
38 try
39 {
@@ -42,7 +45,7 @@ namespace WixToolset.Core.Bind
45 var value = WixVariableResolver.ResolveDelayedVariables(propertyRow.SourceLineNumbers, delayedField.Field.AsString(), this.VariableCache);
46
47 // update the variable cache with the new value
45 - var key = String.Concat("property.", Common.Demodularize(this.OutputType, this.ModularizationGuid, (string)propertyRow[0]));
48 + var key = String.Concat("property.", propertyRow.AsString(0));
49 this.VariableCache[key] = value;
50
51 // update the field data
@@ -62,43 +65,31 @@ namespace WixToolset.Core.Bind
65
66 // add specialization for ProductVersion fields
67 string keyProductVersion = "property.ProductVersion";
65 - if (this.VariableCache.ContainsKey(keyProductVersion))
68 + if (this.VariableCache.TryGetValue(keyProductVersion, out var versionValue) && Version.TryParse(versionValue, out Version productVersion))
69 {
67 - string value = this.VariableCache[keyProductVersion];
68 - Version productVersion = null;
69 -
70 - try
70 + // Don't add the variable if it already exists (developer defined a property with the same name).
71 + string fieldKey = String.Concat(keyProductVersion, ".Major");
72 + if (!this.VariableCache.ContainsKey(fieldKey))
73 {
72 - productVersion = new Version(value);
73 -
74 - // Don't add the variable if it already exists (developer defined a property with the same name).
75 - string fieldKey = String.Concat(keyProductVersion, ".Major");
76 - if (!this.VariableCache.ContainsKey(fieldKey))
77 - {
78 - this.VariableCache[fieldKey] = productVersion.Major.ToString(CultureInfo.InvariantCulture);
79 - }
80 -
81 - fieldKey = String.Concat(keyProductVersion, ".Minor");
82 - if (!this.VariableCache.ContainsKey(fieldKey))
83 - {
84 - this.VariableCache[fieldKey] = productVersion.Minor.ToString(CultureInfo.InvariantCulture);
85 - }
74 + this.VariableCache[fieldKey] = productVersion.Major.ToString(CultureInfo.InvariantCulture);
75 + }
76
87 - fieldKey = String.Concat(keyProductVersion, ".Build");
88 - if (!this.VariableCache.ContainsKey(fieldKey))
89 - {
90 - this.VariableCache[fieldKey] = productVersion.Build.ToString(CultureInfo.InvariantCulture);
91 - }
77 + fieldKey = String.Concat(keyProductVersion, ".Minor");
78 + if (!this.VariableCache.ContainsKey(fieldKey))
79 + {
80 + this.VariableCache[fieldKey] = productVersion.Minor.ToString(CultureInfo.InvariantCulture);
81 + }
82
93 - fieldKey = String.Concat(keyProductVersion, ".Revision");
94 - if (!this.VariableCache.ContainsKey(fieldKey))
95 - {
96 - this.VariableCache[fieldKey] = productVersion.Revision.ToString(CultureInfo.InvariantCulture);
97 - }
83 + fieldKey = String.Concat(keyProductVersion, ".Build");
84 + if (!this.VariableCache.ContainsKey(fieldKey))
85 + {
86 + this.VariableCache[fieldKey] = productVersion.Build.ToString(CultureInfo.InvariantCulture);
87 }
99 - catch
88 +
89 + fieldKey = String.Concat(keyProductVersion, ".Revision");
90 + if (!this.VariableCache.ContainsKey(fieldKey))
91 {
101 - // Ignore the error introduced by new behavior.
92 + this.VariableCache[fieldKey] = productVersion.Revision.ToString(CultureInfo.InvariantCulture);
93 }
94 }
95
@@ -113,7 +104,6 @@ namespace WixToolset.Core.Bind
104 catch (WixException we)
105 {
106 Messaging.Instance.OnMessage(we.Error);
116 - continue;
107 }
108 }
109 }
src/WixToolset.Core/Bind/ResolvedDirectory.cs
+9 -9
@@ -7,15 +7,6 @@ namespace WixToolset.Bind
7 /// </summary>
8 public struct ResolvedDirectory
9 {
10 - /// <summary>The directory parent.</summary>
11 - public string DirectoryParent;
12 -
13 - /// <summary>The name of this directory.</summary>
14 - public string Name;
15 -
16 - /// <summary>The path of this directory.</summary>
17 - public string Path;
18 -
10 /// <summary>
11 /// Constructor for ResolvedDirectory.
12 /// </summary>
@@ -27,5 +18,14 @@ namespace WixToolset.Bind
18 this.Name = name;
19 this.Path = null;
20 }
21 +
22 + /// <summary>The directory parent.</summary>
23 + public string DirectoryParent { get; set; }
24 +
25 + /// <summary>The name of this directory.</summary>
26 + public string Name { get; set; }
27 +
28 + /// <summary>The path of this directory.</summary>
29 + public string Path { get; set; }
30 }
31 }
src/WixToolset.Core/Binder.cs
+4 -4
@@ -609,9 +609,9 @@ namespace WixToolset.Core
609 /// <param name="directory">Directory identifier.</param>
610 /// <param name="canonicalize">Canonicalize the path for standard directories.</param>
611 /// <returns>Source path of a directory.</returns>
612 - public static string GetDirectoryPath(Hashtable directories, Hashtable componentIdGenSeeds, string directory, bool canonicalize)
612 + public static string GetDirectoryPath(Dictionary<string, ResolvedDirectory> directories, Dictionary<string, string> componentIdGenSeeds, string directory, bool canonicalize)
613 {
614 - if (!directories.Contains(directory))
614 + if (!directories.ContainsKey(directory))
615 {
616 throw new WixException(WixErrors.ExpectedDirectory(directory));
617 }
@@ -620,7 +620,7 @@ namespace WixToolset.Core
620
621 if (null == resolvedDirectory.Path)
622 {
623 - if (null != componentIdGenSeeds && componentIdGenSeeds.Contains(directory))
623 + if (null != componentIdGenSeeds && componentIdGenSeeds.ContainsKey(directory))
624 {
625 resolvedDirectory.Path = (string)componentIdGenSeeds[directory];
626 }
@@ -670,7 +670,7 @@ namespace WixToolset.Core
670 /// <param name="compressed">Specifies the package is compressed.</param>
671 /// <param name="useLongName">Specifies the package uses long file names.</param>
672 /// <returns>Source path of file relative to package directory.</returns>
673 - public static string GetFileSourcePath(Hashtable directories, string directoryId, string fileName, bool compressed, bool useLongName)
673 + public static string GetFileSourcePath(Dictionary<string, ResolvedDirectory> directories, string directoryId, string fileName, bool compressed, bool useLongName)
674 {
675 string fileSourcePath = Common.GetName(fileName, true, useLongName);
676
src/WixToolset.Core/Compiler.cs
+4 -4
@@ -7137,7 +7137,7 @@ namespace WixToolset
7137 }
7138
7139 // finally, schedule RemoveExistingProducts
7140 - row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixAction);
7140 + row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixAction, new Identifier("InstallExecuteSequence/RemoveExistingProducts", AccessModifier.Public));
7141 row.Set(0, "InstallExecuteSequence");
7142 row.Set(1, "RemoveExistingProducts");
7143 // row.Set(2, condition);
@@ -7641,11 +7641,11 @@ namespace WixToolset
7641 row.Set(4, diskId);
7642 if (YesNoType.Yes == fileCompression)
7643 {
7644 - row.Set(5, 1);
7644 + row.Set(5, true);
7645 }
7646 else if (YesNoType.No == fileCompression)
7647 {
7648 - row.Set(5, 0);
7648 + row.Set(5, false);
7649 }
7650 else // YesNoType.NotSet == fileCompression
7651 {
@@ -9525,7 +9525,7 @@ namespace WixToolset
9525 var patchIdRow = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixPatchId);
9526 patchIdRow.Set(0, patchId);
9527 patchIdRow.Set(1, clientPatchId);
9528 - patchIdRow.Set(2, optimizePatchSizeForLargeFiles ? 1 : 0);
9528 + patchIdRow.Set(2, optimizePatchSizeForLargeFiles);
9529 patchIdRow.Set(3, apiPatchingSymbolFlags);
9530
9531 if (allowRemoval)
src/WixToolset.Core/Linker.cs
+2 -668
@@ -23,9 +23,6 @@ namespace WixToolset.Core
23 private static readonly string emptyGuid = Guid.Empty.ToString("B");
24
25 private bool sectionIdOnRows;
26 - //private WixActionRowCollection standardActions;
27 - //private Output activeOutput;
28 - //private TableDefinitionCollection tableDefinitions;
26
27 /// <summary>
28 /// Creates a linker.
@@ -34,9 +31,6 @@ namespace WixToolset.Core
31 {
32 this.sectionIdOnRows = true; // TODO: what is the correct value for this?
33
37 - //this.standardActions = WindowsInstallerStandard.GetStandardActions();
38 - //this.tableDefinitions = new TableDefinitionCollection(WindowsInstallerStandard.GetTableDefinitions());
39 -
34 //this.extensionData = new List<IExtensionData>();
35 //this.inspectorExtensions = new List<InspectorExtension>();
36 }
@@ -108,11 +102,6 @@ namespace WixToolset.Core
102
103 //this.activeOutput = null;
104
111 -#if MOVE_TO_BACKEND
112 - var actionRows = new List<IntermediateTuple>();
113 - var suppressActionRows = new List<IntermediateTuple>();
114 -#endif
115 -
105 //TableDefinitionCollection customTableDefinitions = new TableDefinitionCollection();
106 //IntermediateTuple customRows = new List<IntermediateTuple>();
107
@@ -232,7 +221,7 @@ namespace WixToolset.Core
221 }
222
223 // Report duplicates that would ultimately end up being primary key collisions.
235 - ReportConflictingSymbolsCommand reportDupes = new ReportConflictingSymbolsCommand(find.PossiblyConflictingSymbols, resolve.ResolvedSections);
224 + var reportDupes = new ReportConflictingSymbolsCommand(find.PossiblyConflictingSymbols, resolve.ResolvedSections);
225 reportDupes.Execute();
226
227 if (Messaging.Instance.EncounteredError)
@@ -394,19 +383,6 @@ namespace WixToolset.Core
383 }
384 break;
385
397 -#if MOVE_TO_BACKEND
398 - case TupleDefinitionType.WixAction:
399 - //if (this.sectionIdOnRows)
400 - //{
401 - // foreach (Row row in table.Rows)
402 - // {
403 - // row.SectionId = sectionId;
404 - // }
405 - //}
406 - actionRows.Add(tuple);
407 - break;
408 -#endif
409 -
386 #if SOLVE_CUSTOM_TABLE
387 case "WixCustomTable":
388 this.LinkCustomTable(table, customTableDefinitions);
@@ -455,12 +431,6 @@ namespace WixToolset.Core
431 }
432 break;
433
458 -#if MOVE_TO_BACKEND
459 - case TupleDefinitionType.WixSuppressAction:
460 - suppressActionRows.Add(tuple);
461 - break;
462 -#endif
463 -
434 case TupleDefinitionType.WixComplexReference:
435 copyTuple = false;
436 break;
@@ -538,11 +508,6 @@ namespace WixToolset.Core
508 }
509 #endif
510
541 -#if MOVE_TO_BACKEND
542 - // sequence all the actions
543 - this.SequenceActions(actionRows, suppressActionRows);
544 -#endif
545 -
511 #if MOVE_TO_BACKEND
512 // check for missing table and add them or display an error as appropriate
513 switch (this.activeOutput.Type)
@@ -1140,6 +1105,7 @@ namespace WixToolset.Core
1105 }
1106 }
1107 #endif
1108 +
1109 /// <summary>
1110 /// Sends a message to the message delegate if there is one.
1111 /// </summary>
@@ -1726,638 +1692,6 @@ namespace WixToolset.Core
1692 }
1693 #endif
1694
1729 -#if MOVE_TO_BACKEND
1730 - /// <summary>
1731 - /// Set sequence numbers for all the actions and create rows in the output object.
1732 - /// </summary>
1733 - /// <param name="actionRows">Collection of actions to schedule.</param>
1734 - /// <param name="suppressActionRows">Collection of actions to suppress.</param>
1735 - private void SequenceActions(List<IntermediateTuple> actionRows, List<IntermediateTuple> suppressActionRows)
1736 - {
1737 - var overridableActionRows = new WixActionRowCollection();
1738 - var requiredActionRows = new WixActionRowCollection();
1739 - ArrayList scheduledActionRows = new ArrayList();
1740 -
1741 - // gather the required actions for the output type
1742 - if (OutputType.Product == this.activeOutput.Type)
1743 - {
1744 - // AdminExecuteSequence table
1745 - overridableActionRows.Add(this.standardActions[SequenceTable.AdminExecuteSequence, "CostFinalize"]);
1746 - overridableActionRows.Add(this.standardActions[SequenceTable.AdminExecuteSequence, "CostInitialize"]);
1747 - overridableActionRows.Add(this.standardActions[SequenceTable.AdminExecuteSequence, "FileCost"]);
1748 - overridableActionRows.Add(this.standardActions[SequenceTable.AdminExecuteSequence, "InstallAdminPackage"]);
1749 - overridableActionRows.Add(this.standardActions[SequenceTable.AdminExecuteSequence, "InstallFiles"]);
1750 - overridableActionRows.Add(this.standardActions[SequenceTable.AdminExecuteSequence, "InstallFinalize"]);
1751 - overridableActionRows.Add(this.standardActions[SequenceTable.AdminExecuteSequence, "InstallInitialize"]);
1752 - overridableActionRows.Add(this.standardActions[SequenceTable.AdminExecuteSequence, "InstallValidate"]);
1753 -
1754 - // AdminUISequence table
1755 - overridableActionRows.Add(this.standardActions[SequenceTable.AdminUISequence, "CostFinalize"]);
1756 - overridableActionRows.Add(this.standardActions[SequenceTable.AdminUISequence, "CostInitialize"]);
1757 - overridableActionRows.Add(this.standardActions[SequenceTable.AdminUISequence, "ExecuteAction"]);
1758 - overridableActionRows.Add(this.standardActions[SequenceTable.AdminUISequence, "FileCost"]);
1759 -
1760 - // AdvtExecuteSequence table
1761 - overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "CostFinalize"]);
1762 - overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "CostInitialize"]);
1763 - overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "InstallFinalize"]);
1764 - overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "InstallInitialize"]);
1765 - overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "InstallValidate"]);
1766 - overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "PublishFeatures"]);
1767 - overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "PublishProduct"]);
1768 -
1769 - // InstallExecuteSequence table
1770 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "CostFinalize"]);
1771 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "CostInitialize"]);
1772 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "FileCost"]);
1773 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "InstallFinalize"]);
1774 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "InstallInitialize"]);
1775 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "InstallValidate"]);
1776 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "ProcessComponents"]);
1777 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "PublishFeatures"]);
1778 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "PublishProduct"]);
1779 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RegisterProduct"]);
1780 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RegisterUser"]);
1781 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "UnpublishFeatures"]);
1782 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "ValidateProductID"]);
1783 -
1784 - // InstallUISequence table
1785 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "CostFinalize"]);
1786 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "CostInitialize"]);
1787 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "ExecuteAction"]);
1788 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "FileCost"]);
1789 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "ValidateProductID"]);
1790 - }
1791 -
1792 - // gather the required actions for each table
1793 - foreach (Table table in this.activeOutput.Tables)
1794 - {
1795 - switch (table.Name)
1796 - {
1797 - case "AppSearch":
1798 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "AppSearch"], true);
1799 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "AppSearch"], true);
1800 - break;
1801 - case "BindImage":
1802 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "BindImage"], true);
1803 - break;
1804 - case "CCPSearch":
1805 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "AppSearch"], true);
1806 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "CCPSearch"], true);
1807 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RMCCPSearch"], true);
1808 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "AppSearch"], true);
1809 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "CCPSearch"], true);
1810 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "RMCCPSearch"], true);
1811 - break;
1812 - case "Class":
1813 - overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "RegisterClassInfo"], true);
1814 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RegisterClassInfo"], true);
1815 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "UnregisterClassInfo"], true);
1816 - break;
1817 - case "Complus":
1818 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RegisterComPlus"], true);
1819 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "UnregisterComPlus"], true);
1820 - break;
1821 - case "CreateFolder":
1822 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "CreateFolders"], true);
1823 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RemoveFolders"], true);
1824 - break;
1825 - case "DuplicateFile":
1826 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "DuplicateFiles"], true);
1827 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RemoveDuplicateFiles"], true);
1828 - break;
1829 - case "Environment":
1830 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "WriteEnvironmentStrings"], true);
1831 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RemoveEnvironmentStrings"], true);
1832 - break;
1833 - case "Extension":
1834 - overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "RegisterExtensionInfo"], true);
1835 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RegisterExtensionInfo"], true);
1836 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "UnregisterExtensionInfo"], true);
1837 - break;
1838 - case "File":
1839 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "InstallFiles"], true);
1840 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RemoveFiles"], true);
1841 - break;
1842 - case "Font":
1843 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RegisterFonts"], true);
1844 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "UnregisterFonts"], true);
1845 - break;
1846 - case "IniFile":
1847 - case "RemoveIniFile":
1848 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "WriteIniValues"], true);
1849 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RemoveIniValues"], true);
1850 - break;
1851 - case "IsolatedComponent":
1852 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "IsolateComponents"], true);
1853 - break;
1854 - case "LaunchCondition":
1855 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "LaunchConditions"], true);
1856 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "LaunchConditions"], true);
1857 - break;
1858 - case "MIME":
1859 - overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "RegisterMIMEInfo"], true);
1860 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RegisterMIMEInfo"], true);
1861 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "UnregisterMIMEInfo"], true);
1862 - break;
1863 - case "MoveFile":
1864 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "MoveFiles"], true);
1865 - break;
1866 - case "MsiAssembly":
1867 - overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "MsiPublishAssemblies"], true);
1868 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "MsiPublishAssemblies"], true);
1869 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "MsiUnpublishAssemblies"], true);
1870 - break;
1871 - case "MsiServiceConfig":
1872 - case "MsiServiceConfigFailureActions":
1873 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "MsiConfigureServices"], true);
1874 - break;
1875 - case "ODBCDataSource":
1876 - case "ODBCTranslator":
1877 - case "ODBCDriver":
1878 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "SetODBCFolders"], true);
1879 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "InstallODBC"], true);
1880 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RemoveODBC"], true);
1881 - break;
1882 - case "ProgId":
1883 - overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "RegisterProgIdInfo"], true);
1884 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RegisterProgIdInfo"], true);
1885 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "UnregisterProgIdInfo"], true);
1886 - break;
1887 - case "PublishComponent":
1888 - overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "PublishComponents"], true);
1889 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "PublishComponents"], true);
1890 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "UnpublishComponents"], true);
1891 - break;
1892 - case "Registry":
1893 - case "RemoveRegistry":
1894 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "WriteRegistryValues"], true);
1895 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RemoveRegistryValues"], true);
1896 - break;
1897 - case "RemoveFile":
1898 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RemoveFiles"], true);
1899 - break;
1900 - case "SelfReg":
1901 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "SelfRegModules"], true);
1902 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "SelfUnregModules"], true);
1903 - break;
1904 - case "ServiceControl":
1905 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "StartServices"], true);
1906 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "StopServices"], true);
1907 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "DeleteServices"], true);
1908 - break;
1909 - case "ServiceInstall":
1910 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "InstallServices"], true);
1911 - break;
1912 - case "Shortcut":
1913 - overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "CreateShortcuts"], true);
1914 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "CreateShortcuts"], true);
1915 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RemoveShortcuts"], true);
1916 - break;
1917 - case "TypeLib":
1918 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RegisterTypeLibraries"], true);
1919 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "UnregisterTypeLibraries"], true);
1920 - break;
1921 - case "Upgrade":
1922 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "FindRelatedProducts"], true);
1923 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "FindRelatedProducts"], true);
1924 - // Only add the MigrateFeatureStates action if MigrateFeature attribute is set to yes on at least one UpgradeVersion element.
1925 - foreach (Row row in table.Rows)
1926 - {
1927 - int options = (int)row[4];
1928 - if (MsiInterop.MsidbUpgradeAttributesMigrateFeatures == (options & MsiInterop.MsidbUpgradeAttributesMigrateFeatures))
1929 - {
1930 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "MigrateFeatureStates"], true);
1931 - overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "MigrateFeatureStates"], true);
1932 - break;
1933 - }
1934 - }
1935 - break;
1936 - }
1937 - }
1938 -
1939 - // index all the action rows (look for collisions)
1940 - foreach (WixActionRow actionRow in actionRows)
1941 - {
1942 - if (actionRow.Overridable) // overridable action
1943 - {
1944 - WixActionRow collidingActionRow = overridableActionRows[actionRow.SequenceTable, actionRow.Action];
1945 -
1946 - if (null != collidingActionRow)
1947 - {
1948 - this.OnMessage(WixErrors.OverridableActionCollision(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action));
1949 - if (null != collidingActionRow.SourceLineNumbers)
1950 - {
1951 - this.OnMessage(WixErrors.OverridableActionCollision2(collidingActionRow.SourceLineNumbers));
1952 - }
1953 - }
1954 - else
1955 - {
1956 - overridableActionRows.Add(actionRow);
1957 - }
1958 - }
1959 - else // unscheduled/scheduled action
1960 - {
1961 - // unscheduled action (allowed for certain standard actions)
1962 - if (null == actionRow.Before && null == actionRow.After && 0 == actionRow.Sequence)
1963 - {
1964 - WixActionRow standardAction = this.standardActions[actionRow.SequenceTable, actionRow.Action];
1965 -
1966 - if (null != standardAction)
1967 - {
1968 - // populate the sequence from the standard action
1969 - actionRow.Sequence = standardAction.Sequence;
1970 - }
1971 - else // not a supported unscheduled action
1972 - {
1973 - throw new InvalidOperationException(WixStrings.EXP_FoundActionRowWithNoSequenceBeforeOrAfterColumnSet);
1974 - }
1975 - }
1976 -
1977 - WixActionRow collidingActionRow = requiredActionRows[actionRow.SequenceTable, actionRow.Action];
1978 -
1979 - if (null != collidingActionRow)
1980 - {
1981 - this.OnMessage(WixErrors.ActionCollision(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action));
1982 - if (null != collidingActionRow.SourceLineNumbers)
1983 - {
1984 - this.OnMessage(WixErrors.ActionCollision2(collidingActionRow.SourceLineNumbers));
1985 - }
1986 - }
1987 - else
1988 - {
1989 - requiredActionRows.Add(actionRow.Clone());
1990 - }
1991 - }
1992 - }
1993 -
1994 - // add the overridable action rows that are not overridden to the required action rows
1995 - foreach (WixActionRow actionRow in overridableActionRows)
1996 - {
1997 - if (null == requiredActionRows[actionRow.SequenceTable, actionRow.Action])
1998 - {
1999 - requiredActionRows.Add(actionRow.Clone());
2000 - }
2001 - }
2002 -
2003 - // suppress the required actions that are overridable
2004 - foreach (Row suppressActionRow in suppressActionRows)
2005 - {
2006 - SequenceTable sequenceTable = (SequenceTable)Enum.Parse(typeof(SequenceTable), (string)suppressActionRow[0]);
2007 - string action = (string)suppressActionRow[1];
2008 -
2009 - // get the action being suppressed (if it exists)
2010 - WixActionRow requiredActionRow = requiredActionRows[sequenceTable, action];
2011 -
2012 - // if there is an overridable row to suppress; suppress it
2013 - // there is no warning if there is no action to suppress because the action may be suppressed from a merge module in the binder
2014 - if (null != requiredActionRow)
2015 - {
2016 - if (requiredActionRow.Overridable)
2017 - {
2018 - this.OnMessage(WixWarnings.SuppressAction(suppressActionRow.SourceLineNumbers, action, sequenceTable.ToString()));
2019 - if (null != requiredActionRow.SourceLineNumbers)
2020 - {
2021 - this.OnMessage(WixWarnings.SuppressAction2(requiredActionRow.SourceLineNumbers));
2022 - }
2023 - requiredActionRows.Remove(sequenceTable, action);
2024 - }
2025 - else // suppressing a non-overridable action row
2026 - {
2027 - this.OnMessage(WixErrors.SuppressNonoverridableAction(suppressActionRow.SourceLineNumbers, sequenceTable.ToString(), action));
2028 - if (null != requiredActionRow.SourceLineNumbers)
2029 - {
2030 - this.OnMessage(WixErrors.SuppressNonoverridableAction2(requiredActionRow.SourceLineNumbers));
2031 - }
2032 - }
2033 - }
2034 - }
2035 -
2036 - // create a copy of the required action rows so that new rows can be added while enumerating
2037 - WixActionRow[] copyOfRequiredActionRows = new WixActionRow[requiredActionRows.Count];
2038 - requiredActionRows.CopyTo(copyOfRequiredActionRows, 0);
2039 -
2040 - // build up dependency trees of the relatively scheduled actions
2041 - foreach (WixActionRow actionRow in copyOfRequiredActionRows)
2042 - {
2043 - if (0 == actionRow.Sequence)
2044 - {
2045 - // check for standard actions that don't have a sequence number in a merge module
2046 - if (OutputType.Module == this.activeOutput.Type && WindowsInstallerStandard.IsStandardAction(actionRow.Action))
2047 - {
2048 - this.OnMessage(WixErrors.StandardActionRelativelyScheduledInModule(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action));
2049 - }
2050 -
2051 - this.SequenceActionRow(actionRow, requiredActionRows);
2052 - }
2053 - else if (OutputType.Module == this.activeOutput.Type && 0 < actionRow.Sequence && !WindowsInstallerStandard.IsStandardAction(actionRow.Action)) // check for custom actions and dialogs that have a sequence number
2054 - {
2055 - this.OnMessage(WixErrors.CustomActionSequencedInModule(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action));
2056 - }
2057 - }
2058 -
2059 - // look for standard actions with sequence restrictions that aren't necessarily scheduled based on the presence of a particular table
2060 - if (requiredActionRows.Contains(SequenceTable.InstallExecuteSequence, "DuplicateFiles") && !requiredActionRows.Contains(SequenceTable.InstallExecuteSequence, "InstallFiles"))
2061 - {
2062 - requiredActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "InstallFiles"], true);
2063 - }
2064 -
2065 - // schedule actions
2066 - if (OutputType.Module == this.activeOutput.Type)
2067 - {
2068 - // add the action row to the list of scheduled action rows
2069 - scheduledActionRows.AddRange(requiredActionRows);
2070 - }
2071 - else
2072 - {
2073 - // process each sequence table individually
2074 - foreach (SequenceTable sequenceTable in Enum.GetValues(typeof(SequenceTable)))
2075 - {
2076 - // create a collection of just the action rows in this sequence
2077 - WixActionRowCollection sequenceActionRows = new WixActionRowCollection();
2078 - foreach (WixActionRow actionRow in requiredActionRows)
2079 - {
2080 - if (sequenceTable == actionRow.SequenceTable)
2081 - {
2082 - sequenceActionRows.Add(actionRow);
2083 - }
2084 - }
2085 -
2086 - // schedule the absolutely scheduled actions (by sorting them by their sequence numbers)
2087 - ArrayList absoluteActionRows = new ArrayList();
2088 - foreach (WixActionRow actionRow in sequenceActionRows)
2089 - {
2090 - if (0 != actionRow.Sequence)
2091 - {
2092 - // look for sequence number collisions
2093 - foreach (WixActionRow sequenceScheduledActionRow in absoluteActionRows)
2094 - {
2095 - if (sequenceScheduledActionRow.Sequence == actionRow.Sequence)
2096 - {
2097 - this.OnMessage(WixWarnings.ActionSequenceCollision(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action, sequenceScheduledActionRow.Action, actionRow.Sequence));
2098 - if (null != sequenceScheduledActionRow.SourceLineNumbers)
2099 - {
2100 - this.OnMessage(WixWarnings.ActionSequenceCollision2(sequenceScheduledActionRow.SourceLineNumbers));
2101 - }
2102 - }
2103 - }
2104 -
2105 - absoluteActionRows.Add(actionRow);
2106 - }
2107 - }
2108 - absoluteActionRows.Sort();
2109 -
2110 - // schedule the relatively scheduled actions (by resolving the dependency trees)
2111 - int previousUsedSequence = 0;
2112 - ArrayList relativeActionRows = new ArrayList();
2113 - for (int j = 0; j < absoluteActionRows.Count; j++)
2114 - {
2115 - WixActionRow absoluteActionRow = (WixActionRow)absoluteActionRows[j];
2116 - int unusedSequence;
2117 -
2118 - // get all the relatively scheduled action rows occuring before this absolutely scheduled action row
2119 - RowIndexedList<WixActionRow> allPreviousActionRows = new RowIndexedList<WixActionRow>();
2120 - absoluteActionRow.GetAllPreviousActionRows(sequenceTable, allPreviousActionRows);
2121 -
2122 - // get all the relatively scheduled action rows occuring after this absolutely scheduled action row
2123 - RowIndexedList<WixActionRow> allNextActionRows = new RowIndexedList<WixActionRow>();
2124 - absoluteActionRow.GetAllNextActionRows(sequenceTable, allNextActionRows);
2125 -
2126 - // check for relatively scheduled actions occuring before/after a special action (these have a negative sequence number)
2127 - if (0 > absoluteActionRow.Sequence && (0 < allPreviousActionRows.Count || 0 < allNextActionRows.Count))
2128 - {
2129 - // create errors for all the before actions
2130 - foreach (WixActionRow actionRow in allPreviousActionRows)
2131 - {
2132 - this.OnMessage(WixErrors.ActionScheduledRelativeToTerminationAction(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action, absoluteActionRow.Action));
2133 - }
2134 -
2135 - // create errors for all the after actions
2136 - foreach (WixActionRow actionRow in allNextActionRows)
2137 - {
2138 - this.OnMessage(WixErrors.ActionScheduledRelativeToTerminationAction(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action, absoluteActionRow.Action));
2139 - }
2140 -
2141 - // if there is source line information for the absolutely scheduled action display it
2142 - if (null != absoluteActionRow.SourceLineNumbers)
2143 - {
2144 - this.OnMessage(WixErrors.ActionScheduledRelativeToTerminationAction2(absoluteActionRow.SourceLineNumbers));
2145 - }
2146 -
2147 - continue;
2148 - }
2149 -
2150 - // schedule the action rows before this one
2151 - unusedSequence = absoluteActionRow.Sequence - 1;
2152 - for (int i = allPreviousActionRows.Count - 1; i >= 0; i--)
2153 - {
2154 - WixActionRow relativeActionRow = (WixActionRow)allPreviousActionRows[i];
2155 -
2156 - // look for collisions
2157 - if (unusedSequence == previousUsedSequence)
2158 - {
2159 - this.OnMessage(WixErrors.NoUniqueActionSequenceNumber(relativeActionRow.SourceLineNumbers, relativeActionRow.SequenceTable.ToString(), relativeActionRow.Action, absoluteActionRow.Action));
2160 - if (null != absoluteActionRow.SourceLineNumbers)
2161 - {
2162 - this.OnMessage(WixErrors.NoUniqueActionSequenceNumber2(absoluteActionRow.SourceLineNumbers));
2163 - }
2164 -
2165 - unusedSequence++;
2166 - }
2167 -
2168 - relativeActionRow.Sequence = unusedSequence;
2169 - relativeActionRows.Add(relativeActionRow);
2170 -
2171 - unusedSequence--;
2172 - }
2173 -
2174 - // determine the next used action sequence number
2175 - int nextUsedSequence;
2176 - if (absoluteActionRows.Count > j + 1)
2177 - {
2178 - nextUsedSequence = ((WixActionRow)absoluteActionRows[j + 1]).Sequence;
2179 - }
2180 - else
2181 - {
2182 - nextUsedSequence = short.MaxValue + 1;
2183 - }
2184 -
2185 - // schedule the action rows after this one
2186 - unusedSequence = absoluteActionRow.Sequence + 1;
2187 - for (int i = 0; i < allNextActionRows.Count; i++)
2188 - {
2189 - WixActionRow relativeActionRow = (WixActionRow)allNextActionRows[i];
2190 -
2191 - if (unusedSequence == nextUsedSequence)
2192 - {
2193 - this.OnMessage(WixErrors.NoUniqueActionSequenceNumber(relativeActionRow.SourceLineNumbers, relativeActionRow.SequenceTable.ToString(), relativeActionRow.Action, absoluteActionRow.Action));
2194 - if (null != absoluteActionRow.SourceLineNumbers)
2195 - {
2196 - this.OnMessage(WixErrors.NoUniqueActionSequenceNumber2(absoluteActionRow.SourceLineNumbers));
2197 - }
2198 -
2199 - unusedSequence--;
2200 - }
2201 -
2202 - relativeActionRow.Sequence = unusedSequence;
2203 - relativeActionRows.Add(relativeActionRow);
2204 -
2205 - unusedSequence++;
2206 - }
2207 -
2208 - // keep track of this sequence number as the previous used sequence number for the next iteration
2209 - previousUsedSequence = absoluteActionRow.Sequence;
2210 - }
2211 -
2212 - // add the absolutely and relatively scheduled actions to the list of scheduled actions
2213 - scheduledActionRows.AddRange(absoluteActionRows);
2214 - scheduledActionRows.AddRange(relativeActionRows);
2215 - }
2216 - }
2217 -
2218 - // create the action rows for sequences that are not suppressed
2219 - foreach (WixActionRow actionRow in scheduledActionRows)
2220 - {
2221 - // get the table definition for the action (and ensure the proper table exists for a module)
2222 - TableDefinition sequenceTableDefinition = null;
2223 - switch (actionRow.SequenceTable)
2224 - {
2225 - case SequenceTable.AdminExecuteSequence:
2226 - if (OutputType.Module == this.activeOutput.Type)
2227 - {
2228 - this.activeOutput.EnsureTable(this.tableDefinitions["AdminExecuteSequence"]);
2229 - sequenceTableDefinition = this.tableDefinitions["ModuleAdminExecuteSequence"];
2230 - }
2231 - else
2232 - {
2233 - sequenceTableDefinition = this.tableDefinitions["AdminExecuteSequence"];
2234 - }
2235 - break;
2236 - case SequenceTable.AdminUISequence:
2237 - if (OutputType.Module == this.activeOutput.Type)
2238 - {
2239 - this.activeOutput.EnsureTable(this.tableDefinitions["AdminUISequence"]);
2240 - sequenceTableDefinition = this.tableDefinitions["ModuleAdminUISequence"];
2241 - }
2242 - else
2243 - {
2244 - sequenceTableDefinition = this.tableDefinitions["AdminUISequence"];
2245 - }
2246 - break;
2247 - case SequenceTable.AdvtExecuteSequence:
2248 - if (OutputType.Module == this.activeOutput.Type)
2249 - {
2250 - this.activeOutput.EnsureTable(this.tableDefinitions["AdvtExecuteSequence"]);
2251 - sequenceTableDefinition = this.tableDefinitions["ModuleAdvtExecuteSequence"];
2252 - }
2253 - else
2254 - {
2255 - sequenceTableDefinition = this.tableDefinitions["AdvtExecuteSequence"];
2256 - }
2257 - break;
2258 - case SequenceTable.InstallExecuteSequence:
2259 - if (OutputType.Module == this.activeOutput.Type)
2260 - {
2261 - this.activeOutput.EnsureTable(this.tableDefinitions["InstallExecuteSequence"]);
2262 - sequenceTableDefinition = this.tableDefinitions["ModuleInstallExecuteSequence"];
2263 - }
2264 - else
2265 - {
2266 - sequenceTableDefinition = this.tableDefinitions["InstallExecuteSequence"];
2267 - }
2268 - break;
2269 - case SequenceTable.InstallUISequence:
2270 - if (OutputType.Module == this.activeOutput.Type)
2271 - {
2272 - this.activeOutput.EnsureTable(this.tableDefinitions["InstallUISequence"]);
2273 - sequenceTableDefinition = this.tableDefinitions["ModuleInstallUISequence"];
2274 - }
2275 - else
2276 - {
2277 - sequenceTableDefinition = this.tableDefinitions["InstallUISequence"];
2278 - }
2279 - break;
2280 - }
2281 -
2282 - // create the action sequence row in the output
2283 - Table sequenceTable = this.activeOutput.EnsureTable(sequenceTableDefinition);
2284 - Row row = sequenceTable.CreateRow(actionRow.SourceLineNumbers);
2285 - if (this.sectionIdOnRows)
2286 - {
2287 - row.SectionId = actionRow.SectionId;
2288 - }
2289 -
2290 - if (OutputType.Module == this.activeOutput.Type)
2291 - {
2292 - row[0] = actionRow.Action;
2293 - if (0 != actionRow.Sequence)
2294 - {
2295 - row[1] = actionRow.Sequence;
2296 - }
2297 - else
2298 - {
2299 - bool after = (null == actionRow.Before);
2300 - row[2] = after ? actionRow.After : actionRow.Before;
2301 - row[3] = after ? 1 : 0;
2302 - }
2303 - row[4] = actionRow.Condition;
2304 - }
2305 - else
2306 - {
2307 - row[0] = actionRow.Action;
2308 - row[1] = actionRow.Condition;
2309 - row[2] = actionRow.Sequence;
2310 - }
2311 - }
2312 - }
2313 -
2314 - /// <summary>
2315 - /// Sequence an action before or after a standard action.
2316 - /// </summary>
2317 - /// <param name="actionRow">The action row to be sequenced.</param>
2318 - /// <param name="requiredActionRows">Collection of actions which must be included.</param>
2319 - [SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters", MessageId = "System.InvalidOperationException.#ctor(System.String)")]
2320 - private void SequenceActionRow(WixActionRow actionRow, WixActionRowCollection requiredActionRows)
2321 - {
2322 - bool after = false;
2323 - if (actionRow.After != null)
2324 - {
2325 - after = true;
2326 - }
2327 - else if (actionRow.Before == null)
2328 - {
2329 - throw new InvalidOperationException(WixStrings.EXP_FoundActionRowWithNoSequenceBeforeOrAfterColumnSet);
2330 - }
2331 -
2332 - string parentActionName = (after ? actionRow.After : actionRow.Before);
2333 - WixActionRow parentActionRow = requiredActionRows[actionRow.SequenceTable, parentActionName];
2334 -
2335 - if (null == parentActionRow)
2336 - {
2337 - parentActionRow = this.standardActions[actionRow.SequenceTable, parentActionName];
2338 -
2339 - // if the missing parent action is a standard action (with a suggested sequence number), add it
2340 - if (null != parentActionRow)
2341 - {
2342 - // Create a clone to avoid modifying the static copy of the object.
2343 - parentActionRow = parentActionRow.Clone();
2344 - requiredActionRows.Add(parentActionRow);
2345 - }
2346 - else
2347 - {
2348 - throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_FoundActionRowWinNonExistentAction, (after ? "After" : "Before"), parentActionName));
2349 - }
2350 - }
2351 - else if (actionRow == parentActionRow || actionRow.ContainsChildActionRow(parentActionRow)) // cycle detected
2352 - {
2353 - throw new WixException(WixErrors.ActionCircularDependency(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action, parentActionRow.Action));
2354 - }
2355 -
2356 - // Add this action to the appropriate list of dependent action rows.
2357 - WixActionRowCollection relatedRows = (after ? parentActionRow.NextActionRows : parentActionRow.PreviousActionRows);
2358 - relatedRows.Add(actionRow);
2359 - }
2360 -#endif
1695
1696 /// <summary>
1697 /// Resolve features for columns that have null guid placeholders.
src/WixToolset.Core/WindowsInstallerStandard.cs deleted
-260
@@ -1,260 +0,0 @@
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
4 -{
5 - using System.Collections.Generic;
6 - using WixToolset.Data;
7 - using WixToolset.Data.Tuples;
8 -
9 - internal class WindowsInstallerStandard
10 - {
11 - private static readonly HashSet<string> standardActionNames = new HashSet<string>
12 - {
13 - "AllocateRegistrySpace",
14 - "AppSearch",
15 - "BindImage",
16 - "CCPSearch",
17 - "CostFinalize",
18 - "CostInitialize",
19 - "CreateFolders",
20 - "CreateShortcuts",
21 - "DeleteServices",
22 - "DisableRollback",
23 - "DuplicateFiles",
24 - "ExecuteAction",
25 - "FileCost",
26 - "FindRelatedProducts",
27 - "ForceReboot",
28 - "InstallAdminPackage",
29 - "InstallExecute",
30 - "InstallExecuteAgain",
31 - "InstallFiles",
32 - "InstallFinalize",
33 - "InstallInitialize",
34 - "InstallODBC",
35 - "InstallServices",
36 - "InstallSFPCatalogFile",
37 - "InstallValidate",
38 - "IsolateComponents",
39 - "LaunchConditions",
40 - "MigrateFeatureStates",
41 - "MoveFiles",
42 - "MsiConfigureServices",
43 - "MsiPublishAssemblies",
44 - "MsiUnpublishAssemblies",
45 - "PatchFiles",
46 - "ProcessComponents",
47 - "PublishComponents",
48 - "PublishFeatures",
49 - "PublishProduct",
50 - "RegisterClassInfo",
51 - "RegisterComPlus",
52 - "RegisterExtensionInfo",
53 - "RegisterFonts",
54 - "RegisterMIMEInfo",
55 - "RegisterProduct",
56 - "RegisterProgIdInfo",
57 - "RegisterTypeLibraries",
58 - "RegisterUser",
59 - "RemoveDuplicateFiles",
60 - "RemoveEnvironmentStrings",
61 - "RemoveExistingProducts",
62 - "RemoveFiles",
63 - "RemoveFolders",
64 - "RemoveIniValues",
65 - "RemoveODBC",
66 - "RemoveRegistryValues",
67 - "RemoveShortcuts",
68 - "ResolveSource",
69 - "RMCCPSearch",
70 - "ScheduleReboot",
71 - "SelfRegModules",
72 - "SelfUnregModules",
73 - "SetODBCFolders",
74 - "StartServices",
75 - "StopServices",
76 - "UnpublishComponents",
77 - "UnpublishFeatures",
78 - "UnregisterClassInfo",
79 - "UnregisterComPlus",
80 - "UnregisterExtensionInfo",
81 - "UnregisterFonts",
82 - "UnregisterMIMEInfo",
83 - "UnregisterProgIdInfo",
84 - "UnregisterTypeLibraries",
85 - "ValidateProductID",
86 - "WriteEnvironmentStrings",
87 - "WriteIniValues",
88 - "WriteRegistryValues",
89 - };
90 -
91 - private static readonly WixActionTuple[] standardActions = new[]
92 - {
93 - new WixActionTuple(null, new Identifier("AdminExecuteSequence/InstallInitialize", AccessModifier.Public)) { Action="InstallInitialize", Sequence=1500, SequenceTable=SequenceTable.AdminExecuteSequence },
94 - new WixActionTuple(null, new Identifier("AdvtExecuteSequence/InstallInitialize", AccessModifier.Public)) { Action="InstallInitialize", Sequence=1500, SequenceTable=SequenceTable.AdvtExecuteSequence },
95 - new WixActionTuple(null, new Identifier("InstallExecuteSequence/InstallInitialize", AccessModifier.Public)) { Action="InstallInitialize", Sequence=1500, SequenceTable=SequenceTable.InstallExecuteSequence },
96 -
97 - new WixActionTuple(null, new Identifier("InstallExecuteSequence/InstallExecute", AccessModifier.Public)) { Action="InstallExecute", Sequence=6500, SequenceTable=SequenceTable.InstallExecuteSequence, Condition="NOT Installed" },
98 -
99 - new WixActionTuple(null, new Identifier("InstallExecuteSequence/InstallExecuteAgain", AccessModifier.Public)) { Action="InstallExecuteAgain", Sequence=6550, SequenceTable=SequenceTable.InstallExecuteSequence, Condition="NOT Installed" },
100 -
101 - new WixActionTuple(null, new Identifier("AdminExecuteSequence/InstallFinalize", AccessModifier.Public)) { Action="InstallFinalize", Sequence=6600, SequenceTable=SequenceTable.AdminExecuteSequence },
102 - new WixActionTuple(null, new Identifier("AdvtExecuteSequence/InstallFinalize", AccessModifier.Public)) { Action="InstallFinalize", Sequence=6600, SequenceTable=SequenceTable.AdvtExecuteSequence },
103 - new WixActionTuple(null, new Identifier("InstallExecuteSequence/InstallFinalize", AccessModifier.Public)) { Action="InstallFinalize", Sequence=6600, SequenceTable=SequenceTable.InstallExecuteSequence },
104 -
105 - new WixActionTuple(null, new Identifier("AdminExecuteSequence/InstallFiles", AccessModifier.Public)) { Action="InstallFiles", Sequence=4000, SequenceTable=SequenceTable.AdminExecuteSequence },
106 - new WixActionTuple(null, new Identifier("InstallExecuteSequence/InstallFiles", AccessModifier.Public)) { Action="InstallFiles", Sequence=4000, SequenceTable=SequenceTable.InstallExecuteSequence },
107 -
108 - new WixActionTuple(null, new Identifier("AdminExecuteSequence/InstallAdminPackage", AccessModifier.Public)) { Action="InstallAdminPackage", Sequence=3900, SequenceTable=SequenceTable.AdminExecuteSequence },
109 -
110 - new WixActionTuple(null, new Identifier("AdminExecuteSequence/FileCost", AccessModifier.Public)) { Action="FileCost", Sequence=900, SequenceTable=SequenceTable.AdminExecuteSequence },
111 - new WixActionTuple(null, new Identifier("InstallExecuteSequence/FileCost", AccessModifier.Public)) { Action="FileCost", Sequence=900, SequenceTable=SequenceTable.InstallExecuteSequence },
112 - new WixActionTuple(null, new Identifier("InstallUISequence/FileCost", AccessModifier.Public)) { Action="FileCost", Sequence=900, SequenceTable=SequenceTable.InstallUISequence },
113 -
114 - new WixActionTuple(null, new Identifier("AdminExecuteSequence/CostInitialize", AccessModifier.Public)) { Action="CostInitialize", Sequence=800, SequenceTable=SequenceTable.AdminExecuteSequence },
115 - new WixActionTuple(null, new Identifier("AdminUISequence/CostInitialize", AccessModifier.Public)) { Action="CostInitialize", Sequence=800, SequenceTable=SequenceTable.AdminUISequence },
116 - new WixActionTuple(null, new Identifier("AdvtExecuteSequence/CostInitialize", AccessModifier.Public)) { Action="CostInitialize", Sequence=800, SequenceTable=SequenceTable.AdvtExecuteSequence },
117 - new WixActionTuple(null, new Identifier("InstallExecuteSequence/CostInitialize", AccessModifier.Public)) { Action="CostInitialize", Sequence=800, SequenceTable=SequenceTable.InstallExecuteSequence },
118 - new WixActionTuple(null, new Identifier("InstallUISequence/CostInitialize", AccessModifier.Public)) { Action="CostInitialize", Sequence=800, SequenceTable=SequenceTable.InstallUISequence },
119 -
120 - new WixActionTuple(null, new Identifier("AdminExecuteSequence/CostFinalize", AccessModifier.Public)) { Action="CostFinalize", Sequence=1000, SequenceTable=SequenceTable.AdminExecuteSequence },
121 - new WixActionTuple(null, new Identifier("AdminUISequence/CostFinalize", AccessModifier.Public)) { Action="CostFinalize", Sequence=1000, SequenceTable=SequenceTable.AdminUISequence },
122 - new WixActionTuple(null, new Identifier("AdvtExecuteSequence/CostFinalize", AccessModifier.Public)) { Action="CostFinalize", Sequence=1000, SequenceTable=SequenceTable.AdvtExecuteSequence },
123 - new WixActionTuple(null, new Identifier("InstallExecuteSequence/CostFinalize", AccessModifier.Public)) { Action="CostFinalize", Sequence=1000, SequenceTable=SequenceTable.InstallExecuteSequence },
124 - new WixActionTuple(null, new Identifier("InstallUISequence/CostFinalize", AccessModifier.Public)) { Action="CostFinalize", Sequence=1000, SequenceTable=SequenceTable.InstallUISequence },
125 -
126 - new WixActionTuple(null, new Identifier("AdminExecuteSequence/InstallValidate", AccessModifier.Public)) { Action="InstallValidate", Sequence=1400, SequenceTable=SequenceTable.AdminExecuteSequence },
127 - new WixActionTuple(null, new Identifier("AdvtExecuteSequence/InstallValidate", AccessModifier.Public)) { Action="InstallValidate", Sequence=1400, SequenceTable=SequenceTable.AdvtExecuteSequence },
128 - new WixActionTuple(null, new Identifier("InstallExecuteSequence/InstallValidate", AccessModifier.Public)) { Action="InstallValidate", Sequence=1400, SequenceTable=SequenceTable.InstallExecuteSequence },
129 -
130 - new WixActionTuple(null, new Identifier("AdminUISequence/ExecuteAction", AccessModifier.Public)) { Action="ExecuteAction", Sequence=1300, SequenceTable=SequenceTable.AdminUISequence },
131 - new WixActionTuple(null, new Identifier("InstallUISequence/ExecuteAction", AccessModifier.Public)) { Action="ExecuteAction", Sequence=1300, SequenceTable=SequenceTable.InstallUISequence },
132 -
133 - new WixActionTuple(null, new Identifier("AdvtExecuteSequence/CreateShortcuts", AccessModifier.Public)) { Action="CreateShortcuts", Sequence=4500, SequenceTable=SequenceTable.AdvtExecuteSequence },
134 - new WixActionTuple(null, new Identifier("InstallExecuteSequence/CreateShortcuts", AccessModifier.Public)) { Action="CreateShortcuts", Sequence=4500, SequenceTable=SequenceTable.InstallExecuteSequence },
135 -
136 - new WixActionTuple(null, new Identifier("AdvtExecuteSequence/MsiPublishAssemblies", AccessModifier.Public)) { Action="MsiPublishAssemblies", Sequence=6250, SequenceTable=SequenceTable.AdvtExecuteSequence },
137 - new WixActionTuple(null, new Identifier("InstallExecuteSequence/MsiPublishAssemblies", AccessModifier.Public)) { Action="MsiPublishAssemblies", Sequence=6250, SequenceTable=SequenceTable.InstallExecuteSequence },
138 -
139 - //<action name="PublishComponents" sequence="6200" AdvtExecuteSequence="yes" InstallExecuteSequence="yes" />
140 - //<action name="PublishFeatures" sequence="6300" AdvtExecuteSequence="yes" InstallExecuteSequence="yes" />
141 - //<action name="PublishProduct" sequence="6400" AdvtExecuteSequence="yes" InstallExecuteSequence="yes" />
142 - //<action name="RegisterClassInfo" sequence="4600" AdvtExecuteSequence="yes" InstallExecuteSequence="yes" />
143 - //<action name="RegisterExtensionInfo" sequence="4700" AdvtExecuteSequence="yes" InstallExecuteSequence="yes" />
144 - //<action name="RegisterMIMEInfo" sequence="4900" AdvtExecuteSequence="yes" InstallExecuteSequence="yes" />
145 - //<action name="RegisterProgIdInfo" sequence="4800" AdvtExecuteSequence="yes" InstallExecuteSequence="yes" />
146 - //<action name="AllocateRegistrySpace" condition="NOT Installed" sequence="1550" InstallExecuteSequence="yes" />
147 - //<action name="AppSearch" sequence="50" InstallExecuteSequence="yes" InstallUISequence="yes" />
148 - //<action name="BindImage" sequence="4300" InstallExecuteSequence="yes" />
149 - //<action name="CreateFolders" sequence="3700" InstallExecuteSequence="yes" />
150 - //<action name="DuplicateFiles" sequence="4210" InstallExecuteSequence="yes" />
151 - //<action name="FindRelatedProducts" sequence="25" InstallExecuteSequence="yes" InstallUISequence="yes" />
152 - //<action name="InstallODBC" sequence="5400" InstallExecuteSequence="yes" />
153 - //<action name="InstallServices" condition="VersionNT" sequence="5800" InstallExecuteSequence="yes" />
154 - //<action name="MsiConfigureServices" condition="VersionNT>=600" sequence="5850" InstallExecuteSequence="yes" />
155 - //<action name="IsolateComponents" sequence="950" InstallExecuteSequence="yes" InstallUISequence="yes" />
156 - //<action name="LaunchConditions" sequence="100" AdminExecuteSequence="yes" AdminUISequence="yes" InstallExecuteSequence="yes" InstallUISequence="yes" />
157 - //<action name="MigrateFeatureStates" sequence="1200" InstallExecuteSequence="yes" InstallUISequence="yes" />
158 - //<action name="MoveFiles" sequence="3800" InstallExecuteSequence="yes" />
159 - //<action name="PatchFiles" sequence="4090" AdminExecuteSequence="yes" InstallExecuteSequence="yes" />
160 - //<action name="ProcessComponents" sequence="1600" InstallExecuteSequence="yes" />
161 - //<action name="RegisterComPlus" sequence="5700" InstallExecuteSequence="yes" />
162 - //<action name="RegisterFonts" sequence="5300" InstallExecuteSequence="yes" />
163 - //<action name="RegisterProduct" sequence="6100" InstallExecuteSequence="yes" />
164 - //<action name="RegisterTypeLibraries" sequence="5500" InstallExecuteSequence="yes" />
165 - //<action name="RegisterUser" sequence="6000" InstallExecuteSequence="yes" />
166 - //<action name="RemoveDuplicateFiles" sequence="3400" InstallExecuteSequence="yes" />
167 - //<action name="RemoveEnvironmentStrings" sequence="3300" InstallExecuteSequence="yes" />
168 - //<action name="RemoveFiles" sequence="3500" InstallExecuteSequence="yes" />
169 - //<action name="RemoveFolders" sequence="3600" InstallExecuteSequence="yes" />
170 - //<action name="RemoveIniValues" sequence="3100" InstallExecuteSequence="yes" />
171 - //<action name="RemoveODBC" sequence="2400" InstallExecuteSequence="yes" />
172 - //<action name="RemoveRegistryValues" sequence="2600" InstallExecuteSequence="yes" />
173 - //<action name="RemoveShortcuts" sequence="3200" InstallExecuteSequence="yes" />
174 - //<action name="SelfRegModules" sequence="5600" InstallExecuteSequence="yes" />
175 - //<action name="SelfUnregModules" sequence="2200" InstallExecuteSequence="yes" />
176 - //<action name="SetODBCFolders" sequence="1100" InstallExecuteSequence="yes" />
177 -
178 -
179 - new WixActionTuple(null, new Identifier("InstallExecuteSequence/CCPSearch", AccessModifier.Public)) { Action="CCPSearch", Sequence=500, SequenceTable=SequenceTable.InstallExecuteSequence, Condition="NOT Installed" },
180 - new WixActionTuple(null, new Identifier("InstallUISequence/CCPSearch", AccessModifier.Public)) { Action="CCPSearch", Sequence=500, SequenceTable=SequenceTable.InstallUISequence, Condition="NOT Installed" },
181 -
182 - new WixActionTuple(null, new Identifier("InstallExecuteSequence/DeleteServices", AccessModifier.Public)) { Action="DeleteServices", Sequence=2000, SequenceTable=SequenceTable.InstallExecuteSequence, Condition="VersionNT" },
183 -
184 - new WixActionTuple(null, new Identifier("InstallExecuteSequence/RMCCPSearch", AccessModifier.Public)) { Action="RMCCPSearch", Sequence=600, SequenceTable=SequenceTable.InstallExecuteSequence, Condition="NOT Installed" },
185 - new WixActionTuple(null, new Identifier("InstallUISequence/RMCCPSearch", AccessModifier.Public)) { Action="RMCCPSearch", Sequence=600, SequenceTable=SequenceTable.InstallUISequence, Condition="NOT Installed" },
186 -
187 - new WixActionTuple(null, new Identifier("InstallExecuteSequence/StartServices", AccessModifier.Public)) { Action="StartServices", Sequence=5900, SequenceTable=SequenceTable.InstallExecuteSequence, Condition="VersionNT" },
188 - new WixActionTuple(null, new Identifier("InstallExecuteSequence/StopServices", AccessModifier.Public)) { Action="StopServices", Sequence=1900, SequenceTable=SequenceTable.InstallExecuteSequence, Condition="VersionNT" },
189 -
190 - new WixActionTuple(null, new Identifier("InstallExecuteSequence/MsiUnpublishAssemblies", AccessModifier.Public)) { Action="MsiUnpublishAssemblies", Sequence=1750, SequenceTable=SequenceTable.InstallExecuteSequence },
191 - new WixActionTuple(null, new Identifier("InstallExecuteSequence/UnpublishComponents", AccessModifier.Public)) { Action="UnpublishComponents", Sequence=1700, SequenceTable=SequenceTable.InstallExecuteSequence },
192 - new WixActionTuple(null, new Identifier("InstallExecuteSequence/UnpublishFeatures", AccessModifier.Public)) { Action="UnpublishFeatures", Sequence=1800, SequenceTable=SequenceTable.InstallExecuteSequence },
193 - new WixActionTuple(null, new Identifier("InstallExecuteSequence/UnregisterClassInfo", AccessModifier.Public)) { Action="UnregisterClassInfo", Sequence=2700, SequenceTable=SequenceTable.InstallExecuteSequence },
194 - new WixActionTuple(null, new Identifier("InstallExecuteSequence/UnregisterComPlus", AccessModifier.Public)) { Action="UnregisterComPlus", Sequence=2100, SequenceTable=SequenceTable.InstallExecuteSequence },
195 - new WixActionTuple(null, new Identifier("InstallExecuteSequence/UnregisterExtensionInfo", AccessModifier.Public)) { Action="UnregisterExtensionInfo", Sequence=2800, SequenceTable=SequenceTable.InstallExecuteSequence },
196 - new WixActionTuple(null, new Identifier("InstallExecuteSequence/UnregisterFonts", AccessModifier.Public)) { Action="UnregisterFonts", Sequence=2500, SequenceTable=SequenceTable.InstallExecuteSequence },
197 - new WixActionTuple(null, new Identifier("InstallExecuteSequence/UnregisterMIMEInfo", AccessModifier.Public)) { Action="UnregisterMIMEInfo", Sequence=3000, SequenceTable=SequenceTable.InstallExecuteSequence },
198 - new WixActionTuple(null, new Identifier("InstallExecuteSequence/UnregisterProgIdInfo", AccessModifier.Public)) { Action="UnregisterProgIdInfo", Sequence=2900, SequenceTable=SequenceTable.InstallExecuteSequence },
199 - new WixActionTuple(null, new Identifier("InstallExecuteSequence/UnregisterTypeLibraries", AccessModifier.Public)) { Action="UnregisterTypeLibraries", Sequence=2300, SequenceTable=SequenceTable.InstallExecuteSequence },
200 - new WixActionTuple(null, new Identifier("InstallExecuteSequence/ValidateProductID", AccessModifier.Public)) { Action="ValidateProductID", Sequence=700, SequenceTable=SequenceTable.InstallExecuteSequence },
201 - new WixActionTuple(null, new Identifier("InstallExecuteSequence/WriteEnvironmentStrings", AccessModifier.Public)) { Action="WriteEnvironmentStrings", Sequence=5200, SequenceTable=SequenceTable.InstallExecuteSequence },
202 - new WixActionTuple(null, new Identifier("InstallExecuteSequence/WriteIniValues", AccessModifier.Public)) { Action="WriteIniValues", Sequence=5100, SequenceTable=SequenceTable.InstallExecuteSequence },
203 - new WixActionTuple(null, new Identifier("InstallExecuteSequence/WriteRegistryValues", AccessModifier.Public)) { Action="WriteRegistryValues", Sequence=5000, SequenceTable=SequenceTable.InstallExecuteSequence },
204 - };
205 -
206 - private static readonly HashSet<string> standardDirectories = new HashSet<string>
207 - {
208 - "TARGETDIR",
209 - "AdminToolsFolder",
210 - "AppDataFolder",
211 - "CommonAppDataFolder",
212 - "CommonFilesFolder",
213 - "DesktopFolder",
214 - "FavoritesFolder",
215 - "FontsFolder",
216 - "LocalAppDataFolder",
217 - "MyPicturesFolder",
218 - "PersonalFolder",
219 - "ProgramFilesFolder",
220 - "ProgramMenuFolder",
221 - "SendToFolder",
222 - "StartMenuFolder",
223 - "StartupFolder",
224 - "System16Folder",
225 - "SystemFolder",
226 - "TempFolder",
227 - "TemplateFolder",
228 - "WindowsFolder",
229 - "CommonFiles64Folder",
230 - "ProgramFiles64Folder",
231 - "System64Folder",
232 - "NetHoodFolder",
233 - "PrintHoodFolder",
234 - "RecentFolder",
235 - "WindowsVolume",
236 - };
237 -
238 - /// <summary>
239 - /// Find out if an action is a standard action.
240 - /// </summary>
241 - /// <param name="actionName">Name of the action.</param>
242 - /// <returns>true if the action is standard, false otherwise.</returns>
243 - public static bool IsStandardAction(string actionName)
244 - {
245 - return standardActionNames.Contains(actionName);
246 - }
247 -
248 - public static WixActionTuple[] StandardActions() => standardActions;
249 -
250 - /// <summary>
251 - /// Find out if a directory is a standard directory.
252 - /// </summary>
253 - /// <param name="directoryName">Name of the directory.</param>
254 - /// <returns>true if the directory is standard, false otherwise.</returns>
255 - public static bool IsStandardDirectory(string directoryName)
256 - {
257 - return standardDirectories.Contains(directoryName);
258 - }
259 - }
260 -}
src/WixToolset.Core/WixStrings.Designer.cs
+2 -2
@@ -163,7 +163,7 @@ namespace WixToolset {
163 /// <summary>
164 /// Looks up a localized string similar to Found an ActionRow with a non-existent {0} action: {1}..
165 /// </summary>
166 - internal static string EXP_FoundActionRowWinNonExistentAction {
166 + public static string EXP_FoundActionRowWinNonExistentAction {
167 get {
168 return ResourceManager.GetString("EXP_FoundActionRowWinNonExistentAction", resourceCulture);
169 }
@@ -172,7 +172,7 @@ namespace WixToolset {
172 /// <summary>
173 /// Looks up a localized string similar to Found an ActionRow with no Sequence, Before, or After column set..
174 /// </summary>
175 - internal static string EXP_FoundActionRowWithNoSequenceBeforeOrAfterColumnSet {
175 + public static string EXP_FoundActionRowWithNoSequenceBeforeOrAfterColumnSet {
176 get {
177 return ResourceManager.GetString("EXP_FoundActionRowWithNoSequenceBeforeOrAfterColumnSet", resourceCulture);
178 }
src/WixToolset.Data.WindowsInstaller/Data/tables.xml
+1 -1
@@ -1468,7 +1468,7 @@
1468 <columnDefinition name="PatchGroup" type="number" length="4" />
1469 <columnDefinition name="Attributes" type="number" length="4"/>
1470 <columnDefinition name="PatchAttributes" type="number" length="4" nullable="yes"/>
1471 - <columnDefinition name="DeltaPatchHeaderSource" type="string" length="0"/>
1471 + <columnDefinition name="DeltaPatchHeaderSource" type="string" length="0" nullable="yes"/>
1472 </tableDefinition>
1473 <tableDefinition name="WixBindUpdatedFiles" unreal="yes">
1474 <columnDefinition name="File_" type="string" length="0" primaryKey="yes" modularize="column" keyTable="File" keyColumn="1" category="identifier" />
src/WixToolset.Data.WindowsInstaller/RowDictionary.cs
+1 -2
@@ -77,8 +77,7 @@ namespace WixToolset.Data
77 /// <returns>Row or null if key is not found.</returns>
78 public T Get(string key)
79 {
80 - T result;
81 - return this.TryGetValue(key, out result) ? result : null;
80 + return this.TryGetValue(key, out var result) ? result : null;
81 }
82 }
83 }
src/WixToolset.Data.WindowsInstaller/Rows/SymbolPathType.cs deleted
-17
@@ -1,17 +0,0 @@
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.Data.Rows
4 -{
5 - /// <summary>
6 - /// The types that the WixDeltaPatchSymbolPaths table can hold.
7 - /// </summary>
8 - /// <remarks>The order of these values is important since WixDeltaPatchSymbolPaths are sorted by this type.</remarks>
9 - public enum SymbolPathType
10 - {
11 - File,
12 - Component,
13 - Directory,
14 - Media,
15 - Product
16 - };
17 -}
src/WixToolset.Data.WindowsInstaller/Rows/WixActionRow.cs
+28 -24
@@ -8,27 +8,28 @@ namespace WixToolset.Data.Rows
8 using System.Globalization;
9 using System.Xml;
10 using System.Xml.Schema;
11 + using WixToolset.Data.Tuples;
12
13 /// <summary>
14 /// The Sequence tables that actions may belong to.
15 /// </summary>
15 - public enum SequenceTable
16 - {
17 - /// <summary>AdminUISequence</summary>
18 - AdminUISequence,
16 + //public enum SequenceTable
17 + //{
18 + // /// <summary>AdminUISequence</summary>
19 + // AdminUISequence,
20
20 - /// <summary>AdminExecuteSequence</summary>
21 - AdminExecuteSequence,
21 + // /// <summary>AdminExecuteSequence</summary>
22 + // AdminExecuteSequence,
23
23 - /// <summary>AdvtExecuteSequence</summary>
24 - AdvtExecuteSequence,
24 + // /// <summary>AdvtExecuteSequence</summary>
25 + // AdvtExecuteSequence,
26
26 - /// <summary>InstallUISequence</summary>
27 - InstallUISequence,
27 + // /// <summary>InstallUISequence</summary>
28 + // InstallUISequence,
29
29 - /// <summary>InstallExecuteSequence</summary>
30 - InstallExecuteSequence
31 - }
30 + // /// <summary>InstallExecuteSequence</summary>
31 + // InstallExecuteSequence
32 + //}
33
34 /// <summary>
35 /// Specialization of a row for the sequence tables.
@@ -55,15 +56,15 @@ namespace WixToolset.Data.Rows
56 /// <param name="action">The name of the standard action.</param>
57 /// <param name="condition">The condition of the standard action.</param>
58 /// <param name="sequence">The suggested sequence number of the standard action.</param>
58 - private WixActionRow(SequenceTable sequenceTable, string action, string condition, int sequence) :
59 - base(null, WindowsInstallerStandard.GetTableDefinitions()["WixAction"])
60 - {
61 - this.SequenceTable = sequenceTable;
62 - this.Action = action;
63 - this.Condition = condition;
64 - this.Sequence = sequence;
65 - this.Overridable = true; // all standard actions are overridable by default
66 - }
59 + //private WixActionRow(SequenceTable sequenceTable, string action, string condition, int sequence) :
60 + // base(null, WindowsInstallerStandard.GetTableDefinitions()["WixAction"])
61 + //{
62 + // this.SequenceTable = sequenceTable;
63 + // this.Action = action;
64 + // this.Condition = condition;
65 + // this.Sequence = sequence;
66 + // this.Overridable = true; // all standard actions are overridable by default
67 + //}
68
69 /// <summary>
70 /// Instantiates an ActionRow by copying data from another ActionRow.
@@ -296,13 +297,15 @@ namespace WixToolset.Data.Rows
297 WixActionRow[] actionRows = new WixActionRow[sequenceCount];
298 for (int i = 0; i < sequenceCount; i++)
299 {
299 - WixActionRow actionRow = new WixActionRow(sequenceTables[i], id, condition, sequence);
300 - actionRows[i] = actionRow;
300 + //WixActionRow actionRow = new WixActionRow(sequenceTables[i], id, condition, sequence);
301 + //actionRows[i] = actionRow;
302 + throw new NotImplementedException();
303 }
304
305 return actionRows;
306 }
307
308 +#if DEAD_CODE
309 /// <summary>
310 /// Determines whether this ActionRow contains the specified ActionRow as a child in its dependency tree.
311 /// </summary>
@@ -370,5 +373,6 @@ namespace WixToolset.Data.Rows
373 }
374 }
375 }
376 +#endif
377 }
378 }
src/WixToolset.Data.WindowsInstaller/Rows/WixActionRowCollection.cs
+1
@@ -6,6 +6,7 @@ namespace WixToolset.Data.Rows
6 using System.Collections;
7 using System.Diagnostics;
8 using System.Xml;
9 + using WixToolset.Data.Tuples;
10
11 /// <summary>
12 /// A collection of action rows sorted by their sequence table and action name.
src/WixToolset.Data.WindowsInstaller/Rows/WixDeltaPatchSymbolPathsRow.cs
+2
@@ -2,6 +2,8 @@
2
3 namespace WixToolset.Data.Rows
4 {
5 + using WixToolset.Data.Tuples;
6 +
7 /// <summary>
8 /// Specialization of a row for the WixDeltaPatchSymbolPaths table.
9 /// </summary>
src/WixToolset.Data.WindowsInstaller/TableDefinitionCollection.cs
+11
@@ -68,6 +68,17 @@ namespace WixToolset.Data
68 }
69 }
70
71 + /// <summary>
72 + /// Tries to get a table definition by name.
73 + /// </summary>
74 + /// <param name="tableName">Name of table to locate.</param>
75 + /// <param name="table">Table definition if found.</param>
76 + /// <returns>True if table definition was found otherwise false.</returns>
77 + public bool TryGet(string tableName, out TableDefinition table)
78 + {
79 + return this.collection.TryGetValue(tableName, out table);
80 + }
81 +
82 /// <summary>
83 /// Load a table definition collection from an XmlReader.
84 /// </summary>
src/WixToolset.Data.WindowsInstaller/WindowsInstallerStandard.cs deleted
-442
@@ -1,442 +0,0 @@
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.Data
4 -{
5 - using System.Collections.Generic;
6 - using System.Reflection;
7 - using System.Xml;
8 - using WixToolset.Data.Rows;
9 -
10 - /// <summary>
11 - /// Represents the Windows Installer standard objects.
12 - /// </summary>
13 - public static class WindowsInstallerStandard
14 - {
15 - private static readonly object lockObject = new object();
16 -
17 - private static TableDefinitionCollection tableDefinitions;
18 - private static WixActionRowCollection standardActions;
19 -
20 - private static HashSet<string> standardActionNames;
21 - private static HashSet<string> standardDirectories;
22 - private static HashSet<string> standardProperties;
23 -
24 - /// <summary>
25 - /// Gets the table definitions stored in this assembly.
26 - /// </summary>
27 - /// <returns>Table definition collection for tables stored in this assembly.</returns>
28 - public static TableDefinitionCollection GetTableDefinitions()
29 - {
30 - lock (lockObject)
31 - {
32 - if (null == WindowsInstallerStandard.tableDefinitions)
33 - {
34 - using (XmlReader reader = XmlReader.Create(Assembly.GetExecutingAssembly().GetManifestResourceStream("WixToolset.Data.WindowsInstaller.Data.tables.xml")))
35 - {
36 - tableDefinitions = TableDefinitionCollection.Load(reader);
37 - }
38 - }
39 - }
40 -
41 - return WindowsInstallerStandard.tableDefinitions;
42 - }
43 -
44 - /// <summary>
45 - /// Gets the standard actions stored in this assembly.
46 - /// </summary>
47 - /// <returns>Collection of standard actions in this assembly.</returns>
48 - public static WixActionRowCollection GetStandardActions()
49 - {
50 - lock (lockObject)
51 - {
52 - if (null == standardActions)
53 - {
54 - using (XmlReader reader = XmlReader.Create(Assembly.GetExecutingAssembly().GetManifestResourceStream("WixToolset.Data.WindowsInstaller.Data.actions.xml")))
55 - {
56 - standardActions = WixActionRowCollection.Load(reader);
57 - }
58 - }
59 - }
60 -
61 - return standardActions;
62 - }
63 -
64 - /// <summary>
65 - /// Gets (and loads if not yet loaded) the list of standard MSI directories.
66 - /// </summary>
67 - /// <value>The list of standard MSI directories.</value>
68 - public static HashSet<string> GetStandardDirectories()
69 - {
70 - lock (lockObject)
71 - {
72 - if (null == standardDirectories)
73 - {
74 - LoadStandardDirectories();
75 - }
76 - }
77 -
78 - return standardDirectories;
79 - }
80 -
81 - /// <summary>
82 - /// Find out if an action is a standard action.
83 - /// </summary>
84 - /// <param name="actionName">Name of the action.</param>
85 - /// <returns>true if the action is standard, false otherwise.</returns>
86 - public static bool IsStandardAction(string actionName)
87 - {
88 - lock (lockObject)
89 - {
90 - if (null == standardActionNames)
91 - {
92 - standardActionNames = new HashSet<string>();
93 - standardActionNames.Add("AllocateRegistrySpace");
94 - standardActionNames.Add("AppSearch");
95 - standardActionNames.Add("BindImage");
96 - standardActionNames.Add("CCPSearch");
97 - standardActionNames.Add("CostFinalize");
98 - standardActionNames.Add("CostInitialize");
99 - standardActionNames.Add("CreateFolders");
100 - standardActionNames.Add("CreateShortcuts");
101 - standardActionNames.Add("DeleteServices");
102 - standardActionNames.Add("DisableRollback");
103 - standardActionNames.Add("DuplicateFiles");
104 - standardActionNames.Add("ExecuteAction");
105 - standardActionNames.Add("FileCost");
106 - standardActionNames.Add("FindRelatedProducts");
107 - standardActionNames.Add("ForceReboot");
108 - standardActionNames.Add("InstallAdminPackage");
109 - standardActionNames.Add("InstallExecute");
110 - standardActionNames.Add("InstallExecuteAgain");
111 - standardActionNames.Add("InstallFiles");
112 - standardActionNames.Add("InstallFinalize");
113 - standardActionNames.Add("InstallInitialize");
114 - standardActionNames.Add("InstallODBC");
115 - standardActionNames.Add("InstallServices");
116 - standardActionNames.Add("InstallSFPCatalogFile");
117 - standardActionNames.Add("InstallValidate");
118 - standardActionNames.Add("IsolateComponents");
119 - standardActionNames.Add("LaunchConditions");
120 - standardActionNames.Add("MigrateFeatureStates");
121 - standardActionNames.Add("MoveFiles");
122 - standardActionNames.Add("MsiConfigureServices");
123 - standardActionNames.Add("MsiPublishAssemblies");
124 - standardActionNames.Add("MsiUnpublishAssemblies");
125 - standardActionNames.Add("PatchFiles");
126 - standardActionNames.Add("ProcessComponents");
127 - standardActionNames.Add("PublishComponents");
128 - standardActionNames.Add("PublishFeatures");
129 - standardActionNames.Add("PublishProduct");
130 - standardActionNames.Add("RegisterClassInfo");
131 - standardActionNames.Add("RegisterComPlus");
132 - standardActionNames.Add("RegisterExtensionInfo");
133 - standardActionNames.Add("RegisterFonts");
134 - standardActionNames.Add("RegisterMIMEInfo");
135 - standardActionNames.Add("RegisterProduct");
136 - standardActionNames.Add("RegisterProgIdInfo");
137 - standardActionNames.Add("RegisterTypeLibraries");
138 - standardActionNames.Add("RegisterUser");
139 - standardActionNames.Add("RemoveDuplicateFiles");
140 - standardActionNames.Add("RemoveEnvironmentStrings");
141 - standardActionNames.Add("RemoveExistingProducts");
142 - standardActionNames.Add("RemoveFiles");
143 - standardActionNames.Add("RemoveFolders");
144 - standardActionNames.Add("RemoveIniValues");
145 - standardActionNames.Add("RemoveODBC");
146 - standardActionNames.Add("RemoveRegistryValues");
147 - standardActionNames.Add("RemoveShortcuts");
148 - standardActionNames.Add("ResolveSource");
149 - standardActionNames.Add("RMCCPSearch");
150 - standardActionNames.Add("ScheduleReboot");
151 - standardActionNames.Add("SelfRegModules");
152 - standardActionNames.Add("SelfUnregModules");
153 - standardActionNames.Add("SetODBCFolders");
154 - standardActionNames.Add("StartServices");
155 - standardActionNames.Add("StopServices");
156 - standardActionNames.Add("UnpublishComponents");
157 - standardActionNames.Add("UnpublishFeatures");
158 - standardActionNames.Add("UnregisterClassInfo");
159 - standardActionNames.Add("UnregisterComPlus");
160 - standardActionNames.Add("UnregisterExtensionInfo");
161 - standardActionNames.Add("UnregisterFonts");
162 - standardActionNames.Add("UnregisterMIMEInfo");
163 - standardActionNames.Add("UnregisterProgIdInfo");
164 - standardActionNames.Add("UnregisterTypeLibraries");
165 - standardActionNames.Add("ValidateProductID");
166 - standardActionNames.Add("WriteEnvironmentStrings");
167 - standardActionNames.Add("WriteIniValues");
168 - standardActionNames.Add("WriteRegistryValues");
169 - }
170 - }
171 -
172 - return standardActionNames.Contains(actionName);
173 - }
174 -
175 - /// <summary>
176 - /// Find out if a directory is a standard directory.
177 - /// </summary>
178 - /// <param name="directoryName">Name of the directory.</param>
179 - /// <returns>true if the directory is standard, false otherwise.</returns>
180 - public static bool IsStandardDirectory(string directoryName)
181 - {
182 - lock (lockObject)
183 - {
184 - if (null == standardDirectories)
185 - {
186 - LoadStandardDirectories();
187 - }
188 - }
189 -
190 - return standardDirectories.Contains(directoryName);
191 - }
192 -
193 - /// <summary>
194 - /// Find out if a property is a standard property.
195 - /// References:
196 - /// Title: Property Reference [Windows Installer]:
197 - /// URL: http://msdn.microsoft.com/library/en-us/msi/setup/property_reference.asp
198 - /// </summary>
199 - /// <param name="propertyName">Name of the property.</param>
200 - /// <returns>true if a property is standard, false otherwise.</returns>
201 - public static bool IsStandardProperty(string propertyName)
202 - {
203 - lock (lockObject)
204 - {
205 - if (null == standardProperties)
206 - {
207 - standardProperties = new HashSet<string>();
208 - standardProperties.Add("~"); // REG_MULTI_SZ/NULL marker
209 - standardProperties.Add("ACTION");
210 - standardProperties.Add("ADDDEFAULT");
211 - standardProperties.Add("ADDLOCAL");
212 - standardProperties.Add("ADDDSOURCE");
213 - standardProperties.Add("AdminProperties");
214 - standardProperties.Add("AdminUser");
215 - standardProperties.Add("ADVERTISE");
216 - standardProperties.Add("AFTERREBOOT");
217 - standardProperties.Add("AllowProductCodeMismatches");
218 - standardProperties.Add("AllowProductVersionMajorMismatches");
219 - standardProperties.Add("ALLUSERS");
220 - standardProperties.Add("Alpha");
221 - standardProperties.Add("ApiPatchingSymbolFlags");
222 - standardProperties.Add("ARPAUTHORIZEDCDFPREFIX");
223 - standardProperties.Add("ARPCOMMENTS");
224 - standardProperties.Add("ARPCONTACT");
225 - standardProperties.Add("ARPHELPLINK");
226 - standardProperties.Add("ARPHELPTELEPHONE");
227 - standardProperties.Add("ARPINSTALLLOCATION");
228 - standardProperties.Add("ARPNOMODIFY");
229 - standardProperties.Add("ARPNOREMOVE");
230 - standardProperties.Add("ARPNOREPAIR");
231 - standardProperties.Add("ARPPRODUCTIONICON");
232 - standardProperties.Add("ARPREADME");
233 - standardProperties.Add("ARPSIZE");
234 - standardProperties.Add("ARPSYSTEMCOMPONENT");
235 - standardProperties.Add("ARPULRINFOABOUT");
236 - standardProperties.Add("ARPURLUPDATEINFO");
237 - standardProperties.Add("AVAILABLEFREEREG");
238 - standardProperties.Add("BorderSize");
239 - standardProperties.Add("BorderTop");
240 - standardProperties.Add("CaptionHeight");
241 - standardProperties.Add("CCP_DRIVE");
242 - standardProperties.Add("ColorBits");
243 - standardProperties.Add("COMPADDLOCAL");
244 - standardProperties.Add("COMPADDSOURCE");
245 - standardProperties.Add("COMPANYNAME");
246 - standardProperties.Add("ComputerName");
247 - standardProperties.Add("CostingComplete");
248 - standardProperties.Add("Date");
249 - standardProperties.Add("DefaultUIFont");
250 - standardProperties.Add("DISABLEADVTSHORTCUTS");
251 - standardProperties.Add("DISABLEMEDIA");
252 - standardProperties.Add("DISABLEROLLBACK");
253 - standardProperties.Add("DiskPrompt");
254 - standardProperties.Add("DontRemoveTempFolderWhenFinished");
255 - standardProperties.Add("EnableUserControl");
256 - standardProperties.Add("EXECUTEACTION");
257 - standardProperties.Add("EXECUTEMODE");
258 - standardProperties.Add("FASTOEM");
259 - standardProperties.Add("FILEADDDEFAULT");
260 - standardProperties.Add("FILEADDLOCAL");
261 - standardProperties.Add("FILEADDSOURCE");
262 - standardProperties.Add("IncludeWholeFilesOnly");
263 - standardProperties.Add("Installed");
264 - standardProperties.Add("INSTALLLEVEL");
265 - standardProperties.Add("Intel");
266 - standardProperties.Add("Intel64");
267 - standardProperties.Add("IsAdminPackage");
268 - standardProperties.Add("LeftUnit");
269 - standardProperties.Add("LIMITUI");
270 - standardProperties.Add("ListOfPatchGUIDsToReplace");
271 - standardProperties.Add("ListOfTargetProductCode");
272 - standardProperties.Add("LOGACTION");
273 - standardProperties.Add("LogonUser");
274 - standardProperties.Add("Manufacturer");
275 - standardProperties.Add("MEDIAPACKAGEPATH");
276 - standardProperties.Add("MediaSourceDir");
277 - standardProperties.Add("MinimumRequiredMsiVersion");
278 - standardProperties.Add("MsiAMD64");
279 - standardProperties.Add("MSIAPRSETTINGSIDENTIFIER");
280 - standardProperties.Add("MSICHECKCRCS");
281 - standardProperties.Add("MSIDISABLERMRESTART");
282 - standardProperties.Add("MSIENFORCEUPGRADECOMPONENTRULES");
283 - standardProperties.Add("MSIFASTINSTALL");
284 - standardProperties.Add("MsiFileToUseToCreatePatchTables");
285 - standardProperties.Add("MsiHiddenProperties");
286 - standardProperties.Add("MSIINSTALLPERUSER");
287 - standardProperties.Add("MSIINSTANCEGUID");
288 - standardProperties.Add("MsiLogFileLocation");
289 - standardProperties.Add("MsiLogging");
290 - standardProperties.Add("MsiNetAssemblySupport");
291 - standardProperties.Add("MSINEWINSTANCE");
292 - standardProperties.Add("MSINODISABLEMEDIA");
293 - standardProperties.Add("MsiNTProductType");
294 - standardProperties.Add("MsiNTSuiteBackOffice");
295 - standardProperties.Add("MsiNTSuiteDataCenter");
296 - standardProperties.Add("MsiNTSuiteEnterprise");
297 - standardProperties.Add("MsiNTSuiteSmallBusiness");
298 - standardProperties.Add("MsiNTSuiteSmallBusinessRestricted");
299 - standardProperties.Add("MsiNTSuiteWebServer");
300 - standardProperties.Add("MsiNTSuitePersonal");
301 - standardProperties.Add("MsiPatchRemovalList");
302 - standardProperties.Add("MSIPATCHREMOVE");
303 - standardProperties.Add("MSIRESTARTMANAGERCONTROL");
304 - standardProperties.Add("MsiRestartManagerSessionKey");
305 - standardProperties.Add("MSIRMSHUTDOWN");
306 - standardProperties.Add("MsiRunningElevated");
307 - standardProperties.Add("MsiUIHideCancel");
308 - standardProperties.Add("MsiUIProgressOnly");
309 - standardProperties.Add("MsiUISourceResOnly");
310 - standardProperties.Add("MsiSystemRebootPending");
311 - standardProperties.Add("MsiWin32AssemblySupport");
312 - standardProperties.Add("NOCOMPANYNAME");
313 - standardProperties.Add("NOUSERNAME");
314 - standardProperties.Add("OLEAdvtSupport");
315 - standardProperties.Add("OptimizePatchSizeForLargeFiles");
316 - standardProperties.Add("OriginalDatabase");
317 - standardProperties.Add("OutOfDiskSpace");
318 - standardProperties.Add("OutOfNoRbDiskSpace");
319 - standardProperties.Add("ParentOriginalDatabase");
320 - standardProperties.Add("ParentProductCode");
321 - standardProperties.Add("PATCH");
322 - standardProperties.Add("PATCH_CACHE_DIR");
323 - standardProperties.Add("PATCH_CACHE_ENABLED");
324 - standardProperties.Add("PatchGUID");
325 - standardProperties.Add("PATCHNEWPACKAGECODE");
326 - standardProperties.Add("PATCHNEWSUMMARYCOMMENTS");
327 - standardProperties.Add("PATCHNEWSUMMARYSUBJECT");
328 - standardProperties.Add("PatchOutputPath");
329 - standardProperties.Add("PatchSourceList");
330 - standardProperties.Add("PhysicalMemory");
331 - standardProperties.Add("PIDKEY");
332 - standardProperties.Add("PIDTemplate");
333 - standardProperties.Add("Preselected");
334 - standardProperties.Add("PRIMARYFOLDER");
335 - standardProperties.Add("PrimaryVolumePath");
336 - standardProperties.Add("PrimaryVolumeSpaceAvailable");
337 - standardProperties.Add("PrimaryVolumeSpaceRemaining");
338 - standardProperties.Add("PrimaryVolumeSpaceRequired");
339 - standardProperties.Add("Privileged");
340 - standardProperties.Add("ProductCode");
341 - standardProperties.Add("ProductID");
342 - standardProperties.Add("ProductLanguage");
343 - standardProperties.Add("ProductName");
344 - standardProperties.Add("ProductState");
345 - standardProperties.Add("ProductVersion");
346 - standardProperties.Add("PROMPTROLLBACKCOST");
347 - standardProperties.Add("REBOOT");
348 - standardProperties.Add("REBOOTPROMPT");
349 - standardProperties.Add("RedirectedDllSupport");
350 - standardProperties.Add("REINSTALL");
351 - standardProperties.Add("REINSTALLMODE");
352 - standardProperties.Add("RemoveAdminTS");
353 - standardProperties.Add("REMOVE");
354 - standardProperties.Add("ReplacedInUseFiles");
355 - standardProperties.Add("RestrictedUserControl");
356 - standardProperties.Add("RESUME");
357 - standardProperties.Add("RollbackDisabled");
358 - standardProperties.Add("ROOTDRIVE");
359 - standardProperties.Add("ScreenX");
360 - standardProperties.Add("ScreenY");
361 - standardProperties.Add("SecureCustomProperties");
362 - standardProperties.Add("ServicePackLevel");
363 - standardProperties.Add("ServicePackLevelMinor");
364 - standardProperties.Add("SEQUENCE");
365 - standardProperties.Add("SharedWindows");
366 - standardProperties.Add("ShellAdvtSupport");
367 - standardProperties.Add("SHORTFILENAMES");
368 - standardProperties.Add("SourceDir");
369 - standardProperties.Add("SOURCELIST");
370 - standardProperties.Add("SystemLanguageID");
371 - standardProperties.Add("TARGETDIR");
372 - standardProperties.Add("TerminalServer");
373 - standardProperties.Add("TextHeight");
374 - standardProperties.Add("Time");
375 - standardProperties.Add("TRANSFORMS");
376 - standardProperties.Add("TRANSFORMSATSOURCE");
377 - standardProperties.Add("TRANSFORMSSECURE");
378 - standardProperties.Add("TTCSupport");
379 - standardProperties.Add("UILevel");
380 - standardProperties.Add("UpdateStarted");
381 - standardProperties.Add("UpgradeCode");
382 - standardProperties.Add("UPGRADINGPRODUCTCODE");
383 - standardProperties.Add("UserLanguageID");
384 - standardProperties.Add("USERNAME");
385 - standardProperties.Add("UserSID");
386 - standardProperties.Add("Version9X");
387 - standardProperties.Add("VersionDatabase");
388 - standardProperties.Add("VersionMsi");
389 - standardProperties.Add("VersionNT");
390 - standardProperties.Add("VersionNT64");
391 - standardProperties.Add("VirtualMemory");
392 - standardProperties.Add("WindowsBuild");
393 - standardProperties.Add("WindowsVolume");
394 - }
395 - }
396 -
397 - return standardProperties.Contains(propertyName);
398 - }
399 -
400 - /// <summary>
401 - /// Sets up a hashtable with the set of standard MSI directories
402 - /// </summary>
403 - private static void LoadStandardDirectories()
404 - {
405 - lock (lockObject)
406 - {
407 - if (null == standardDirectories)
408 - {
409 - standardDirectories = new HashSet<string>();
410 - standardDirectories.Add("TARGETDIR");
411 - standardDirectories.Add("AdminToolsFolder");
412 - standardDirectories.Add("AppDataFolder");
413 - standardDirectories.Add("CommonAppDataFolder");
414 - standardDirectories.Add("CommonFilesFolder");
415 - standardDirectories.Add("DesktopFolder");
416 - standardDirectories.Add("FavoritesFolder");
417 - standardDirectories.Add("FontsFolder");
418 - standardDirectories.Add("LocalAppDataFolder");
419 - standardDirectories.Add("MyPicturesFolder");
420 - standardDirectories.Add("PersonalFolder");
421 - standardDirectories.Add("ProgramFilesFolder");
422 - standardDirectories.Add("ProgramMenuFolder");
423 - standardDirectories.Add("SendToFolder");
424 - standardDirectories.Add("StartMenuFolder");
425 - standardDirectories.Add("StartupFolder");
426 - standardDirectories.Add("System16Folder");
427 - standardDirectories.Add("SystemFolder");
428 - standardDirectories.Add("TempFolder");
429 - standardDirectories.Add("TemplateFolder");
430 - standardDirectories.Add("WindowsFolder");
431 - standardDirectories.Add("CommonFiles64Folder");
432 - standardDirectories.Add("ProgramFiles64Folder");
433 - standardDirectories.Add("System64Folder");
434 - standardDirectories.Add("NetHoodFolder");
435 - standardDirectories.Add("PrintHoodFolder");
436 - standardDirectories.Add("RecentFolder");
437 - standardDirectories.Add("WindowsVolume");
438 - }
439 - }
440 - }
441 - }
442 -}
src/WixToolset.Data.WindowsInstaller/WindowsInstallerStandardInternal.cs new
+59
@@ -0,0 +1,59 @@
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.Data
4 +{
5 + using System.Reflection;
6 + using System.Xml;
7 + using WixToolset.Data.Rows;
8 +
9 + /// <summary>
10 + /// Represents the Windows Installer standard objects.
11 + /// </summary>
12 + public static class WindowsInstallerStandardInternal
13 + {
14 + private static readonly object lockObject = new object();
15 +
16 + private static TableDefinitionCollection tableDefinitions;
17 + private static WixActionRowCollection standardActions;
18 +
19 + /// <summary>
20 + /// Gets the table definitions stored in this assembly.
21 + /// </summary>
22 + /// <returns>Table definition collection for tables stored in this assembly.</returns>
23 + public static TableDefinitionCollection GetTableDefinitions()
24 + {
25 + lock (lockObject)
26 + {
27 + if (null == WindowsInstallerStandardInternal.tableDefinitions)
28 + {
29 + using (XmlReader reader = XmlReader.Create(Assembly.GetExecutingAssembly().GetManifestResourceStream("WixToolset.Data.WindowsInstaller.Data.tables.xml")))
30 + {
31 + WindowsInstallerStandardInternal.tableDefinitions = TableDefinitionCollection.Load(reader);
32 + }
33 + }
34 + }
35 +
36 + return WindowsInstallerStandardInternal.tableDefinitions;
37 + }
38 +
39 + /// <summary>
40 + /// Gets the standard actions stored in this assembly.
41 + /// </summary>
42 + /// <returns>Collection of standard actions in this assembly.</returns>
43 + public static WixActionRowCollection GetStandardActionRows()
44 + {
45 + lock (lockObject)
46 + {
47 + if (null == WindowsInstallerStandardInternal.standardActions)
48 + {
49 + using (XmlReader reader = XmlReader.Create(Assembly.GetExecutingAssembly().GetManifestResourceStream("WixToolset.Data.WindowsInstaller.Data.actions.xml")))
50 + {
51 + WindowsInstallerStandardInternal.standardActions = WixActionRowCollection.Load(reader);
52 + }
53 + }
54 + }
55 +
56 + return WindowsInstallerStandardInternal.standardActions;
57 + }
58 + }
59 +}
src/test/WixToolsetTest.CoreIntegrationFixture/ProgramFixture.cs
+3 -4
@@ -26,18 +26,17 @@ namespace WixToolsetTest.CoreIntegrationFixture
26 var result = program.Run(new WixToolsetServiceProvider(), new[] { "build", "Package.wxs", "PackageComponents.wxs", "-loc", "Package.en-us.wxl", "-bindpath", "data", "-intermediateFolder", intermediateFolder, "-o", $@"{intermediateFolder}\bin\test.msi" });
27
28 Assert.Equal(0, result);
29 -#if FIXED_MSI_BACKEND
29 +
30 Assert.True(File.Exists(Path.Combine(intermediateFolder, @"bin\test.msi")));
31 Assert.True(File.Exists(Path.Combine(intermediateFolder, @"bin\test.wixpdb")));
32 Assert.True(File.Exists(Path.Combine(intermediateFolder, @"bin\MsiPackage\test.txt")));
33 -#else
34 - var intermediate = Intermediate.Load(Path.Combine(intermediateFolder, @"bin\test.msi"));
33 +
34 + var intermediate = Intermediate.Load(Path.Combine(intermediateFolder, @"bin\test.wir"));
35 Assert.Single(intermediate.Sections);
36
37 var wixFile = intermediate.Sections.SelectMany(s => s.Tuples).OfType<WixFileTuple>().Single();
38 Assert.Equal(@"data\test.txt", wixFile[WixFileTupleFields.Source].AsPath().Path);
39 Assert.Equal(@"test.txt", wixFile[WixFileTupleFields.Source].PreviousValue.AsPath().Path);
40 -#endif
40 }
41 }
42 }