@joebigelow / wix-1 / commits / b645ddc2

Integrate latest changes to tuple definitions

Rob Mensching committed May 22, 2019 at 00:54 UTC b645ddc2c1386c1199ca1e7790201d7a5ab6627b
2 files changed +1020 -655
src/WixToolset.Converters.Tupleizer/ConvertTuplesCommand.cs
+565 -363
@@ -3,6 +3,7 @@
3 namespace WixToolset.Converters.Tupleizer
4 {
5 using System;
6 + using System.Collections.Generic;
7 using System.Linq;
8 using WixToolset.Data;
9 using WixToolset.Data.Tuples;
@@ -21,11 +22,17 @@ namespace WixToolset.Converters.Tupleizer
22 {
23 var section = new IntermediateSection(String.Empty, OutputType3ToSectionType4(output.Type), output.Codepage);
24
25 + var wixMediaByDiskId = IndexWixMediaTableByDiskId(output);
26 + var bindPathsById = IndexById<Wix3.Row>(output, "BindPath");
27 + var fontsById = IndexById<Wix3.Row>(output, "Font");
28 + var selfRegById = IndexById<Wix3.Row>(output, "SelfReg");
29 + var wixDirectoryById = IndexById<Wix3.Row>(output, "WixDirectory");
30 +
31 foreach (Wix3.Table table in output.Tables)
32 {
33 foreach (Wix3.Row row in table.Rows)
34 {
28 - var tuple = GenerateTupleFromRow(row);
35 + var tuple = GenerateTupleFromRow(row, wixMediaByDiskId, fontsById, bindPathsById, selfRegById, wixDirectoryById);
36 if (tuple != null)
37 {
38 section.Tuples.Add(tuple);
@@ -36,353 +43,534 @@ namespace WixToolset.Converters.Tupleizer
43 return new Intermediate(String.Empty, new[] { section }, localizationsByCulture: null, embedFilePaths: null);
44 }
45
39 - private static IntermediateTuple GenerateTupleFromRow(Wix3.Row row)
46 + private static Dictionary<int, Wix3.WixMediaRow> IndexWixMediaTableByDiskId(Wix3.Output output)
47 + {
48 + var wixMediaByDiskId = new Dictionary<int, Wix3.WixMediaRow>();
49 + var wixMediaTable = output.Tables["WixMedia"];
50 +
51 + if (wixMediaTable != null)
52 + {
53 + foreach (Wix3.WixMediaRow row in wixMediaTable.Rows)
54 + {
55 + wixMediaByDiskId.Add(FieldAsInt(row, 0), row);
56 + }
57 + }
58 +
59 + return wixMediaByDiskId;
60 + }
61 +
62 + private static Dictionary<string, T> IndexById<T>(Wix3.Output output, string tableName) where T : Wix3.Row
63 + {
64 + var byId = new Dictionary<string, T>();
65 + var table = output.Tables[tableName];
66 +
67 + if (table != null)
68 + {
69 + foreach (T row in table.Rows)
70 + {
71 + byId.Add(FieldAsString(row, 0), row);
72 + }
73 + }
74 +
75 + return byId;
76 + }
77 +
78 + private static IntermediateTuple GenerateTupleFromRow(Wix3.Row row, Dictionary<int, Wix3.WixMediaRow> wixMediaByDiskId, Dictionary<string, Wix3.Row> fontsById, Dictionary<string, Wix3.Row> bindPathsById, Dictionary<string, Wix3.Row> selfRegById, Dictionary<string, Wix3.Row> wixDirectoryById)
79 {
80 var name = row.Table.Name;
81 switch (name)
82 {
44 - case "_SummaryInformation":
45 - return DefaultTupleFromRow(typeof(_SummaryInformationTuple), row, columnZeroIsId: false);
46 - case "ActionText":
47 - return DefaultTupleFromRow(typeof(ActionTextTuple), row, columnZeroIsId: false);
48 - case "AdvtExecuteSequence":
49 - return DefaultTupleFromRow(typeof(AdvtExecuteSequenceTuple), row, columnZeroIsId: false);
50 - case "AppId":
51 - return DefaultTupleFromRow(typeof(AppIdTuple), row, columnZeroIsId: false);
52 - case "AppSearch":
53 - return DefaultTupleFromRow(typeof(AppSearchTuple), row, columnZeroIsId: false);
54 - case "Binary":
55 - return DefaultTupleFromRow(typeof(BinaryTuple), row, columnZeroIsId: false);
56 - case "Class":
57 - return DefaultTupleFromRow(typeof(ClassTuple), row, columnZeroIsId: false);
58 - case "CompLocator":
59 - return DefaultTupleFromRow(typeof(CompLocatorTuple), row, columnZeroIsId: true);
60 - case "Component":
61 - {
62 - var attributes = FieldAsNullableInt(row, 3);
63 -
64 - var location = ComponentLocation.LocalOnly;
65 - if ((attributes & WindowsInstallerConstants.MsidbComponentAttributesSourceOnly) == WindowsInstallerConstants.MsidbComponentAttributesSourceOnly)
66 - {
67 - location = ComponentLocation.SourceOnly;
68 - }
69 - else if ((attributes & WindowsInstallerConstants.MsidbComponentAttributesOptional) == WindowsInstallerConstants.MsidbComponentAttributesOptional)
70 - {
71 - location = ComponentLocation.Either;
72 - }
83 + case "_SummaryInformation":
84 + return DefaultTupleFromRow(typeof(SummaryInformationTuple), row, columnZeroIsId: false);
85 + case "ActionText":
86 + return DefaultTupleFromRow(typeof(ActionTextTuple), row, columnZeroIsId: false);
87 + case "AdvtExecuteSequence":
88 + return DefaultTupleFromRow(typeof(AdvtExecuteSequenceTuple), row, columnZeroIsId: false);
89 + case "AppId":
90 + return DefaultTupleFromRow(typeof(AppIdTuple), row, columnZeroIsId: false);
91 + case "AppSearch":
92 + return DefaultTupleFromRow(typeof(AppSearchTuple), row, columnZeroIsId: false);
93 + case "Billboard":
94 + return DefaultTupleFromRow(typeof(BillboardTuple), row, columnZeroIsId: true);
95 + case "Binary":
96 + return DefaultTupleFromRow(typeof(BinaryTuple), row, columnZeroIsId: true);
97 + case "BindPath":
98 + return null;
99 + case "CCPSearch":
100 + return DefaultTupleFromRow(typeof(CCPSearchTuple), row, columnZeroIsId: true);
101 + case "Class":
102 + return DefaultTupleFromRow(typeof(ClassTuple), row, columnZeroIsId: false);
103 + case "CompLocator":
104 + return DefaultTupleFromRow(typeof(CompLocatorTuple), row, columnZeroIsId: true);
105 + case "Component":
106 + {
107 + var attributes = FieldAsNullableInt(row, 3);
108
74 - var keyPathType = ComponentKeyPathType.File;
75 - if ((attributes & WindowsInstallerConstants.MsidbComponentAttributesRegistryKeyPath) == WindowsInstallerConstants.MsidbComponentAttributesRegistryKeyPath)
76 - {
77 - keyPathType = ComponentKeyPathType.Registry;
78 - }
79 - else if ((attributes & WindowsInstallerConstants.MsidbComponentAttributesODBCDataSource) == WindowsInstallerConstants.MsidbComponentAttributesODBCDataSource)
80 - {
81 - keyPathType = ComponentKeyPathType.OdbcDataSource;
82 - }
109 + var location = ComponentLocation.LocalOnly;
110 + if ((attributes & WindowsInstallerConstants.MsidbComponentAttributesSourceOnly) == WindowsInstallerConstants.MsidbComponentAttributesSourceOnly)
111 + {
112 + location = ComponentLocation.SourceOnly;
113 + }
114 + else if ((attributes & WindowsInstallerConstants.MsidbComponentAttributesOptional) == WindowsInstallerConstants.MsidbComponentAttributesOptional)
115 + {
116 + location = ComponentLocation.Either;
117 + }
118
84 - return new ComponentTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0)))
85 - {
86 - ComponentId = FieldAsString(row, 1),
87 - Directory_ = FieldAsString(row, 2),
88 - Condition = FieldAsString(row, 4),
89 - KeyPath = FieldAsString(row, 5),
90 - Location = location,
91 - DisableRegistryReflection = (attributes & WindowsInstallerConstants.MsidbComponentAttributesDisableRegistryReflection) == WindowsInstallerConstants.MsidbComponentAttributesDisableRegistryReflection,
92 - NeverOverwrite = (attributes & WindowsInstallerConstants.MsidbComponentAttributesNeverOverwrite) == WindowsInstallerConstants.MsidbComponentAttributesNeverOverwrite,
93 - Permanent = (attributes & WindowsInstallerConstants.MsidbComponentAttributesPermanent) == WindowsInstallerConstants.MsidbComponentAttributesPermanent,
94 - SharedDllRefCount = (attributes & WindowsInstallerConstants.MsidbComponentAttributesSharedDllRefCount) == WindowsInstallerConstants.MsidbComponentAttributesSharedDllRefCount,
95 - Shared = (attributes & WindowsInstallerConstants.MsidbComponentAttributesShared) == WindowsInstallerConstants.MsidbComponentAttributesShared,
96 - Transitive = (attributes & WindowsInstallerConstants.MsidbComponentAttributesTransitive) == WindowsInstallerConstants.MsidbComponentAttributesTransitive,
97 - UninstallWhenSuperseded = (attributes & WindowsInstallerConstants.MsidbComponentAttributesUninstallOnSupersedence) == WindowsInstallerConstants.MsidbComponentAttributesUninstallOnSupersedence,
98 - Win64 = (attributes & WindowsInstallerConstants.MsidbComponentAttributes64bit) == WindowsInstallerConstants.MsidbComponentAttributes64bit,
99 - KeyPathType = keyPathType,
100 - };
119 + var keyPathType = ComponentKeyPathType.File;
120 + if ((attributes & WindowsInstallerConstants.MsidbComponentAttributesRegistryKeyPath) == WindowsInstallerConstants.MsidbComponentAttributesRegistryKeyPath)
121 + {
122 + keyPathType = ComponentKeyPathType.Registry;
123 + }
124 + else if ((attributes & WindowsInstallerConstants.MsidbComponentAttributesODBCDataSource) == WindowsInstallerConstants.MsidbComponentAttributesODBCDataSource)
125 + {
126 + keyPathType = ComponentKeyPathType.OdbcDataSource;
127 }
128
103 - case "Condition":
104 - return DefaultTupleFromRow(typeof(ConditionTuple), row, columnZeroIsId: false);
105 - case "CreateFolder":
106 - return DefaultTupleFromRow(typeof(CreateFolderTuple), row, columnZeroIsId: false);
107 - case "CustomAction":
129 + return new ComponentTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0)))
130 {
109 - var caType = FieldAsInt(row, 1);
110 - var executionType = DetermineCustomActionExecutionType(caType);
111 - var sourceType = DetermineCustomActionSourceType(caType);
112 - var targetType = DetermineCustomActionTargetType(caType);
131 + ComponentId = FieldAsString(row, 1),
132 + DirectoryRef = FieldAsString(row, 2),
133 + Condition = FieldAsString(row, 4),
134 + KeyPath = FieldAsString(row, 5),
135 + Location = location,
136 + DisableRegistryReflection = (attributes & WindowsInstallerConstants.MsidbComponentAttributesDisableRegistryReflection) == WindowsInstallerConstants.MsidbComponentAttributesDisableRegistryReflection,
137 + NeverOverwrite = (attributes & WindowsInstallerConstants.MsidbComponentAttributesNeverOverwrite) == WindowsInstallerConstants.MsidbComponentAttributesNeverOverwrite,
138 + Permanent = (attributes & WindowsInstallerConstants.MsidbComponentAttributesPermanent) == WindowsInstallerConstants.MsidbComponentAttributesPermanent,
139 + SharedDllRefCount = (attributes & WindowsInstallerConstants.MsidbComponentAttributesSharedDllRefCount) == WindowsInstallerConstants.MsidbComponentAttributesSharedDllRefCount,
140 + Shared = (attributes & WindowsInstallerConstants.MsidbComponentAttributesShared) == WindowsInstallerConstants.MsidbComponentAttributesShared,
141 + Transitive = (attributes & WindowsInstallerConstants.MsidbComponentAttributesTransitive) == WindowsInstallerConstants.MsidbComponentAttributesTransitive,
142 + UninstallWhenSuperseded = (attributes & WindowsInstallerConstants.MsidbComponentAttributesUninstallOnSupersedence) == WindowsInstallerConstants.MsidbComponentAttributesUninstallOnSupersedence,
143 + Win64 = (attributes & WindowsInstallerConstants.MsidbComponentAttributes64bit) == WindowsInstallerConstants.MsidbComponentAttributes64bit,
144 + KeyPathType = keyPathType,
145 + };
146 + }
147
114 - return new CustomActionTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0)))
115 - {
116 - ExecutionType = executionType,
117 - SourceType = sourceType,
118 - Source = FieldAsString(row, 2),
119 - TargetType = targetType,
120 - Target = FieldAsString(row, 3),
121 - Win64 = (caType & WindowsInstallerConstants.MsidbCustomActionType64BitScript) == WindowsInstallerConstants.MsidbCustomActionType64BitScript,
122 - TSAware = (caType & WindowsInstallerConstants.MsidbCustomActionTypeTSAware) == WindowsInstallerConstants.MsidbCustomActionTypeTSAware,
123 - Impersonate = (caType & WindowsInstallerConstants.MsidbCustomActionTypeNoImpersonate) != WindowsInstallerConstants.MsidbCustomActionTypeNoImpersonate,
124 - IgnoreResult = (caType & WindowsInstallerConstants.MsidbCustomActionTypeContinue) == WindowsInstallerConstants.MsidbCustomActionTypeContinue,
125 - Hidden = (caType & WindowsInstallerConstants.MsidbCustomActionTypeHideTarget) == WindowsInstallerConstants.MsidbCustomActionTypeHideTarget,
126 - Async = (caType & WindowsInstallerConstants.MsidbCustomActionTypeAsync) == WindowsInstallerConstants.MsidbCustomActionTypeAsync,
127 - };
128 - }
148 + case "Condition":
149 + return DefaultTupleFromRow(typeof(ConditionTuple), row, columnZeroIsId: false);
150 + case "CreateFolder":
151 + return DefaultTupleFromRow(typeof(CreateFolderTuple), row, columnZeroIsId: false);
152 + case "CustomAction":
153 + {
154 + var caType = FieldAsInt(row, 1);
155 + var executionType = DetermineCustomActionExecutionType(caType);
156 + var sourceType = DetermineCustomActionSourceType(caType);
157 + var targetType = DetermineCustomActionTargetType(caType);
158
130 - case "Directory":
131 - return DefaultTupleFromRow(typeof(DirectoryTuple), row, columnZeroIsId: false);
132 - case "DrLocator":
133 - return DefaultTupleFromRow(typeof(DrLocatorTuple), row, columnZeroIsId: false);
134 - case "Error":
135 - return DefaultTupleFromRow(typeof(ErrorTuple), row, columnZeroIsId: false);
136 - case "Extension":
137 - return DefaultTupleFromRow(typeof(ExtensionTuple), row, columnZeroIsId: false);
138 - case "Feature":
139 - {
140 - int attributes = FieldAsInt(row, 7);
141 - var installDefault = FeatureInstallDefault.Local;
142 - if ((attributes & WindowsInstallerConstants.MsidbFeatureAttributesFollowParent) == WindowsInstallerConstants.MsidbFeatureAttributesFollowParent)
143 - {
144 - installDefault = FeatureInstallDefault.FollowParent;
145 - }
146 - else
147 - if ((attributes & WindowsInstallerConstants.MsidbFeatureAttributesFavorSource) == WindowsInstallerConstants.MsidbFeatureAttributesFavorSource)
148 - {
149 - installDefault = FeatureInstallDefault.Source;
150 - }
159 + return new CustomActionTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0)))
160 + {
161 + ExecutionType = executionType,
162 + SourceType = sourceType,
163 + Source = FieldAsString(row, 2),
164 + TargetType = targetType,
165 + Target = FieldAsString(row, 3),
166 + Win64 = (caType & WindowsInstallerConstants.MsidbCustomActionType64BitScript) == WindowsInstallerConstants.MsidbCustomActionType64BitScript,
167 + TSAware = (caType & WindowsInstallerConstants.MsidbCustomActionTypeTSAware) == WindowsInstallerConstants.MsidbCustomActionTypeTSAware,
168 + Impersonate = (caType & WindowsInstallerConstants.MsidbCustomActionTypeNoImpersonate) != WindowsInstallerConstants.MsidbCustomActionTypeNoImpersonate,
169 + IgnoreResult = (caType & WindowsInstallerConstants.MsidbCustomActionTypeContinue) == WindowsInstallerConstants.MsidbCustomActionTypeContinue,
170 + Hidden = (caType & WindowsInstallerConstants.MsidbCustomActionTypeHideTarget) == WindowsInstallerConstants.MsidbCustomActionTypeHideTarget,
171 + Async = (caType & WindowsInstallerConstants.MsidbCustomActionTypeAsync) == WindowsInstallerConstants.MsidbCustomActionTypeAsync,
172 + };
173 + }
174
152 - return new FeatureTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0)))
153 - {
154 - Feature_Parent = FieldAsString(row, 1),
155 - Title = FieldAsString(row, 2),
156 - Description = FieldAsString(row, 3),
157 - Display = FieldAsInt(row, 4), // BUGBUGBUG: FieldAsNullableInt(row, 4),
158 - Level = FieldAsInt(row, 5),
159 - Directory_ = FieldAsString(row, 6),
160 - DisallowAbsent = (attributes & WindowsInstallerConstants.MsidbFeatureAttributesUIDisallowAbsent) == WindowsInstallerConstants.MsidbFeatureAttributesUIDisallowAbsent,
161 - DisallowAdvertise = (attributes & WindowsInstallerConstants.MsidbFeatureAttributesDisallowAdvertise) == WindowsInstallerConstants.MsidbFeatureAttributesDisallowAdvertise,
162 - InstallDefault = installDefault,
163 - TypicalDefault = (attributes & WindowsInstallerConstants.MsidbFeatureAttributesFavorAdvertise) == WindowsInstallerConstants.MsidbFeatureAttributesFavorAdvertise ? FeatureTypicalDefault.Advertise : FeatureTypicalDefault.Install,
164 - };
175 + case "Directory":
176 + {
177 + var id = FieldAsString(row, 0);
178 + var splits = SplitDefaultDir(FieldAsString(row, 2));
179 +
180 + var tuple = new DirectoryTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, id))
181 + {
182 + ParentDirectoryRef = FieldAsString(row, 1),
183 + Name = splits[0],
184 + ShortName = splits[1],
185 + SourceName = splits[2],
186 + SourceShortName = splits[3]
187 + };
188 +
189 + if (wixDirectoryById.TryGetValue(id, out var wixDirectoryRow))
190 + {
191 + tuple.ComponentGuidGenerationSeed = FieldAsString(wixDirectoryRow, 1);
192 }
193
167 - case "FeatureComponents":
168 - return DefaultTupleFromRow(typeof(FeatureComponentsTuple), row, columnZeroIsId: false);
169 - case "File":
170 - {
171 - var attributes = FieldAsNullableInt(row, 6);
172 - var readOnly = (attributes & WindowsInstallerConstants.MsidbFileAttributesReadOnly) == WindowsInstallerConstants.MsidbFileAttributesReadOnly;
173 - var hidden = (attributes & WindowsInstallerConstants.MsidbFileAttributesHidden) == WindowsInstallerConstants.MsidbFileAttributesHidden;
174 - var system = (attributes & WindowsInstallerConstants.MsidbFileAttributesSystem) == WindowsInstallerConstants.MsidbFileAttributesSystem;
175 - var vital = (attributes & WindowsInstallerConstants.MsidbFileAttributesVital) == WindowsInstallerConstants.MsidbFileAttributesVital;
176 - var checksum = (attributes & WindowsInstallerConstants.MsidbFileAttributesChecksum) == WindowsInstallerConstants.MsidbFileAttributesChecksum;
177 - bool? compressed = null;
178 - if ((attributes & WindowsInstallerConstants.MsidbFileAttributesNoncompressed) == WindowsInstallerConstants.MsidbFileAttributesNoncompressed)
179 - {
180 - compressed = false;
181 - }
182 - else if ((attributes & WindowsInstallerConstants.MsidbFileAttributesCompressed) == WindowsInstallerConstants.MsidbFileAttributesCompressed)
183 - {
184 - compressed = true;
185 - }
194 + return tuple;
195 + }
196 + case "DrLocator":
197 + return DefaultTupleFromRow(typeof(DrLocatorTuple), row, columnZeroIsId: false);
198 + case "DuplicateFile":
199 + return DefaultTupleFromRow(typeof(DuplicateFileTuple), row, columnZeroIsId: true);
200 + case "Error":
201 + return DefaultTupleFromRow(typeof(ErrorTuple), row, columnZeroIsId: false);
202 + case "Extension":
203 + return DefaultTupleFromRow(typeof(ExtensionTuple), row, columnZeroIsId: false);
204 + case "Feature":
205 + {
206 + var attributes = FieldAsInt(row, 7);
207 + var installDefault = FeatureInstallDefault.Local;
208 + if ((attributes & WindowsInstallerConstants.MsidbFeatureAttributesFollowParent) == WindowsInstallerConstants.MsidbFeatureAttributesFollowParent)
209 + {
210 + installDefault = FeatureInstallDefault.FollowParent;
211 + }
212 + else if ((attributes & WindowsInstallerConstants.MsidbFeatureAttributesFavorSource) == WindowsInstallerConstants.MsidbFeatureAttributesFavorSource)
213 + {
214 + installDefault = FeatureInstallDefault.Source;
215 + }
216
187 - return new FileTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0)))
188 - {
189 - Component_ = FieldAsString(row, 1),
190 - LongFileName = FieldAsString(row, 2),
191 - FileSize = FieldAsInt(row, 3),
192 - Version = FieldAsString(row, 4),
193 - Language = FieldAsString(row, 5),
194 - ReadOnly = readOnly,
195 - Hidden = hidden,
196 - System = system,
197 - Vital = vital,
198 - Checksum = checksum,
199 - Compressed = compressed,
200 - };
217 + return new FeatureTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0)))
218 + {
219 + ParentFeatureRef = FieldAsString(row, 1),
220 + Title = FieldAsString(row, 2),
221 + Description = FieldAsString(row, 3),
222 + Display = FieldAsInt(row, 4), // BUGBUGBUG: FieldAsNullableInt(row, 4),
223 + Level = FieldAsInt(row, 5),
224 + DirectoryRef = FieldAsString(row, 6),
225 + DisallowAbsent = (attributes & WindowsInstallerConstants.MsidbFeatureAttributesUIDisallowAbsent) == WindowsInstallerConstants.MsidbFeatureAttributesUIDisallowAbsent,
226 + DisallowAdvertise = (attributes & WindowsInstallerConstants.MsidbFeatureAttributesDisallowAdvertise) == WindowsInstallerConstants.MsidbFeatureAttributesDisallowAdvertise,
227 + InstallDefault = installDefault,
228 + TypicalDefault = (attributes & WindowsInstallerConstants.MsidbFeatureAttributesFavorAdvertise) == WindowsInstallerConstants.MsidbFeatureAttributesFavorAdvertise ? FeatureTypicalDefault.Advertise : FeatureTypicalDefault.Install,
229 + };
230 + }
231 +
232 + case "FeatureComponents":
233 + return DefaultTupleFromRow(typeof(FeatureComponentsTuple), row, columnZeroIsId: false);
234 + case "File":
235 + {
236 + var attributes = FieldAsNullableInt(row, 6);
237 + var readOnly = (attributes & WindowsInstallerConstants.MsidbFileAttributesReadOnly) == WindowsInstallerConstants.MsidbFileAttributesReadOnly;
238 + var hidden = (attributes & WindowsInstallerConstants.MsidbFileAttributesHidden) == WindowsInstallerConstants.MsidbFileAttributesHidden;
239 + var system = (attributes & WindowsInstallerConstants.MsidbFileAttributesSystem) == WindowsInstallerConstants.MsidbFileAttributesSystem;
240 + var vital = (attributes & WindowsInstallerConstants.MsidbFileAttributesVital) == WindowsInstallerConstants.MsidbFileAttributesVital;
241 + var checksum = (attributes & WindowsInstallerConstants.MsidbFileAttributesChecksum) == WindowsInstallerConstants.MsidbFileAttributesChecksum;
242 + bool? compressed = null;
243 + if ((attributes & WindowsInstallerConstants.MsidbFileAttributesNoncompressed) == WindowsInstallerConstants.MsidbFileAttributesNoncompressed)
244 + {
245 + compressed = false;
246 + }
247 + else if ((attributes & WindowsInstallerConstants.MsidbFileAttributesCompressed) == WindowsInstallerConstants.MsidbFileAttributesCompressed)
248 + {
249 + compressed = true;
250 }
251
203 - case "Font":
204 - return DefaultTupleFromRow(typeof(FontTuple), row, columnZeroIsId: false);
205 - case "Icon":
206 - return DefaultTupleFromRow(typeof(IconTuple), row, columnZeroIsId: false);
207 - case "InstallExecuteSequence":
208 - return DefaultTupleFromRow(typeof(InstallExecuteSequenceTuple), row, columnZeroIsId: false);
209 - case "LockPermissions":
210 - return DefaultTupleFromRow(typeof(LockPermissionsTuple), row, columnZeroIsId: false);
211 - case "Media":
212 - return DefaultTupleFromRow(typeof(MediaTuple), row, columnZeroIsId: false);
213 - case "MIME":
214 - return DefaultTupleFromRow(typeof(MIMETuple), row, columnZeroIsId: false);
215 - case "MoveFile":
216 - return DefaultTupleFromRow(typeof(MoveFileTuple), row, columnZeroIsId: false);
217 - case "MsiAssembly":
218 - return DefaultTupleFromRow(typeof(MsiAssemblyTuple), row, columnZeroIsId: false);
219 - case "MsiShortcutProperty":
220 - return DefaultTupleFromRow(typeof(MsiShortcutPropertyTuple), row, columnZeroIsId: false);
221 - case "ProgId":
222 - return DefaultTupleFromRow(typeof(ProgIdTuple), row, columnZeroIsId: false);
223 - case "Property":
224 - return DefaultTupleFromRow(typeof(PropertyTuple), row, columnZeroIsId: false);
225 - case "PublishComponent":
226 - return DefaultTupleFromRow(typeof(PublishComponentTuple), row, columnZeroIsId: false);
227 - case "Registry":
228 - {
229 - var value = FieldAsString(row, 4);
230 - var valueType = RegistryValueType.String;
231 - var valueAction = RegistryValueActionType.Write;
232 -
233 - if (!String.IsNullOrEmpty(value))
234 - {
235 - if (value.StartsWith("#x", StringComparison.Ordinal))
236 - {
237 - valueType = RegistryValueType.Binary;
238 - value = value.Substring(2);
239 - }
240 - else if (value.StartsWith("#%", StringComparison.Ordinal))
241 - {
242 - valueType = RegistryValueType.Expandable;
243 - value = value.Substring(2);
244 - }
245 - else if (value.StartsWith("#", StringComparison.Ordinal))
246 - {
247 - valueType = RegistryValueType.Integer;
248 - value = value.Substring(1);
249 - }
250 - else if (value.StartsWith("[~]", StringComparison.Ordinal) && value.EndsWith("[~]", StringComparison.Ordinal))
251 - {
252 - value = value.Substring(3, value.Length - 6);
253 - valueType = RegistryValueType.MultiString;
254 - valueAction = RegistryValueActionType.Write;
255 - }
256 - else if (value.StartsWith("[~]", StringComparison.Ordinal))
257 - {
258 - value = value.Substring(3);
259 - valueType = RegistryValueType.MultiString;
260 - valueAction = RegistryValueActionType.Append;
261 - }
262 - else if (value.EndsWith("[~]", StringComparison.Ordinal))
263 - {
264 - value = value.Substring(0, value.Length - 3);
265 - valueType = RegistryValueType.MultiString;
266 - valueAction = RegistryValueActionType.Prepend;
267 - }
268 - }
252 + var id = FieldAsString(row, 0);
253
270 - return new RegistryTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0)))
271 - {
272 - Root = (RegistryRootType)FieldAsInt(row, 1),
273 - Key = FieldAsString(row, 2),
274 - Name = FieldAsString(row, 3),
275 - Value = value,
276 - Component_ = FieldAsString(row, 5),
277 - ValueAction = valueAction,
278 - ValueType = valueType,
279 - };
254 + var tuple = new FileTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, id))
255 + {
256 + ComponentRef = FieldAsString(row, 1),
257 + Name = FieldAsString(row, 2),
258 + FileSize = FieldAsInt(row, 3),
259 + Version = FieldAsString(row, 4),
260 + Language = FieldAsString(row, 5),
261 + ReadOnly = readOnly,
262 + Hidden = hidden,
263 + System = system,
264 + Vital = vital,
265 + Checksum = checksum,
266 + Compressed = compressed,
267 + };
268 +
269 + if (bindPathsById.TryGetValue(id, out var bindPathRow))
270 + {
271 + tuple.BindPath = FieldAsString(bindPathRow, 1) ?? String.Empty;
272 }
273
282 - case "RegLocator":
283 - return DefaultTupleFromRow(typeof(RegLocatorTuple), row, columnZeroIsId: false);
284 - case "RemoveFile":
285 - return DefaultTupleFromRow(typeof(RemoveFileTuple), row, columnZeroIsId: false);
286 - case "RemoveRegistry":
274 + if (fontsById.TryGetValue(id, out var fontRow))
275 {
288 - return new RemoveRegistryTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0)))
289 - {
290 - Action = RemoveRegistryActionType.RemoveOnInstall,
291 - Root = (RegistryRootType)FieldAsInt(row, 1),
292 - Key = FieldAsString(row, 2),
293 - Name = FieldAsString(row, 3),
294 - Component_ = FieldAsString(row, 4),
295 - };
276 + tuple.FontTitle = FieldAsString(fontRow, 1) ?? String.Empty;
277 }
278
298 - case "ReserveCost":
299 - return DefaultTupleFromRow(typeof(ReserveCostTuple), row, columnZeroIsId: false);
300 - case "ServiceControl":
279 + if (selfRegById.TryGetValue(id, out var selfRegRow))
280 {
302 - var events = FieldAsInt(row, 2);
303 - var wait = FieldAsNullableInt(row, 4);
304 - return new ServiceControlTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0)))
305 - {
306 - Name = FieldAsString(row, 1),
307 - Arguments = FieldAsString(row, 3),
308 - Wait = !wait.HasValue || wait.Value == 1,
309 - Component_ = FieldAsString(row, 5),
310 - InstallRemove = (events & WindowsInstallerConstants.MsidbServiceControlEventDelete) == WindowsInstallerConstants.MsidbServiceControlEventDelete,
311 - UninstallRemove = (events & WindowsInstallerConstants.MsidbServiceControlEventUninstallDelete) == WindowsInstallerConstants.MsidbServiceControlEventUninstallDelete,
312 - InstallStart = (events & WindowsInstallerConstants.MsidbServiceControlEventStart) == WindowsInstallerConstants.MsidbServiceControlEventStart,
313 - UninstallStart = (events & WindowsInstallerConstants.MsidbServiceControlEventUninstallStart) == WindowsInstallerConstants.MsidbServiceControlEventUninstallStart,
314 - InstallStop = (events & WindowsInstallerConstants.MsidbServiceControlEventStop) == WindowsInstallerConstants.MsidbServiceControlEventStop,
315 - UninstallStop = (events & WindowsInstallerConstants.MsidbServiceControlEventUninstallStop) == WindowsInstallerConstants.MsidbServiceControlEventUninstallStop,
316 - };
281 + tuple.SelfRegCost = FieldAsNullableInt(selfRegRow, 1) ?? 0;
282 }
283
319 - case "ServiceInstall":
320 - return DefaultTupleFromRow(typeof(ServiceInstallTuple), row, columnZeroIsId: true);
321 - case "Shortcut":
322 - return DefaultTupleFromRow(typeof(ShortcutTuple), row, columnZeroIsId: true);
323 - case "Signature":
324 - return DefaultTupleFromRow(typeof(SignatureTuple), row, columnZeroIsId: false);
325 - case "Upgrade":
284 + return tuple;
285 + }
286 + case "Font":
287 + return null;
288 + case "Icon":
289 + return DefaultTupleFromRow(typeof(IconTuple), row, columnZeroIsId: true);
290 + case "InstallExecuteSequence":
291 + return DefaultTupleFromRow(typeof(InstallExecuteSequenceTuple), row, columnZeroIsId: false);
292 + case "LockPermissions":
293 + return DefaultTupleFromRow(typeof(LockPermissionsTuple), row, columnZeroIsId: false);
294 + case "Media":
295 + {
296 + var diskId = FieldAsInt(row, 0);
297 + var tuple = new MediaTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, diskId))
298 {
327 - var attributes = FieldAsInt(row, 4);
328 - return new UpgradeTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0)))
329 - {
330 - UpgradeCode = FieldAsString(row, 0),
331 - VersionMin = FieldAsString(row, 1),
332 - VersionMax = FieldAsString(row, 2),
333 - Language = FieldAsString(row, 3),
334 - Remove = FieldAsString(row, 5),
335 - ActionProperty = FieldAsString(row, 6),
336 - MigrateFeatures = (attributes & WindowsInstallerConstants.MsidbUpgradeAttributesMigrateFeatures) == WindowsInstallerConstants.MsidbUpgradeAttributesMigrateFeatures,
337 - OnlyDetect = (attributes & WindowsInstallerConstants.MsidbUpgradeAttributesOnlyDetect) == WindowsInstallerConstants.MsidbUpgradeAttributesOnlyDetect,
338 - IgnoreRemoveFailures = (attributes & WindowsInstallerConstants.MsidbUpgradeAttributesIgnoreRemoveFailure) == WindowsInstallerConstants.MsidbUpgradeAttributesIgnoreRemoveFailure,
339 - VersionMinInclusive = (attributes & WindowsInstallerConstants.MsidbUpgradeAttributesVersionMinInclusive) == WindowsInstallerConstants.MsidbUpgradeAttributesVersionMinInclusive,
340 - VersionMaxInclusive = (attributes & WindowsInstallerConstants.MsidbUpgradeAttributesVersionMaxInclusive) == WindowsInstallerConstants.MsidbUpgradeAttributesVersionMaxInclusive,
341 - ExcludeLanguages = (attributes & WindowsInstallerConstants.MsidbUpgradeAttributesLanguagesExclusive) == WindowsInstallerConstants.MsidbUpgradeAttributesLanguagesExclusive,
342 - };
299 + DiskId = diskId,
300 + LastSequence = FieldAsNullableInt(row, 1),
301 + DiskPrompt = FieldAsString(row, 2),
302 + Cabinet = FieldAsString(row, 3),
303 + VolumeLabel = FieldAsString(row, 4),
304 + Source = FieldAsString(row, 5)
305 + };
306 +
307 + if (wixMediaByDiskId.TryGetValue(diskId, out var wixMediaRow))
308 + {
309 + var compressionLevel = FieldAsString(wixMediaRow, 1);
310 +
311 + tuple.CompressionLevel = String.IsNullOrEmpty(compressionLevel) ? null : (CompressionLevel?)Enum.Parse(typeof(CompressionLevel), compressionLevel, true);
312 + tuple.Layout = wixMediaRow.Layout;
313 }
314
345 - case "Verb":
346 - return DefaultTupleFromRow(typeof(VerbTuple), row, columnZeroIsId: false);
347 - //case "WixAction":
348 - // return new WixActionTuple(SourceLineNumber4(row.SourceLineNumbers))
349 - // {
350 - // SequenceTable = (SequenceTable)Enum.Parse(typeof(SequenceTable), FieldAsString(row, 0)),
351 - // Action = FieldAsString(row, 1),
352 - // Condition = FieldAsString(row, 2),
353 - // Sequence = FieldAsInt(row, 3),
354 - // Before = FieldAsString(row, 4),
355 - // After = FieldAsString(row, 5),
356 - // Overridable = FieldAsNullableInt(row, 6) != 0,
357 - // };
358 - case "WixFile":
359 - var assemblyAttributes3 = FieldAsNullableInt(row, 1);
360 - return new WixFileTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0)))
315 + return tuple;
316 + }
317 + case "MIME":
318 + return DefaultTupleFromRow(typeof(MIMETuple), row, columnZeroIsId: false);
319 + case "ModuleIgnoreTable":
320 + return DefaultTupleFromRow(typeof(ModuleIgnoreTableTuple), row, columnZeroIsId: true);
321 + case "MoveFile":
322 + return DefaultTupleFromRow(typeof(MoveFileTuple), row, columnZeroIsId: true);
323 + case "MsiAssembly":
324 + return DefaultTupleFromRow(typeof(MsiAssemblyTuple), row, columnZeroIsId: false);
325 + case "MsiLockPermissionsEx":
326 + return DefaultTupleFromRow(typeof(MsiLockPermissionsExTuple), row, columnZeroIsId: true);
327 + case "MsiShortcutProperty":
328 + return DefaultTupleFromRow(typeof(MsiShortcutPropertyTuple), row, columnZeroIsId: true);
329 + case "ODBCDataSource":
330 + return DefaultTupleFromRow(typeof(ODBCDataSourceTuple), row, columnZeroIsId: true);
331 + case "ODBCDriver":
332 + return DefaultTupleFromRow(typeof(ODBCDriverTuple), row, columnZeroIsId: true);
333 + case "ODBCTranslator":
334 + return DefaultTupleFromRow(typeof(ODBCTranslatorTuple), row, columnZeroIsId: true);
335 + case "ProgId":
336 + return DefaultTupleFromRow(typeof(ProgIdTuple), row, columnZeroIsId: false);
337 + case "Property":
338 + return DefaultTupleFromRow(typeof(PropertyTuple), row, columnZeroIsId: true);
339 + case "PublishComponent":
340 + return DefaultTupleFromRow(typeof(PublishComponentTuple), row, columnZeroIsId: false);
341 + case "Registry":
342 + {
343 + var value = FieldAsString(row, 4);
344 + var valueType = RegistryValueType.String;
345 + var valueAction = RegistryValueActionType.Write;
346 +
347 + if (!String.IsNullOrEmpty(value))
348 + {
349 + if (value.StartsWith("#x", StringComparison.Ordinal))
350 {
362 - AssemblyType = assemblyAttributes3 == 0 ? FileAssemblyType.DotNetAssembly : assemblyAttributes3 == 1 ? FileAssemblyType.Win32Assembly : FileAssemblyType.NotAnAssembly,
363 - File_AssemblyManifest = FieldAsString(row, 2),
364 - File_AssemblyApplication = FieldAsString(row, 3),
365 - Directory_ = FieldAsString(row, 4),
366 - DiskId = FieldAsInt(row, 5), // TODO: BUGBUGBUG: AB#2626: DiskId is nullable in WiX v3.
367 - Source = new IntermediateFieldPathValue() { Path = FieldAsString(row, 6) },
368 - ProcessorArchitecture = FieldAsString(row, 7),
369 - PatchGroup = FieldAsInt(row, 8),
370 - Attributes = FieldAsInt(row, 9),
371 - };
372 - case "WixProperty":
373 - {
374 - var attributes = FieldAsInt(row, 1);
375 - return new WixPropertyTuple(SourceLineNumber4(row.SourceLineNumbers))
351 + valueType = RegistryValueType.Binary;
352 + value = value.Substring(2);
353 + }
354 + else if (value.StartsWith("#%", StringComparison.Ordinal))
355 + {
356 + valueType = RegistryValueType.Expandable;
357 + value = value.Substring(2);
358 + }
359 + else if (value.StartsWith("#", StringComparison.Ordinal))
360 + {
361 + valueType = RegistryValueType.Integer;
362 + value = value.Substring(1);
363 + }
364 + else if (value.StartsWith("[~]", StringComparison.Ordinal) && value.EndsWith("[~]", StringComparison.Ordinal))
365 + {
366 + value = value.Substring(3, value.Length - 6);
367 + valueType = RegistryValueType.MultiString;
368 + valueAction = RegistryValueActionType.Write;
369 + }
370 + else if (value.StartsWith("[~]", StringComparison.Ordinal))
371 + {
372 + value = value.Substring(3);
373 + valueType = RegistryValueType.MultiString;
374 + valueAction = RegistryValueActionType.Append;
375 + }
376 + else if (value.EndsWith("[~]", StringComparison.Ordinal))
377 {
377 - Property_ = FieldAsString(row, 0),
378 - Admin = (attributes & 0x1) == 0x1,
379 - Hidden = (attributes & 0x2) == 0x2,
380 - Secure = (attributes & 0x4) == 0x4,
381 - };
378 + value = value.Substring(0, value.Length - 3);
379 + valueType = RegistryValueType.MultiString;
380 + valueAction = RegistryValueActionType.Prepend;
381 + }
382 }
383
384 - default:
385 - return GenericTupleFromCustomRow(row, columnZeroIsId: false);
384 + return new RegistryTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0)))
385 + {
386 + Root = (RegistryRootType)FieldAsInt(row, 1),
387 + Key = FieldAsString(row, 2),
388 + Name = FieldAsString(row, 3),
389 + Value = value,
390 + ComponentRef = FieldAsString(row, 5),
391 + ValueAction = valueAction,
392 + ValueType = valueType,
393 + };
394 + }
395 + case "RegLocator":
396 + {
397 + var type = FieldAsInt(row, 4);
398 +
399 + return new RegLocatorTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0)))
400 + {
401 + Root = (RegistryRootType)FieldAsInt(row, 1),
402 + Key = FieldAsString(row, 2),
403 + Name = FieldAsString(row, 3),
404 + Type = (RegLocatorType)(type & 0xF),
405 + Win64 = (type & WindowsInstallerConstants.MsidbLocatorType64bit) == WindowsInstallerConstants.MsidbLocatorType64bit
406 + };
407 + }
408 + case "RemoveFile":
409 + {
410 + var installMode = FieldAsInt(row, 4);
411 + return new RemoveFileTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0)))
412 + {
413 + ComponentRef = FieldAsString(row, 1),
414 + FileName = FieldAsString(row, 2),
415 + DirProperty = FieldAsString(row, 3),
416 + OnInstall = (installMode & WindowsInstallerConstants.MsidbRemoveFileInstallModeOnInstall) == WindowsInstallerConstants.MsidbRemoveFileInstallModeOnInstall ? (bool?)true : null,
417 + OnUninstall = (installMode & WindowsInstallerConstants.MsidbRemoveFileInstallModeOnRemove) == WindowsInstallerConstants.MsidbRemoveFileInstallModeOnRemove ? (bool?)true : null
418 + };
419 + }
420 + case "RemoveRegistry":
421 + {
422 + return new RemoveRegistryTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0)))
423 + {
424 + Action = RemoveRegistryActionType.RemoveOnInstall,
425 + Root = (RegistryRootType)FieldAsInt(row, 1),
426 + Key = FieldAsString(row, 2),
427 + Name = FieldAsString(row, 3),
428 + ComponentRef = FieldAsString(row, 4),
429 + };
430 + }
431 +
432 + case "ReserveCost":
433 + return DefaultTupleFromRow(typeof(ReserveCostTuple), row, columnZeroIsId: true);
434 + case "SelfReg":
435 + return null;
436 + case "ServiceControl":
437 + {
438 + var events = FieldAsInt(row, 2);
439 + var wait = FieldAsNullableInt(row, 4);
440 + return new ServiceControlTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0)))
441 + {
442 + Name = FieldAsString(row, 1),
443 + Arguments = FieldAsString(row, 3),
444 + Wait = !wait.HasValue || wait.Value == 1,
445 + ComponentRef = FieldAsString(row, 5),
446 + InstallRemove = (events & WindowsInstallerConstants.MsidbServiceControlEventDelete) == WindowsInstallerConstants.MsidbServiceControlEventDelete,
447 + UninstallRemove = (events & WindowsInstallerConstants.MsidbServiceControlEventUninstallDelete) == WindowsInstallerConstants.MsidbServiceControlEventUninstallDelete,
448 + InstallStart = (events & WindowsInstallerConstants.MsidbServiceControlEventStart) == WindowsInstallerConstants.MsidbServiceControlEventStart,
449 + UninstallStart = (events & WindowsInstallerConstants.MsidbServiceControlEventUninstallStart) == WindowsInstallerConstants.MsidbServiceControlEventUninstallStart,
450 + InstallStop = (events & WindowsInstallerConstants.MsidbServiceControlEventStop) == WindowsInstallerConstants.MsidbServiceControlEventStop,
451 + UninstallStop = (events & WindowsInstallerConstants.MsidbServiceControlEventUninstallStop) == WindowsInstallerConstants.MsidbServiceControlEventUninstallStop,
452 + };
453 + }
454 +
455 + case "ServiceInstall":
456 + return DefaultTupleFromRow(typeof(ServiceInstallTuple), row, columnZeroIsId: true);
457 + case "Shortcut":
458 + {
459 + var splitName = FieldAsString(row, 2).Split('|');
460 +
461 + return new ShortcutTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0)))
462 + {
463 + DirectoryRef = FieldAsString(row, 1),
464 + Name = splitName.Length > 1 ? splitName[1] : splitName[0],
465 + ShortName = splitName.Length > 1 ? splitName[0] : null,
466 + ComponentRef = FieldAsString(row, 3),
467 + Target = FieldAsString(row, 4),
468 + Arguments = FieldAsString(row, 5),
469 + Description = FieldAsString(row, 6),
470 + Hotkey = FieldAsNullableInt(row, 7),
471 + IconRef = FieldAsString(row, 8),
472 + IconIndex = FieldAsNullableInt(row, 9),
473 + Show = (ShortcutShowType?)FieldAsNullableInt(row, 10),
474 + WorkingDirectory = FieldAsString(row, 11),
475 + DisplayResourceDll = FieldAsString(row, 12),
476 + DisplayResourceId = FieldAsNullableInt(row, 13),
477 + DescriptionResourceDll = FieldAsString(row, 14),
478 + DescriptionResourceId= FieldAsNullableInt(row, 15),
479 + };
480 + }
481 + case "Signature":
482 + return DefaultTupleFromRow(typeof(SignatureTuple), row, columnZeroIsId: false);
483 + case "UIText":
484 + return DefaultTupleFromRow(typeof(UITextTuple), row, columnZeroIsId: true);
485 + case "Upgrade":
486 + {
487 + var attributes = FieldAsInt(row, 4);
488 + return new UpgradeTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0)))
489 + {
490 + UpgradeCode = FieldAsString(row, 0),
491 + VersionMin = FieldAsString(row, 1),
492 + VersionMax = FieldAsString(row, 2),
493 + Language = FieldAsString(row, 3),
494 + Remove = FieldAsString(row, 5),
495 + ActionProperty = FieldAsString(row, 6),
496 + MigrateFeatures = (attributes & WindowsInstallerConstants.MsidbUpgradeAttributesMigrateFeatures) == WindowsInstallerConstants.MsidbUpgradeAttributesMigrateFeatures,
497 + OnlyDetect = (attributes & WindowsInstallerConstants.MsidbUpgradeAttributesOnlyDetect) == WindowsInstallerConstants.MsidbUpgradeAttributesOnlyDetect,
498 + IgnoreRemoveFailures = (attributes & WindowsInstallerConstants.MsidbUpgradeAttributesIgnoreRemoveFailure) == WindowsInstallerConstants.MsidbUpgradeAttributesIgnoreRemoveFailure,
499 + VersionMinInclusive = (attributes & WindowsInstallerConstants.MsidbUpgradeAttributesVersionMinInclusive) == WindowsInstallerConstants.MsidbUpgradeAttributesVersionMinInclusive,
500 + VersionMaxInclusive = (attributes & WindowsInstallerConstants.MsidbUpgradeAttributesVersionMaxInclusive) == WindowsInstallerConstants.MsidbUpgradeAttributesVersionMaxInclusive,
501 + ExcludeLanguages = (attributes & WindowsInstallerConstants.MsidbUpgradeAttributesLanguagesExclusive) == WindowsInstallerConstants.MsidbUpgradeAttributesLanguagesExclusive,
502 + };
503 + }
504 + case "Verb":
505 + return DefaultTupleFromRow(typeof(VerbTuple), row, columnZeroIsId: false);
506 + case "WixAction":
507 + var sequenceTable = FieldAsString(row, 0);
508 + return new WixActionTuple(SourceLineNumber4(row.SourceLineNumbers))
509 + {
510 + SequenceTable = (SequenceTable)Enum.Parse(typeof(SequenceTable), sequenceTable == "AdvtExecuteSequence" ? nameof(SequenceTable.AdvertiseExecuteSequence) : sequenceTable),
511 + Action = FieldAsString(row, 1),
512 + Condition = FieldAsString(row, 2),
513 + Sequence = FieldAsNullableInt(row, 3),
514 + Before = FieldAsString(row, 4),
515 + After = FieldAsString(row, 5),
516 + Overridable = FieldAsNullableInt(row, 6) != 0,
517 + };
518 + case "WixBootstrapperApplication":
519 + return DefaultTupleFromRow(typeof(WixBootstrapperApplicationTuple), row, columnZeroIsId: true);
520 + case "WixBundleContainer":
521 + return DefaultTupleFromRow(typeof(WixBundleContainerTuple), row, columnZeroIsId: true);
522 + case "WixBundleVariable":
523 + return DefaultTupleFromRow(typeof(WixBundleVariableTuple), row, columnZeroIsId: true);
524 + case "WixChainItem":
525 + return DefaultTupleFromRow(typeof(WixChainItemTuple), row, columnZeroIsId: true);
526 + case "WixCustomTable":
527 + return DefaultTupleFromRow(typeof(WixCustomTableTuple), row, columnZeroIsId: true);
528 + case "WixDeltaPatchFile":
529 + return DefaultTupleFromRow(typeof(WixDeltaPatchFileTuple), row, columnZeroIsId: true);
530 + case "WixDirectory":
531 + return null;
532 + case "WixFile":
533 + var assemblyAttributes3 = FieldAsNullableInt(row, 1);
534 + return new WixFileTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0)))
535 + {
536 + AssemblyType = assemblyAttributes3 == 0 ? FileAssemblyType.DotNetAssembly : assemblyAttributes3 == 1 ? FileAssemblyType.Win32Assembly : FileAssemblyType.NotAnAssembly,
537 + AssemblyManifestFileRef = FieldAsString(row, 2),
538 + AssemblyApplicationFileRef = FieldAsString(row, 3),
539 + DirectoryRef = FieldAsString(row, 4),
540 + DiskId = FieldAsNullableInt(row, 5) ?? 0,
541 + Source = new IntermediateFieldPathValue() { Path = FieldAsString(row, 6) },
542 + ProcessorArchitecture = FieldAsString(row, 7),
543 + PatchGroup = FieldAsInt(row, 8),
544 + Attributes = FieldAsInt(row, 9),
545 + PatchAttributes = (PatchAttributeType)FieldAsInt(row, 10),
546 + };
547 + case "WixInstanceTransforms":
548 + return DefaultTupleFromRow(typeof(WixInstanceTransformsTuple), row, columnZeroIsId: true);
549 + case "WixMedia":
550 + return null;
551 + case "WixMerge":
552 + return DefaultTupleFromRow(typeof(WixMergeTuple), row, columnZeroIsId: true);
553 + case "WixPatchBaseline":
554 + return DefaultTupleFromRow(typeof(WixPatchBaselineTuple), row, columnZeroIsId: true);
555 + case "WixProperty":
556 + {
557 + var attributes = FieldAsInt(row, 1);
558 + return new WixPropertyTuple(SourceLineNumber4(row.SourceLineNumbers))
559 + {
560 + PropertyRef = FieldAsString(row, 0),
561 + Admin = (attributes & 0x1) == 0x1,
562 + Hidden = (attributes & 0x2) == 0x2,
563 + Secure = (attributes & 0x4) == 0x4,
564 + };
565 + }
566 + case "WixSuppressModularization":
567 + return DefaultTupleFromRow(typeof(WixSuppressModularizationTuple), row, columnZeroIsId: true);
568 + case "WixUI":
569 + return DefaultTupleFromRow(typeof(WixUITuple), row, columnZeroIsId: true);
570 + case "WixVariable":
571 + return DefaultTupleFromRow(typeof(WixVariableTuple), row, columnZeroIsId: true);
572 + default:
573 + return GenericTupleFromCustomRow(row, columnZeroIsId: false);
574 }
575 }
576
@@ -470,16 +658,16 @@ namespace WixToolset.Converters.Tupleizer
658 {
659 switch (columnType)
660 {
473 - case Wix3.ColumnType.Number:
474 - return IntermediateFieldType.Number;
475 - case Wix3.ColumnType.Object:
476 - return IntermediateFieldType.Path;
477 - case Wix3.ColumnType.Unknown:
478 - case Wix3.ColumnType.String:
479 - case Wix3.ColumnType.Localized:
480 - case Wix3.ColumnType.Preserved:
481 - default:
482 - return IntermediateFieldType.String;
661 + case Wix3.ColumnType.Number:
662 + return IntermediateFieldType.Number;
663 + case Wix3.ColumnType.Object:
664 + return IntermediateFieldType.Path;
665 + case Wix3.ColumnType.Unknown:
666 + case Wix3.ColumnType.String:
667 + case Wix3.ColumnType.Localized:
668 + case Wix3.ColumnType.Preserved:
669 + default:
670 + return IntermediateFieldType.String;
671 }
672 }
673
@@ -520,22 +708,22 @@ namespace WixToolset.Converters.Tupleizer
708 var column = row.Fields[i].Column;
709 switch (column.Type)
710 {
523 - case Wix3.ColumnType.String:
524 - case Wix3.ColumnType.Localized:
525 - case Wix3.ColumnType.Object:
526 - case Wix3.ColumnType.Preserved:
527 - tuple.Set(i - offset, FieldAsString(row, i));
528 - break;
529 - case Wix3.ColumnType.Number:
530 - int? nullableValue = FieldAsNullableInt(row, i);
531 - // TODO: Consider whether null values should be coerced to their default value when
532 - // a column is not nullable. For now, just pass through the null.
533 - //int value = FieldAsInt(row, i);
534 - //tuple.Set(i - offset, column.IsNullable ? nullableValue : value);
535 - tuple.Set(i - offset, nullableValue);
711 + case Wix3.ColumnType.String:
712 + case Wix3.ColumnType.Localized:
713 + case Wix3.ColumnType.Object:
714 + case Wix3.ColumnType.Preserved:
715 + tuple.Set(i - offset, FieldAsString(row, i));
716 + break;
717 + case Wix3.ColumnType.Number:
718 + int? nullableValue = FieldAsNullableInt(row, i);
719 + // TODO: Consider whether null values should be coerced to their default value when
720 + // a column is not nullable. For now, just pass through the null.
721 + //int value = FieldAsInt(row, i);
722 + //tuple.Set(i - offset, column.IsNullable ? nullableValue : value);
723 + tuple.Set(i - offset, nullableValue);
724 + break;
725 + case Wix3.ColumnType.Unknown:
726 break;
537 - case Wix3.ColumnType.Unknown:
538 - break;
727 }
728 }
729 }
@@ -545,15 +733,15 @@ namespace WixToolset.Converters.Tupleizer
733 var column = row.Fields[0].Column;
734 switch (column.Type)
735 {
548 - case Wix3.ColumnType.String:
549 - case Wix3.ColumnType.Localized:
550 - case Wix3.ColumnType.Object:
551 - case Wix3.ColumnType.Preserved:
552 - return new Identifier(AccessModifier.Public, (string)row.Fields[0].Data);
553 - case Wix3.ColumnType.Number:
554 - return new Identifier(AccessModifier.Public, FieldAsInt(row, 0));
555 - default:
556 - return null;
736 + case Wix3.ColumnType.String:
737 + case Wix3.ColumnType.Localized:
738 + case Wix3.ColumnType.Object:
739 + case Wix3.ColumnType.Preserved:
740 + return new Identifier(AccessModifier.Public, (string)row.Fields[0].Data);
741 + case Wix3.ColumnType.Number:
742 + return new Identifier(AccessModifier.Public, FieldAsInt(row, 0));
743 + default:
744 + return null;
745 }
746 }
747
@@ -561,20 +749,20 @@ namespace WixToolset.Converters.Tupleizer
749 {
750 switch (outputType)
751 {
564 - case Wix3.OutputType.Bundle:
565 - return SectionType.Bundle;
566 - case Wix3.OutputType.Module:
567 - return SectionType.Module;
568 - case Wix3.OutputType.Patch:
569 - return SectionType.Patch;
570 - case Wix3.OutputType.PatchCreation:
571 - return SectionType.PatchCreation;
572 - case Wix3.OutputType.Product:
573 - return SectionType.Product;
574 - case Wix3.OutputType.Transform:
575 - case Wix3.OutputType.Unknown:
576 - default:
577 - return SectionType.Unknown;
752 + case Wix3.OutputType.Bundle:
753 + return SectionType.Bundle;
754 + case Wix3.OutputType.Module:
755 + return SectionType.Module;
756 + case Wix3.OutputType.Patch:
757 + return SectionType.Patch;
758 + case Wix3.OutputType.PatchCreation:
759 + return SectionType.PatchCreation;
760 + case Wix3.OutputType.Product:
761 + return SectionType.Product;
762 + case Wix3.OutputType.Transform:
763 + case Wix3.OutputType.Unknown:
764 + default:
765 + return SectionType.Unknown;
766 }
767 }
768
@@ -605,5 +793,19 @@ namespace WixToolset.Converters.Tupleizer
793 return Convert.ToInt32(field.Data);
794 }
795 }
796 +
797 + private static string[] SplitDefaultDir(string defaultDir)
798 + {
799 + var split1 = defaultDir.Split(':');
800 + var targetSplit = split1.Length > 1 ? split1[1].Split('|') : split1[0].Split('|');
801 + var sourceSplit = split1.Length > 1 ? split1[0].Split('|') : new[] { String.Empty };
802 + return new[]
803 + {
804 + targetSplit.Length > 1 ? targetSplit[1] : targetSplit[0],
805 + targetSplit.Length > 1 ? targetSplit[0] : null,
806 + sourceSplit.Length > 1 ? sourceSplit[1] : sourceSplit[0],
807 + sourceSplit.Length > 1 ? sourceSplit[0] : null
808 + };
809 + }
810 }
811 }
src/test/WixToolsetTest.Converters.Tupleizer/ConvertTuplesFixture.cs
+455 -292
@@ -3,6 +3,7 @@
3 namespace WixToolsetTest.Converters.Tupleizer
4 {
5 using System;
6 + using System.Collections.Generic;
7 using System.IO;
8 using System.Linq;
9 using WixBuildTools.TestSupport;
@@ -42,350 +43,512 @@ namespace WixToolsetTest.Converters.Tupleizer
43
44 intermediate = Intermediate.Load(wixiplFile);
45
46 + var wixMediaByDiskId = IndexWixMediaTableByDiskId(output);
47 +
48 // Dump to text for easy diffing, with some massaging to keep v3 and v4 diffable.
49 //
50 var tables = output.Tables.Cast<Wix3.Table>();
51 var wix3Dump = tables
52 .SelectMany(table => table.Rows.Cast<Wix3.Row>()
50 - .Select(row => RowToString(row)))
53 + .SelectMany(row => RowToStrings(row, wixMediaByDiskId)))
54 + .Where(s => !String.IsNullOrEmpty(s))
55 + .OrderBy(s => s)
56 .ToArray();
57
58 var tuples = intermediate.Sections.SelectMany(s => s.Tuples);
54 - var wix4Dump = tuples.Select(tuple => TupleToString(tuple)).ToArray();
59 + var wix4Dump = tuples
60 + .SelectMany(tuple => TupleToStrings(tuple))
61 + .OrderBy(s => s)
62 + .ToArray();
63
64 +#if false
65 Assert.Equal(wix3Dump, wix4Dump);
66 +#else // useful when you want to diff the outputs with another diff tool.
67 + var wix3TextDump = String.Join(Environment.NewLine, wix3Dump);
68 + var wix4TextDump = String.Join(Environment.NewLine, wix4Dump);
69
58 - // Useful when you want to diff the outputs with another diff tool...
59 - //
60 - //var wix3TextDump = String.Join(Environment.NewLine, wix3Dump.OrderBy(val => val));
61 - //var wix4TextDump = String.Join(Environment.NewLine, wix4Dump.OrderBy(val => val));
62 - //Assert.Equal(wix3TextDump, wix4TextDump);
70 + File.WriteAllText(Path.Combine(Path.GetTempPath(), "~3.txt"), wix3TextDump);
71 + File.WriteAllText(Path.Combine(Path.GetTempPath(), "~4.txt"), wix4TextDump);
72 +
73 + Assert.Equal(wix3TextDump, wix4TextDump);
74 +#endif
75 }
76 }
77
66 - private static string RowToString(Wix3.Row row)
78 + private static Dictionary<int, Wix3.WixMediaRow> IndexWixMediaTableByDiskId(Wix3.Output output)
79 {
68 - var fields = String.Join(",", row.Fields.Select(field => field.Data?.ToString()));
80 + var wixMediaByDiskId = new Dictionary<int, Wix3.WixMediaRow>();
81 + var wixMediaTable = output.Tables["WixMedia"];
82
70 - // Massage output to match WiX v3 rows and v4 tuples.
71 - //
72 - switch (row.Table.Name)
83 + if (wixMediaTable != null)
84 {
74 - case "File":
75 - var fieldValues = row.Fields.Take(7).Select(field => field.Data?.ToString()).ToArray();
76 - if (fieldValues[3] == null)
77 - {
78 - // "Somebody" sometimes writes out a null field even when the column definition says
79 - // it's non-nullable. Not naming names or anything. (SWID tags.)
80 - fieldValues[3] = "0";
81 - }
82 - fields = String.Join(",", fieldValues);
83 - break;
84 - case "WixFile":
85 - fields = String.Join(",", row.Fields.Take(8).Select(field => field.Data?.ToString()));
86 - break;
85 + foreach (Wix3.WixMediaRow row in wixMediaTable.Rows)
86 + {
87 + wixMediaByDiskId.Add((int)row[0], row);
88 + }
89 }
90
89 - return $"{row.Table.Name},{fields}";
91 + return wixMediaByDiskId;
92 }
93
92 - private static string TupleToString(WixToolset.Data.IntermediateTuple tuple)
94 + private static IEnumerable<string> RowToStrings(Wix3.Row row, Dictionary<int, Wix3.WixMediaRow> wixMediaByDiskId)
95 {
94 - var fields = String.Join(",", tuple.Fields.Select(field => field?.AsString()));
96 + string fields = null;
97
96 - switch (tuple.Definition.Name)
98 + // Massage output to match WiX v3 rows and v4 tuples.
99 + //
100 + switch (row.Table.Name)
101 {
98 - // Massage output to match WiX v3 rows and v4 tuples.
99 - //
100 - case "Component":
101 - {
102 - var componentTuple = (ComponentTuple)tuple;
103 - var attributes = ComponentLocation.Either == componentTuple.Location ? WindowsInstallerConstants.MsidbComponentAttributesOptional : 0;
104 - attributes |= ComponentLocation.SourceOnly == componentTuple.Location ? WindowsInstallerConstants.MsidbComponentAttributesSourceOnly : 0;
105 - attributes |= ComponentKeyPathType.Registry == componentTuple.KeyPathType ? WindowsInstallerConstants.MsidbComponentAttributesRegistryKeyPath : 0;
106 - attributes |= ComponentKeyPathType.OdbcDataSource == componentTuple.KeyPathType ? WindowsInstallerConstants.MsidbComponentAttributesODBCDataSource : 0;
107 - attributes |= componentTuple.DisableRegistryReflection ? WindowsInstallerConstants.MsidbComponentAttributesDisableRegistryReflection : 0;
108 - attributes |= componentTuple.NeverOverwrite ? WindowsInstallerConstants.MsidbComponentAttributesNeverOverwrite : 0;
109 - attributes |= componentTuple.Permanent ? WindowsInstallerConstants.MsidbComponentAttributesPermanent : 0;
110 - attributes |= componentTuple.SharedDllRefCount ? WindowsInstallerConstants.MsidbComponentAttributesSharedDllRefCount : 0;
111 - attributes |= componentTuple.Shared ? WindowsInstallerConstants.MsidbComponentAttributesShared : 0;
112 - attributes |= componentTuple.Transitive ? WindowsInstallerConstants.MsidbComponentAttributesTransitive : 0;
113 - attributes |= componentTuple.UninstallWhenSuperseded ? WindowsInstallerConstants.MsidbComponentAttributes64bit : 0;
114 - attributes |= componentTuple.Win64 ? WindowsInstallerConstants.MsidbComponentAttributes64bit : 0;
115 -
116 - fields = String.Join(",",
117 - componentTuple.ComponentId,
118 - componentTuple.Directory_,
119 - attributes.ToString(),
120 - componentTuple.Condition,
121 - componentTuple.KeyPath
122 - );
123 - break;
124 - }
125 - case "CustomAction":
102 + case "Directory":
103 + var dirs = SplitDefaultDir((string)row[2]);
104 + fields = String.Join(",", row[0], row[1], dirs[0], dirs[1], dirs[2], dirs[3]);
105 + break;
106 + case "File":
107 + {
108 + var fieldValues = row.Fields.Take(7).Select(SafeConvertField).ToArray();
109 + if (fieldValues[3] == null)
110 {
127 - var customActionTuple = (CustomActionTuple)tuple;
128 - var type = customActionTuple.Win64 ? WindowsInstallerConstants.MsidbCustomActionType64BitScript : 0;
129 - type |= customActionTuple.TSAware ? WindowsInstallerConstants.MsidbCustomActionTypeTSAware : 0;
130 - type |= customActionTuple.Impersonate ? 0 : WindowsInstallerConstants.MsidbCustomActionTypeNoImpersonate;
131 - type |= customActionTuple.IgnoreResult ? WindowsInstallerConstants.MsidbCustomActionTypeContinue : 0;
132 - type |= customActionTuple.Hidden ? WindowsInstallerConstants.MsidbCustomActionTypeHideTarget : 0;
133 - type |= customActionTuple.Async ? WindowsInstallerConstants.MsidbCustomActionTypeAsync : 0;
134 - type |= CustomActionExecutionType.FirstSequence == customActionTuple.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeFirstSequence : 0;
135 - type |= CustomActionExecutionType.OncePerProcess == customActionTuple.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeOncePerProcess : 0;
136 - type |= CustomActionExecutionType.ClientRepeat == customActionTuple.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeClientRepeat : 0;
137 - type |= CustomActionExecutionType.Deferred == customActionTuple.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeInScript : 0;
138 - type |= CustomActionExecutionType.Rollback == customActionTuple.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeInScript | WindowsInstallerConstants.MsidbCustomActionTypeRollback : 0;
139 - type |= CustomActionExecutionType.Commit == customActionTuple.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeInScript | WindowsInstallerConstants.MsidbCustomActionTypeCommit : 0;
140 - type |= CustomActionSourceType.File == customActionTuple.SourceType ? WindowsInstallerConstants.MsidbCustomActionTypeSourceFile : 0;
141 - type |= CustomActionSourceType.Directory == customActionTuple.SourceType ? WindowsInstallerConstants.MsidbCustomActionTypeDirectory : 0;
142 - type |= CustomActionSourceType.Property == customActionTuple.SourceType ? WindowsInstallerConstants.MsidbCustomActionTypeProperty : 0;
143 - type |= CustomActionTargetType.Dll == customActionTuple.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeDll : 0;
144 - type |= CustomActionTargetType.Exe == customActionTuple.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeExe : 0;
145 - type |= CustomActionTargetType.TextData == customActionTuple.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeTextData : 0;
146 - type |= CustomActionTargetType.JScript == customActionTuple.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeJScript : 0;
147 - type |= CustomActionTargetType.VBScript == customActionTuple.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeVBScript : 0;
148 -
149 - fields = String.Join(",",
150 - type.ToString(),
151 - customActionTuple.Source,
152 - customActionTuple.Target,
153 - customActionTuple.PatchUninstall ? WindowsInstallerConstants.MsidbCustomActionTypePatchUninstall.ToString() : null
154 - );
155 - break;
111 + // "Somebody" sometimes writes out a null field even when the column definition says
112 + // it's non-nullable. Not naming names or anything. (SWID tags.)
113 + fieldValues[3] = "0";
114 }
157 - case "Feature":
158 - {
159 - var featureTuple = (FeatureTuple)tuple;
160 - var attributes = featureTuple.DisallowAbsent ? WindowsInstallerConstants.MsidbFeatureAttributesUIDisallowAbsent : 0;
161 - attributes |= featureTuple.DisallowAdvertise ? WindowsInstallerConstants.MsidbFeatureAttributesDisallowAdvertise : 0;
162 - attributes |= FeatureInstallDefault.FollowParent == featureTuple.InstallDefault ? WindowsInstallerConstants.MsidbFeatureAttributesFollowParent : 0;
163 - attributes |= FeatureInstallDefault.Source == featureTuple.InstallDefault ? WindowsInstallerConstants.MsidbFeatureAttributesFavorSource : 0;
164 - attributes |= FeatureTypicalDefault.Advertise == featureTuple.TypicalDefault ? WindowsInstallerConstants.MsidbFeatureAttributesFavorAdvertise : 0;
165 -
166 - fields = String.Join(",",
167 - featureTuple.Feature_Parent,
168 - featureTuple.Title,
169 - featureTuple.Description,
170 - featureTuple.Display.ToString(),
171 - featureTuple.Level.ToString(),
172 - featureTuple.Directory_,
173 - attributes.ToString());
174 - break;
175 - }
176 - case "File":
115 + fields = String.Join(",", fieldValues);
116 + break;
117 + }
118 + case "Media":
119 + var compression = wixMediaByDiskId.TryGetValue((int)row[0], out var wixMedia) ? (CompressionLevel?)Enum.Parse(typeof(CompressionLevel), SafeConvertField(wixMedia.Fields[1]), true) : null;
120 +
121 + fields = String.Join(",", row.Fields.Select(SafeConvertField));
122 + fields = String.Join(",", fields, (int?)compression, SafeConvertField(wixMedia?.Fields[2]));
123 + break;
124 + case "RegLocator":
125 + var type = (int)row[4];
126 + fields = String.Join(",", row[0], row[1], row[2], row[3], type & 0xF, (type & 0x10) == 0x10);
127 + break;
128 + case "RemoveFile":
129 + var attributes = (int)row[4];
130 + var onInstall = (attributes & 1) == 1 ? (bool?)true : null;
131 + var onUninstall = (attributes & 2) == 2 ? (bool?)true : null;
132 + fields = String.Join(",", row.Fields.Take(4).Select(SafeConvertField));
133 + fields = String.Join(",", fields, onInstall, onUninstall);
134 + break;
135 + case "Shortcut":
136 + var split = ((string)row[2]).Split('|');
137 + var afterName = String.Join(",", row.Fields.Skip(3).Select(SafeConvertField));
138 + fields = String.Join(",", row[0], row[1], split.Length > 1 ? split[1] : split[0], split.Length > 1 ? split[0] : String.Empty, afterName);
139 + break;
140 + case "WixAction":
141 + var table = (int)SequenceStringToSequenceTable(row[0]);
142 + fields = String.Join(",", table, row[1], row[2], row[3], row[4], row[5], row[6]);
143 + break;
144 + case "WixFile":
145 + {
146 + var fieldValues = row.Fields.Take(10).Select(SafeConvertField).ToArray();
147 + if (fieldValues[8] == null)
148 {
178 - var fileTuple = (FileTuple)tuple;
179 - fields = String.Join(",",
180 - fileTuple.Component_,
181 - fileTuple.LongFileName,
182 - fileTuple.FileSize.ToString(),
183 - fileTuple.Version,
184 - fileTuple.Language,
185 - ((fileTuple.ReadOnly ? WindowsInstallerConstants.MsidbFileAttributesReadOnly : 0)
186 - | (fileTuple.Hidden ? WindowsInstallerConstants.MsidbFileAttributesHidden : 0)
187 - | (fileTuple.System ? WindowsInstallerConstants.MsidbFileAttributesSystem : 0)
188 - | (fileTuple.Vital ? WindowsInstallerConstants.MsidbFileAttributesVital : 0)
189 - | (fileTuple.Checksum ? WindowsInstallerConstants.MsidbFileAttributesChecksum : 0)
190 - | ((fileTuple.Compressed.HasValue && fileTuple.Compressed.Value) ? WindowsInstallerConstants.MsidbFileAttributesCompressed : 0)
191 - | ((fileTuple.Compressed.HasValue && !fileTuple.Compressed.Value) ? WindowsInstallerConstants.MsidbFileAttributesNoncompressed : 0))
192 - .ToString());
193 - break;
149 + // "Somebody" sometimes writes out a null field even when the column definition says
150 + // it's non-nullable. Not naming names or anything. (SWID tags.)
151 + fieldValues[8] = "0";
152 }
153 + fields = String.Join(",", fieldValues);
154 + break;
155 + }
156 + case "WixMedia":
157 + break;
158 + default:
159 + fields = String.Join(",", row.Fields.Select(SafeConvertField));
160 + break;
161 + }
162
196 - case "Registry":
197 - {
198 - var registryTuple = (RegistryTuple)tuple;
199 - var value = registryTuple.Value;
200 -
201 - switch (registryTuple.ValueType)
202 - {
203 - case RegistryValueType.Binary:
204 - value = String.Concat("#x", value);
205 - break;
206 - case RegistryValueType.Expandable:
207 - value = String.Concat("#%", value);
208 - break;
209 - case RegistryValueType.Integer:
210 - value = String.Concat("#", value);
211 - break;
212 - case RegistryValueType.MultiString:
213 - switch (registryTuple.ValueAction)
214 - {
215 - case RegistryValueActionType.Append:
216 - value = String.Concat("[~]", value);
217 - break;
218 - case RegistryValueActionType.Prepend:
219 - value = String.Concat(value, "[~]");
220 - break;
221 - case RegistryValueActionType.Write:
222 - default:
223 - if (null != value && -1 == value.IndexOf("[~]", StringComparison.Ordinal))
224 - {
225 - value = String.Concat("[~]", value, "[~]");
226 - }
227 - break;
228 - }
229 - break;
230 - case RegistryValueType.String:
231 - // escape the leading '#' character for string registry keys
232 - if (null != value && value.StartsWith("#", StringComparison.Ordinal))
233 - {
234 - value = String.Concat("#", value);
235 - }
236 - break;
237 - }
163 + if (fields != null)
164 + {
165 + yield return $"{row.Table.Name}:{fields}";
166 + }
167 + }
168
239 - fields = String.Join(",",
240 - ((int)registryTuple.Root).ToString(),
241 - registryTuple.Key,
242 - registryTuple.Name,
243 - value,
244 - registryTuple.Component_
245 - );
246 - break;
247 - }
169 + private static IEnumerable<string> TupleToStrings(IntermediateTuple tuple)
170 + {
171 + string fields;
172 + switch (tuple.Definition.Name)
173 + {
174 + // Massage output to match WiX v3 rows and v4 tuples.
175 + //
176 + case "Component":
177 + {
178 + var componentTuple = (ComponentTuple)tuple;
179 + var attributes = ComponentLocation.Either == componentTuple.Location ? WindowsInstallerConstants.MsidbComponentAttributesOptional : 0;
180 + attributes |= ComponentLocation.SourceOnly == componentTuple.Location ? WindowsInstallerConstants.MsidbComponentAttributesSourceOnly : 0;
181 + attributes |= ComponentKeyPathType.Registry == componentTuple.KeyPathType ? WindowsInstallerConstants.MsidbComponentAttributesRegistryKeyPath : 0;
182 + attributes |= ComponentKeyPathType.OdbcDataSource == componentTuple.KeyPathType ? WindowsInstallerConstants.MsidbComponentAttributesODBCDataSource : 0;
183 + attributes |= componentTuple.DisableRegistryReflection ? WindowsInstallerConstants.MsidbComponentAttributesDisableRegistryReflection : 0;
184 + attributes |= componentTuple.NeverOverwrite ? WindowsInstallerConstants.MsidbComponentAttributesNeverOverwrite : 0;
185 + attributes |= componentTuple.Permanent ? WindowsInstallerConstants.MsidbComponentAttributesPermanent : 0;
186 + attributes |= componentTuple.SharedDllRefCount ? WindowsInstallerConstants.MsidbComponentAttributesSharedDllRefCount : 0;
187 + attributes |= componentTuple.Shared ? WindowsInstallerConstants.MsidbComponentAttributesShared : 0;
188 + attributes |= componentTuple.Transitive ? WindowsInstallerConstants.MsidbComponentAttributesTransitive : 0;
189 + attributes |= componentTuple.UninstallWhenSuperseded ? WindowsInstallerConstants.MsidbComponentAttributes64bit : 0;
190 + attributes |= componentTuple.Win64 ? WindowsInstallerConstants.MsidbComponentAttributes64bit : 0;
191 +
192 + fields = String.Join(",",
193 + componentTuple.ComponentId,
194 + componentTuple.DirectoryRef,
195 + attributes.ToString(),
196 + componentTuple.Condition,
197 + componentTuple.KeyPath
198 + );
199 + break;
200 + }
201 + case "CustomAction":
202 + {
203 + var customActionTuple = (CustomActionTuple)tuple;
204 + var type = customActionTuple.Win64 ? WindowsInstallerConstants.MsidbCustomActionType64BitScript : 0;
205 + type |= customActionTuple.TSAware ? WindowsInstallerConstants.MsidbCustomActionTypeTSAware : 0;
206 + type |= customActionTuple.Impersonate ? 0 : WindowsInstallerConstants.MsidbCustomActionTypeNoImpersonate;
207 + type |= customActionTuple.IgnoreResult ? WindowsInstallerConstants.MsidbCustomActionTypeContinue : 0;
208 + type |= customActionTuple.Hidden ? WindowsInstallerConstants.MsidbCustomActionTypeHideTarget : 0;
209 + type |= customActionTuple.Async ? WindowsInstallerConstants.MsidbCustomActionTypeAsync : 0;
210 + type |= CustomActionExecutionType.FirstSequence == customActionTuple.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeFirstSequence : 0;
211 + type |= CustomActionExecutionType.OncePerProcess == customActionTuple.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeOncePerProcess : 0;
212 + type |= CustomActionExecutionType.ClientRepeat == customActionTuple.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeClientRepeat : 0;
213 + type |= CustomActionExecutionType.Deferred == customActionTuple.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeInScript : 0;
214 + type |= CustomActionExecutionType.Rollback == customActionTuple.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeInScript | WindowsInstallerConstants.MsidbCustomActionTypeRollback : 0;
215 + type |= CustomActionExecutionType.Commit == customActionTuple.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeInScript | WindowsInstallerConstants.MsidbCustomActionTypeCommit : 0;
216 + type |= CustomActionSourceType.File == customActionTuple.SourceType ? WindowsInstallerConstants.MsidbCustomActionTypeSourceFile : 0;
217 + type |= CustomActionSourceType.Directory == customActionTuple.SourceType ? WindowsInstallerConstants.MsidbCustomActionTypeDirectory : 0;
218 + type |= CustomActionSourceType.Property == customActionTuple.SourceType ? WindowsInstallerConstants.MsidbCustomActionTypeProperty : 0;
219 + type |= CustomActionTargetType.Dll == customActionTuple.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeDll : 0;
220 + type |= CustomActionTargetType.Exe == customActionTuple.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeExe : 0;
221 + type |= CustomActionTargetType.TextData == customActionTuple.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeTextData : 0;
222 + type |= CustomActionTargetType.JScript == customActionTuple.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeJScript : 0;
223 + type |= CustomActionTargetType.VBScript == customActionTuple.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeVBScript : 0;
224 +
225 + fields = String.Join(",",
226 + type.ToString(),
227 + customActionTuple.Source,
228 + customActionTuple.Target,
229 + customActionTuple.PatchUninstall ? WindowsInstallerConstants.MsidbCustomActionTypePatchUninstall.ToString() : null
230 + );
231 + break;
232 + }
233 + case "Directory":
234 + {
235 + var directoryTuple = (DirectoryTuple)tuple;
236
249 - case "RemoveRegistry":
237 + if (!String.IsNullOrEmpty(directoryTuple.ComponentGuidGenerationSeed))
238 {
251 - var removeRegistryTuple = (RemoveRegistryTuple)tuple;
252 - fields = String.Join(",",
253 - ((int)removeRegistryTuple.Root).ToString(),
254 - removeRegistryTuple.Key,
255 - removeRegistryTuple.Name,
256 - removeRegistryTuple.Component_
257 - );
258 - break;
239 + yield return $"WixDirectory:{directoryTuple.Id.Id},{directoryTuple.ComponentGuidGenerationSeed}";
240 }
241
261 - case "ServiceControl":
262 - {
263 - var serviceControlTuple = (ServiceControlTuple)tuple;
264 -
265 - var events = serviceControlTuple.InstallRemove ? WindowsInstallerConstants.MsidbServiceControlEventDelete : 0;
266 - events |= serviceControlTuple.UninstallRemove ? WindowsInstallerConstants.MsidbServiceControlEventUninstallDelete : 0;
267 - events |= serviceControlTuple.InstallStart ? WindowsInstallerConstants.MsidbServiceControlEventStart : 0;
268 - events |= serviceControlTuple.UninstallStart ? WindowsInstallerConstants.MsidbServiceControlEventUninstallStart : 0;
269 - events |= serviceControlTuple.InstallStop ? WindowsInstallerConstants.MsidbServiceControlEventStop : 0;
270 - events |= serviceControlTuple.UninstallStop ? WindowsInstallerConstants.MsidbServiceControlEventUninstallStop : 0;
271 -
272 - fields = String.Join(",",
273 - serviceControlTuple.Name,
274 - events.ToString(),
275 - serviceControlTuple.Arguments,
276 - serviceControlTuple.Wait == true ? "1" : "0",
277 - serviceControlTuple.Component_
278 - );
279 - break;
280 - }
242 + fields = String.Join(",", directoryTuple.ParentDirectoryRef, directoryTuple.Name, directoryTuple.ShortName, directoryTuple.SourceName, directoryTuple.SourceShortName);
243 + break;
244 + }
245 + case "Feature":
246 + {
247 + var featureTuple = (FeatureTuple)tuple;
248 + var attributes = featureTuple.DisallowAbsent ? WindowsInstallerConstants.MsidbFeatureAttributesUIDisallowAbsent : 0;
249 + attributes |= featureTuple.DisallowAdvertise ? WindowsInstallerConstants.MsidbFeatureAttributesDisallowAdvertise : 0;
250 + attributes |= FeatureInstallDefault.FollowParent == featureTuple.InstallDefault ? WindowsInstallerConstants.MsidbFeatureAttributesFollowParent : 0;
251 + attributes |= FeatureInstallDefault.Source == featureTuple.InstallDefault ? WindowsInstallerConstants.MsidbFeatureAttributesFavorSource : 0;
252 + attributes |= FeatureTypicalDefault.Advertise == featureTuple.TypicalDefault ? WindowsInstallerConstants.MsidbFeatureAttributesFavorAdvertise : 0;
253 +
254 + fields = String.Join(",",
255 + featureTuple.ParentFeatureRef,
256 + featureTuple.Title,
257 + featureTuple.Description,
258 + featureTuple.Display.ToString(),
259 + featureTuple.Level.ToString(),
260 + featureTuple.DirectoryRef,
261 + attributes.ToString());
262 + break;
263 + }
264 + case "File":
265 + {
266 + var fileTuple = (FileTuple)tuple;
267
282 - case "ServiceInstall":
268 + if (fileTuple.BindPath != null)
269 {
284 - var serviceInstallTuple = (ServiceInstallTuple)tuple;
285 -
286 - var errorControl = (int)serviceInstallTuple.ErrorControl;
287 - errorControl |= serviceInstallTuple.Vital ? WindowsInstallerConstants.MsidbServiceInstallErrorControlVital : 0;
288 -
289 - var serviceType = (int)serviceInstallTuple.ServiceType;
290 - serviceType |= serviceInstallTuple.Interactive ? WindowsInstallerConstants.MsidbServiceInstallInteractive : 0;
291 -
292 - fields = String.Join(",",
293 - serviceInstallTuple.Name,
294 - serviceInstallTuple.DisplayName,
295 - serviceType.ToString(),
296 - ((int)serviceInstallTuple.StartType).ToString(),
297 - errorControl.ToString(),
298 - serviceInstallTuple.LoadOrderGroup,
299 - serviceInstallTuple.Dependencies,
300 - serviceInstallTuple.StartName,
301 - serviceInstallTuple.Password,
302 - serviceInstallTuple.Arguments,
303 - serviceInstallTuple.Component_,
304 - serviceInstallTuple.Description
305 - );
306 - break;
270 + yield return $"BindImage:{fileTuple.Id.Id},{fileTuple.BindPath}";
271 }
272
309 - case "Upgrade":
273 + if (fileTuple.FontTitle != null)
274 {
311 - var upgradeTuple = (UpgradeTuple)tuple;
312 -
313 - var attributes = upgradeTuple.MigrateFeatures ? WindowsInstallerConstants.MsidbUpgradeAttributesMigrateFeatures : 0;
314 - attributes |= upgradeTuple.OnlyDetect ? WindowsInstallerConstants.MsidbUpgradeAttributesOnlyDetect : 0;
315 - attributes |= upgradeTuple.IgnoreRemoveFailures ? WindowsInstallerConstants.MsidbUpgradeAttributesIgnoreRemoveFailure : 0;
316 - attributes |= upgradeTuple.VersionMinInclusive ? WindowsInstallerConstants.MsidbUpgradeAttributesVersionMinInclusive : 0;
317 - attributes |= upgradeTuple.VersionMaxInclusive ? WindowsInstallerConstants.MsidbUpgradeAttributesVersionMaxInclusive : 0;
318 - attributes |= upgradeTuple.ExcludeLanguages ? WindowsInstallerConstants.MsidbUpgradeAttributesLanguagesExclusive : 0;
319 -
320 - fields = String.Join(",",
321 - upgradeTuple.VersionMin,
322 - upgradeTuple.VersionMax,
323 - upgradeTuple.Language,
324 - attributes.ToString(),
325 - upgradeTuple.Remove,
326 - upgradeTuple.ActionProperty
327 - );
328 - break;
275 + yield return $"Font:{fileTuple.Id.Id},{fileTuple.FontTitle}";
276 }
277
331 - case "WixAction":
278 + if (fileTuple.SelfRegCost.HasValue)
279 {
333 - var wixActionTuple = (WixActionTuple)tuple;
334 - fields = String.Join(",",
335 - wixActionTuple.SequenceTable,
336 - wixActionTuple.Action,
337 - wixActionTuple.Condition,
338 - // BUGBUGBUG: AB#2626
339 - wixActionTuple.Sequence == 0 ? String.Empty : wixActionTuple.Sequence.ToString(),
340 - wixActionTuple.Before,
341 - wixActionTuple.After,
342 - wixActionTuple.Overridable == true ? "1" : "0"
343 - );
344 - break;
280 + yield return $"SelfReg:{fileTuple.Id.Id},{fileTuple.SelfRegCost}";
281 }
282
347 - case "WixComplexReference":
348 - {
349 - var wixComplexReferenceTuple = (WixComplexReferenceTuple)tuple;
350 - fields = String.Join(",",
351 - wixComplexReferenceTuple.Parent,
352 - ((int)wixComplexReferenceTuple.ParentType).ToString(),
353 - wixComplexReferenceTuple.ParentLanguage,
354 - wixComplexReferenceTuple.Child,
355 - ((int)wixComplexReferenceTuple.ChildType).ToString(),
356 - wixComplexReferenceTuple.IsPrimary ? "1" : "0"
357 - );
358 - break;
359 - }
283 + fields = String.Join(",",
284 + fileTuple.ComponentRef,
285 + fileTuple.Name,
286 + fileTuple.FileSize.ToString(),
287 + fileTuple.Version,
288 + fileTuple.Language,
289 + ((fileTuple.ReadOnly ? WindowsInstallerConstants.MsidbFileAttributesReadOnly : 0)
290 + | (fileTuple.Hidden ? WindowsInstallerConstants.MsidbFileAttributesHidden : 0)
291 + | (fileTuple.System ? WindowsInstallerConstants.MsidbFileAttributesSystem : 0)
292 + | (fileTuple.Vital ? WindowsInstallerConstants.MsidbFileAttributesVital : 0)
293 + | (fileTuple.Checksum ? WindowsInstallerConstants.MsidbFileAttributesChecksum : 0)
294 + | ((fileTuple.Compressed.HasValue && fileTuple.Compressed.Value) ? WindowsInstallerConstants.MsidbFileAttributesCompressed : 0)
295 + | ((fileTuple.Compressed.HasValue && !fileTuple.Compressed.Value) ? WindowsInstallerConstants.MsidbFileAttributesNoncompressed : 0))
296 + .ToString());
297 + break;
298 + }
299
361 - case "WixFile":
362 - {
363 - var wixFileTuple = (WixFileTuple)tuple;
364 - fields = String.Concat(
365 - wixFileTuple.AssemblyType == FileAssemblyType.DotNetAssembly ? "0" : wixFileTuple.AssemblyType == FileAssemblyType.Win32Assembly ? "1" : String.Empty, ",",
366 - String.Join(",", tuple.Fields.Skip(2).Take(6).Select(field => (string)field).ToArray()));
367 - break;
368 - }
300 + case "Media":
301 + fields = String.Join(",", tuple.Fields.Skip(1).Select(SafeConvertField));
302 + break;
303 +
304 + case "Registry":
305 + {
306 + var registryTuple = (RegistryTuple)tuple;
307 + var value = registryTuple.Value;
308
370 - case "WixProperty":
309 + switch (registryTuple.ValueType)
310 {
372 - var wixPropertyTuple = (WixPropertyTuple)tuple;
373 - var attributes = 0;
374 - attributes |= wixPropertyTuple.Admin ? 0x1 : 0;
375 - attributes |= wixPropertyTuple.Hidden ? 0x2 : 0;
376 - attributes |= wixPropertyTuple.Secure ? 0x4 : 0;
377 -
378 - fields = String.Join(",",
379 - wixPropertyTuple.Property_,
380 - attributes.ToString()
381 - );
311 + case RegistryValueType.Binary:
312 + value = String.Concat("#x", value);
313 + break;
314 + case RegistryValueType.Expandable:
315 + value = String.Concat("#%", value);
316 + break;
317 + case RegistryValueType.Integer:
318 + value = String.Concat("#", value);
319 + break;
320 + case RegistryValueType.MultiString:
321 + switch (registryTuple.ValueAction)
322 + {
323 + case RegistryValueActionType.Append:
324 + value = String.Concat("[~]", value);
325 + break;
326 + case RegistryValueActionType.Prepend:
327 + value = String.Concat(value, "[~]");
328 + break;
329 + case RegistryValueActionType.Write:
330 + default:
331 + if (null != value && -1 == value.IndexOf("[~]", StringComparison.Ordinal))
332 + {
333 + value = String.Concat("[~]", value, "[~]");
334 + }
335 + break;
336 + }
337 + break;
338 + case RegistryValueType.String:
339 + // escape the leading '#' character for string registry keys
340 + if (null != value && value.StartsWith("#", StringComparison.Ordinal))
341 + {
342 + value = String.Concat("#", value);
343 + }
344 break;
345 }
346
347 + fields = String.Join(",",
348 + ((int)registryTuple.Root).ToString(),
349 + registryTuple.Key,
350 + registryTuple.Name,
351 + value,
352 + registryTuple.ComponentRef
353 + );
354 + break;
355 + }
356 +
357 + case "RemoveRegistry":
358 + {
359 + var removeRegistryTuple = (RemoveRegistryTuple)tuple;
360 + fields = String.Join(",",
361 + ((int)removeRegistryTuple.Root).ToString(),
362 + removeRegistryTuple.Key,
363 + removeRegistryTuple.Name,
364 + removeRegistryTuple.ComponentRef
365 + );
366 + break;
367 + }
368 +
369 + case "ServiceControl":
370 + {
371 + var serviceControlTuple = (ServiceControlTuple)tuple;
372 +
373 + var events = serviceControlTuple.InstallRemove ? WindowsInstallerConstants.MsidbServiceControlEventDelete : 0;
374 + events |= serviceControlTuple.UninstallRemove ? WindowsInstallerConstants.MsidbServiceControlEventUninstallDelete : 0;
375 + events |= serviceControlTuple.InstallStart ? WindowsInstallerConstants.MsidbServiceControlEventStart : 0;
376 + events |= serviceControlTuple.UninstallStart ? WindowsInstallerConstants.MsidbServiceControlEventUninstallStart : 0;
377 + events |= serviceControlTuple.InstallStop ? WindowsInstallerConstants.MsidbServiceControlEventStop : 0;
378 + events |= serviceControlTuple.UninstallStop ? WindowsInstallerConstants.MsidbServiceControlEventUninstallStop : 0;
379 +
380 + fields = String.Join(",",
381 + serviceControlTuple.Name,
382 + events.ToString(),
383 + serviceControlTuple.Arguments,
384 + serviceControlTuple.Wait == true ? "1" : "0",
385 + serviceControlTuple.ComponentRef
386 + );
387 + break;
388 + }
389 +
390 + case "ServiceInstall":
391 + {
392 + var serviceInstallTuple = (ServiceInstallTuple)tuple;
393 +
394 + var errorControl = (int)serviceInstallTuple.ErrorControl;
395 + errorControl |= serviceInstallTuple.Vital ? WindowsInstallerConstants.MsidbServiceInstallErrorControlVital : 0;
396 +
397 + var serviceType = (int)serviceInstallTuple.ServiceType;
398 + serviceType |= serviceInstallTuple.Interactive ? WindowsInstallerConstants.MsidbServiceInstallInteractive : 0;
399 +
400 + fields = String.Join(",",
401 + serviceInstallTuple.Name,
402 + serviceInstallTuple.DisplayName,
403 + serviceType.ToString(),
404 + ((int)serviceInstallTuple.StartType).ToString(),
405 + errorControl.ToString(),
406 + serviceInstallTuple.LoadOrderGroup,
407 + serviceInstallTuple.Dependencies,
408 + serviceInstallTuple.StartName,
409 + serviceInstallTuple.Password,
410 + serviceInstallTuple.Arguments,
411 + serviceInstallTuple.ComponentRef,
412 + serviceInstallTuple.Description
413 + );
414 + break;
415 + }
416 +
417 + case "Upgrade":
418 + {
419 + var upgradeTuple = (UpgradeTuple)tuple;
420 +
421 + var attributes = upgradeTuple.MigrateFeatures ? WindowsInstallerConstants.MsidbUpgradeAttributesMigrateFeatures : 0;
422 + attributes |= upgradeTuple.OnlyDetect ? WindowsInstallerConstants.MsidbUpgradeAttributesOnlyDetect : 0;
423 + attributes |= upgradeTuple.IgnoreRemoveFailures ? WindowsInstallerConstants.MsidbUpgradeAttributesIgnoreRemoveFailure : 0;
424 + attributes |= upgradeTuple.VersionMinInclusive ? WindowsInstallerConstants.MsidbUpgradeAttributesVersionMinInclusive : 0;
425 + attributes |= upgradeTuple.VersionMaxInclusive ? WindowsInstallerConstants.MsidbUpgradeAttributesVersionMaxInclusive : 0;
426 + attributes |= upgradeTuple.ExcludeLanguages ? WindowsInstallerConstants.MsidbUpgradeAttributesLanguagesExclusive : 0;
427 +
428 + fields = String.Join(",",
429 + upgradeTuple.VersionMin,
430 + upgradeTuple.VersionMax,
431 + upgradeTuple.Language,
432 + attributes.ToString(),
433 + upgradeTuple.Remove,
434 + upgradeTuple.ActionProperty
435 + );
436 + break;
437 + }
438 +
439 + case "WixAction":
440 + {
441 + var wixActionTuple = (WixActionTuple)tuple;
442 + var data = wixActionTuple.Fields[(int)WixActionTupleFields.SequenceTable].AsObject();
443 + var sequenceTableAsInt = data is string ? (int)SequenceStringToSequenceTable(data) : (int)wixActionTuple.SequenceTable;
444 +
445 + fields = String.Join(",",
446 + sequenceTableAsInt,
447 + wixActionTuple.Action,
448 + wixActionTuple.Condition,
449 + wixActionTuple.Sequence?.ToString() ?? String.Empty,
450 + wixActionTuple.Before,
451 + wixActionTuple.After,
452 + wixActionTuple.Overridable == true ? "1" : "0"
453 + );
454 + break;
455 + }
456 +
457 + case "WixComplexReference":
458 + {
459 + var wixComplexReferenceTuple = (WixComplexReferenceTuple)tuple;
460 + fields = String.Join(",",
461 + wixComplexReferenceTuple.Parent,
462 + (int)wixComplexReferenceTuple.ParentType,
463 + wixComplexReferenceTuple.ParentLanguage,
464 + wixComplexReferenceTuple.Child,
465 + (int)wixComplexReferenceTuple.ChildType,
466 + wixComplexReferenceTuple.IsPrimary ? "1" : "0"
467 + );
468 + break;
469 + }
470 +
471 + case "WixFile":
472 + {
473 + var wixFileTuple = (WixFileTuple)tuple;
474 + fields = String.Concat(
475 + wixFileTuple.AssemblyType == FileAssemblyType.DotNetAssembly ? "0" : wixFileTuple.AssemblyType == FileAssemblyType.Win32Assembly ? "1" : String.Empty, ",",
476 + String.Join(",", tuple.Fields.Skip(1).Take(8).Select(field => (string)field)));
477 + break;
478 + }
479 +
480 + case "WixProperty":
481 + {
482 + var wixPropertyTuple = (WixPropertyTuple)tuple;
483 + var attributes = wixPropertyTuple.Admin ? 0x1 : 0;
484 + attributes |= wixPropertyTuple.Hidden ? 0x2 : 0;
485 + attributes |= wixPropertyTuple.Secure ? 0x4 : 0;
486 +
487 + fields = String.Join(",",
488 + wixPropertyTuple.PropertyRef,
489 + attributes.ToString()
490 + );
491 + break;
492 + }
493 +
494 + default:
495 + fields = String.Join(",", tuple.Fields.Select(SafeConvertField));
496 + break;
497 + }
498 +
499 + var name = tuple.Definition.Type == TupleDefinitionType.SummaryInformation ? "_SummaryInformation" : tuple.Definition.Name;
500 + var id = tuple.Id?.Id ?? String.Empty;
501 + fields = String.IsNullOrEmpty(id) ? fields : String.IsNullOrEmpty(fields) ? id : $"{id},{fields}";
502 + yield return $"{name}:{fields}";
503 + }
504 +
505 + private static SequenceTable SequenceStringToSequenceTable(object sequenceString)
506 + {
507 + switch (sequenceString)
508 + {
509 + case "AdminExecuteSequence":
510 + return SequenceTable.AdminExecuteSequence;
511 + case "AdminUISequence":
512 + return SequenceTable.AdminUISequence;
513 + case "AdvtExecuteSequence":
514 + return SequenceTable.AdvertiseExecuteSequence;
515 + case "InstallExecuteSequence":
516 + return SequenceTable.InstallExecuteSequence;
517 + case "InstallUISequence":
518 + return SequenceTable.InstallUISequence;
519 + default:
520 + throw new ArgumentException($"Unknown sequence: {sequenceString}");
521 }
522 + }
523
387 - var id = tuple.Id == null ? String.Empty : String.Concat(",", tuple.Id.Id);
388 - return $"{tuple.Definition.Name}{id},{fields}";
524 + private static string SafeConvertField(Wix3.Field field)
525 + {
526 + return field?.Data?.ToString();
527 + }
528 +
529 + private static string SafeConvertField(IntermediateField field)
530 + {
531 + var data = field.AsObject();
532 + if (data is IntermediateFieldPathValue path)
533 + {
534 + return path.Path;
535 + }
536 +
537 + return data?.ToString();
538 + }
539 +
540 + private static string[] SplitDefaultDir(string defaultDir)
541 + {
542 + var split1 = defaultDir.Split(':');
543 + var targetSplit = split1.Length > 1 ? split1[1].Split('|') : split1[0].Split('|');
544 + var sourceSplit = split1.Length > 1 ? split1[0].Split('|') : new[] { String.Empty };
545 + return new[]
546 + {
547 + targetSplit.Length > 1 ? targetSplit[1] : targetSplit[0],
548 + targetSplit.Length > 1 ? targetSplit[0] : String.Empty,
549 + sourceSplit.Length > 1 ? sourceSplit[1] : sourceSplit[0],
550 + sourceSplit.Length > 1 ? sourceSplit[0] : String.Empty
551 + };
552 }
553 }
554 }