aboutsummaryrefslogtreecommitdiff
path: root/src/WixToolset.Converters.Tupleizer/ConvertTuples.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/WixToolset.Converters.Tupleizer/ConvertTuples.cs')
-rw-r--r--src/WixToolset.Converters.Tupleizer/ConvertTuples.cs816
1 files changed, 816 insertions, 0 deletions
diff --git a/src/WixToolset.Converters.Tupleizer/ConvertTuples.cs b/src/WixToolset.Converters.Tupleizer/ConvertTuples.cs
new file mode 100644
index 00000000..88fe0575
--- /dev/null
+++ b/src/WixToolset.Converters.Tupleizer/ConvertTuples.cs
@@ -0,0 +1,816 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixToolset.Converters.Tupleizer
4{
5 using System;
6 using System.Collections.Generic;
7 using System.Linq;
8 using WixToolset.Data;
9 using WixToolset.Data.Tuples;
10 using WixToolset.Data.WindowsInstaller;
11 using Wix3 = Microsoft.Tools.WindowsInstallerXml;
12
13 public static class ConvertTuples
14 {
15 public static Intermediate ConvertFile(string path)
16 {
17 var output = Wix3.Output.Load(path, suppressVersionCheck: true, suppressSchema: true);
18 return ConvertOutput(output);
19 }
20
21 public static Intermediate ConvertOutput(Wix3.Output output)
22 {
23 var section = new IntermediateSection(String.Empty, OutputType3ToSectionType4(output.Type), output.Codepage);
24
25 var wixMediaByDiskId = IndexWixMediaTableByDiskId(output);
26 var componentsById = IndexById<Wix3.Row>(output, "Component");
27 var bindPathsById = IndexById<Wix3.Row>(output, "BindPath");
28 var fontsById = IndexById<Wix3.Row>(output, "Font");
29 var selfRegById = IndexById<Wix3.Row>(output, "SelfReg");
30 var wixDirectoryById = IndexById<Wix3.Row>(output, "WixDirectory");
31 var wixFileById = IndexById<Wix3.Row>(output, "WixFile");
32
33 foreach (Wix3.Table table in output.Tables)
34 {
35 foreach (Wix3.Row row in table.Rows)
36 {
37 var tuple = GenerateTupleFromRow(row, wixMediaByDiskId, componentsById, fontsById, bindPathsById, selfRegById, wixFileById, wixDirectoryById);
38 if (tuple != null)
39 {
40 section.Tuples.Add(tuple);
41 }
42 }
43 }
44
45 return new Intermediate(String.Empty, new[] { section }, localizationsByCulture: null, embedFilePaths: null);
46 }
47
48 private static Dictionary<int, Wix3.WixMediaRow> IndexWixMediaTableByDiskId(Wix3.Output output)
49 {
50 var wixMediaByDiskId = new Dictionary<int, Wix3.WixMediaRow>();
51 var wixMediaTable = output.Tables["WixMedia"];
52
53 if (wixMediaTable != null)
54 {
55 foreach (Wix3.WixMediaRow row in wixMediaTable.Rows)
56 {
57 wixMediaByDiskId.Add(FieldAsInt(row, 0), row);
58 }
59 }
60
61 return wixMediaByDiskId;
62 }
63
64 private static Dictionary<string, T> IndexById<T>(Wix3.Output output, string tableName) where T : Wix3.Row
65 {
66 var byId = new Dictionary<string, T>();
67 var table = output.Tables[tableName];
68
69 if (table != null)
70 {
71 foreach (T row in table.Rows)
72 {
73 byId.Add(FieldAsString(row, 0), row);
74 }
75 }
76
77 return byId;
78 }
79
80 private static IntermediateTuple GenerateTupleFromRow(Wix3.Row row, Dictionary<int, Wix3.WixMediaRow> wixMediaByDiskId, Dictionary<string, Wix3.Row> componentsById, Dictionary<string, Wix3.Row> fontsById, Dictionary<string, Wix3.Row> bindPathsById, Dictionary<string, Wix3.Row> selfRegById, Dictionary<string, Wix3.Row> wixFileById, Dictionary<string, Wix3.Row> wixDirectoryById)
81 {
82 var name = row.Table.Name;
83 switch (name)
84 {
85 case "_SummaryInformation":
86 return DefaultTupleFromRow(typeof(SummaryInformationTuple), row, columnZeroIsId: false);
87 case "ActionText":
88 return DefaultTupleFromRow(typeof(ActionTextTuple), row, columnZeroIsId: false);
89 case "AdvtExecuteSequence":
90 return DefaultTupleFromRow(typeof(AdvtExecuteSequenceTuple), row, columnZeroIsId: false);
91 case "AppId":
92 return DefaultTupleFromRow(typeof(AppIdTuple), row, columnZeroIsId: false);
93 case "AppSearch":
94 return DefaultTupleFromRow(typeof(AppSearchTuple), row, columnZeroIsId: false);
95 case "Billboard":
96 return DefaultTupleFromRow(typeof(BillboardTuple), row, columnZeroIsId: true);
97 case "Binary":
98 return DefaultTupleFromRow(typeof(BinaryTuple), row, columnZeroIsId: true);
99 case "BindPath":
100 return null;
101 case "CCPSearch":
102 return DefaultTupleFromRow(typeof(CCPSearchTuple), row, columnZeroIsId: true);
103 case "Class":
104 return DefaultTupleFromRow(typeof(ClassTuple), row, columnZeroIsId: false);
105 case "CompLocator":
106 return DefaultTupleFromRow(typeof(CompLocatorTuple), row, columnZeroIsId: true);
107 case "Component":
108 {
109 var attributes = FieldAsNullableInt(row, 3);
110
111 var location = ComponentLocation.LocalOnly;
112 if ((attributes & WindowsInstallerConstants.MsidbComponentAttributesSourceOnly) == WindowsInstallerConstants.MsidbComponentAttributesSourceOnly)
113 {
114 location = ComponentLocation.SourceOnly;
115 }
116 else if ((attributes & WindowsInstallerConstants.MsidbComponentAttributesOptional) == WindowsInstallerConstants.MsidbComponentAttributesOptional)
117 {
118 location = ComponentLocation.Either;
119 }
120
121 var keyPath = FieldAsString(row, 5);
122 var keyPathType = String.IsNullOrEmpty(keyPath) ? ComponentKeyPathType.Directory : ComponentKeyPathType.File;
123 if ((attributes & WindowsInstallerConstants.MsidbComponentAttributesRegistryKeyPath) == WindowsInstallerConstants.MsidbComponentAttributesRegistryKeyPath)
124 {
125 keyPathType = ComponentKeyPathType.Registry;
126 }
127 else if ((attributes & WindowsInstallerConstants.MsidbComponentAttributesODBCDataSource) == WindowsInstallerConstants.MsidbComponentAttributesODBCDataSource)
128 {
129 keyPathType = ComponentKeyPathType.OdbcDataSource;
130 }
131
132 return new ComponentTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0)))
133 {
134 ComponentId = FieldAsString(row, 1),
135 DirectoryRef = FieldAsString(row, 2),
136 Condition = FieldAsString(row, 4),
137 KeyPath = keyPath,
138 Location = location,
139 DisableRegistryReflection = (attributes & WindowsInstallerConstants.MsidbComponentAttributesDisableRegistryReflection) == WindowsInstallerConstants.MsidbComponentAttributesDisableRegistryReflection,
140 NeverOverwrite = (attributes & WindowsInstallerConstants.MsidbComponentAttributesNeverOverwrite) == WindowsInstallerConstants.MsidbComponentAttributesNeverOverwrite,
141 Permanent = (attributes & WindowsInstallerConstants.MsidbComponentAttributesPermanent) == WindowsInstallerConstants.MsidbComponentAttributesPermanent,
142 SharedDllRefCount = (attributes & WindowsInstallerConstants.MsidbComponentAttributesSharedDllRefCount) == WindowsInstallerConstants.MsidbComponentAttributesSharedDllRefCount,
143 Shared = (attributes & WindowsInstallerConstants.MsidbComponentAttributesShared) == WindowsInstallerConstants.MsidbComponentAttributesShared,
144 Transitive = (attributes & WindowsInstallerConstants.MsidbComponentAttributesTransitive) == WindowsInstallerConstants.MsidbComponentAttributesTransitive,
145 UninstallWhenSuperseded = (attributes & WindowsInstallerConstants.MsidbComponentAttributesUninstallOnSupersedence) == WindowsInstallerConstants.MsidbComponentAttributesUninstallOnSupersedence,
146 Win64 = (attributes & WindowsInstallerConstants.MsidbComponentAttributes64bit) == WindowsInstallerConstants.MsidbComponentAttributes64bit,
147 KeyPathType = keyPathType,
148 };
149 }
150
151 case "Condition":
152 return DefaultTupleFromRow(typeof(ConditionTuple), row, columnZeroIsId: false);
153 case "CreateFolder":
154 return DefaultTupleFromRow(typeof(CreateFolderTuple), row, columnZeroIsId: false);
155 case "CustomAction":
156 {
157 var caType = FieldAsInt(row, 1);
158 var executionType = DetermineCustomActionExecutionType(caType);
159 var sourceType = DetermineCustomActionSourceType(caType);
160 var targetType = DetermineCustomActionTargetType(caType);
161
162 return new CustomActionTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0)))
163 {
164 ExecutionType = executionType,
165 SourceType = sourceType,
166 Source = FieldAsString(row, 2),
167 TargetType = targetType,
168 Target = FieldAsString(row, 3),
169 Win64 = (caType & WindowsInstallerConstants.MsidbCustomActionType64BitScript) == WindowsInstallerConstants.MsidbCustomActionType64BitScript,
170 TSAware = (caType & WindowsInstallerConstants.MsidbCustomActionTypeTSAware) == WindowsInstallerConstants.MsidbCustomActionTypeTSAware,
171 Impersonate = (caType & WindowsInstallerConstants.MsidbCustomActionTypeNoImpersonate) != WindowsInstallerConstants.MsidbCustomActionTypeNoImpersonate,
172 IgnoreResult = (caType & WindowsInstallerConstants.MsidbCustomActionTypeContinue) == WindowsInstallerConstants.MsidbCustomActionTypeContinue,
173 Hidden = (caType & WindowsInstallerConstants.MsidbCustomActionTypeHideTarget) == WindowsInstallerConstants.MsidbCustomActionTypeHideTarget,
174 Async = (caType & WindowsInstallerConstants.MsidbCustomActionTypeAsync) == WindowsInstallerConstants.MsidbCustomActionTypeAsync,
175 };
176 }
177
178 case "Directory":
179 {
180 var id = FieldAsString(row, 0);
181 var splits = SplitDefaultDir(FieldAsString(row, 2));
182
183 var tuple = new DirectoryTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, id))
184 {
185 ParentDirectoryRef = FieldAsString(row, 1),
186 Name = splits[0],
187 ShortName = splits[1],
188 SourceName = splits[2],
189 SourceShortName = splits[3]
190 };
191
192 if (wixDirectoryById.TryGetValue(id, out var wixDirectoryRow))
193 {
194 tuple.ComponentGuidGenerationSeed = FieldAsString(wixDirectoryRow, 1);
195 }
196
197 return tuple;
198 }
199 case "DrLocator":
200 return DefaultTupleFromRow(typeof(DrLocatorTuple), row, columnZeroIsId: false);
201 case "DuplicateFile":
202 return DefaultTupleFromRow(typeof(DuplicateFileTuple), row, columnZeroIsId: true);
203 case "Error":
204 return DefaultTupleFromRow(typeof(ErrorTuple), row, columnZeroIsId: false);
205 case "Extension":
206 return DefaultTupleFromRow(typeof(ExtensionTuple), row, columnZeroIsId: false);
207 case "Feature":
208 {
209 var attributes = FieldAsInt(row, 7);
210 var installDefault = FeatureInstallDefault.Local;
211 if ((attributes & WindowsInstallerConstants.MsidbFeatureAttributesFollowParent) == WindowsInstallerConstants.MsidbFeatureAttributesFollowParent)
212 {
213 installDefault = FeatureInstallDefault.FollowParent;
214 }
215 else if ((attributes & WindowsInstallerConstants.MsidbFeatureAttributesFavorSource) == WindowsInstallerConstants.MsidbFeatureAttributesFavorSource)
216 {
217 installDefault = FeatureInstallDefault.Source;
218 }
219
220 return new FeatureTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0)))
221 {
222 ParentFeatureRef = FieldAsString(row, 1),
223 Title = FieldAsString(row, 2),
224 Description = FieldAsString(row, 3),
225 Display = FieldAsInt(row, 4), // BUGBUGBUG: FieldAsNullableInt(row, 4),
226 Level = FieldAsInt(row, 5),
227 DirectoryRef = FieldAsString(row, 6),
228 DisallowAbsent = (attributes & WindowsInstallerConstants.MsidbFeatureAttributesUIDisallowAbsent) == WindowsInstallerConstants.MsidbFeatureAttributesUIDisallowAbsent,
229 DisallowAdvertise = (attributes & WindowsInstallerConstants.MsidbFeatureAttributesDisallowAdvertise) == WindowsInstallerConstants.MsidbFeatureAttributesDisallowAdvertise,
230 InstallDefault = installDefault,
231 TypicalDefault = (attributes & WindowsInstallerConstants.MsidbFeatureAttributesFavorAdvertise) == WindowsInstallerConstants.MsidbFeatureAttributesFavorAdvertise ? FeatureTypicalDefault.Advertise : FeatureTypicalDefault.Install,
232 };
233 }
234
235 case "FeatureComponents":
236 return DefaultTupleFromRow(typeof(FeatureComponentsTuple), row, columnZeroIsId: false);
237 case "File":
238 {
239 var attributes = FieldAsNullableInt(row, 6);
240
241 FileTupleAttributes tupleAttributes = 0;
242 tupleAttributes |= (attributes & WindowsInstallerConstants.MsidbFileAttributesReadOnly) == WindowsInstallerConstants.MsidbFileAttributesReadOnly ? FileTupleAttributes.ReadOnly : 0;
243 tupleAttributes |= (attributes & WindowsInstallerConstants.MsidbFileAttributesHidden) == WindowsInstallerConstants.MsidbFileAttributesHidden ? FileTupleAttributes.Hidden : 0;
244 tupleAttributes |= (attributes & WindowsInstallerConstants.MsidbFileAttributesSystem) == WindowsInstallerConstants.MsidbFileAttributesSystem ? FileTupleAttributes.System : 0;
245 tupleAttributes |= (attributes & WindowsInstallerConstants.MsidbFileAttributesVital) == WindowsInstallerConstants.MsidbFileAttributesVital ? FileTupleAttributes.Vital : 0;
246 tupleAttributes |= (attributes & WindowsInstallerConstants.MsidbFileAttributesChecksum) == WindowsInstallerConstants.MsidbFileAttributesChecksum ? FileTupleAttributes.Checksum : 0;
247 tupleAttributes |= (attributes & WindowsInstallerConstants.MsidbFileAttributesNoncompressed) == WindowsInstallerConstants.MsidbFileAttributesNoncompressed ? FileTupleAttributes.Uncompressed : 0;
248 tupleAttributes |= (attributes & WindowsInstallerConstants.MsidbFileAttributesCompressed) == WindowsInstallerConstants.MsidbFileAttributesCompressed ? FileTupleAttributes.Compressed : 0;
249
250 var id = FieldAsString(row, 0);
251
252 var tuple = new FileTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, id))
253 {
254 ComponentRef = FieldAsString(row, 1),
255 Name = FieldAsString(row, 2),
256 FileSize = FieldAsInt(row, 3),
257 Version = FieldAsString(row, 4),
258 Language = FieldAsString(row, 5),
259 Attributes = tupleAttributes
260 };
261
262 if (bindPathsById.TryGetValue(id, out var bindPathRow))
263 {
264 tuple.BindPath = FieldAsString(bindPathRow, 1) ?? String.Empty;
265 }
266
267 if (fontsById.TryGetValue(id, out var fontRow))
268 {
269 tuple.FontTitle = FieldAsString(fontRow, 1) ?? String.Empty;
270 }
271
272 if (selfRegById.TryGetValue(id, out var selfRegRow))
273 {
274 tuple.SelfRegCost = FieldAsNullableInt(selfRegRow, 1) ?? 0;
275 }
276
277 if (wixFileById.TryGetValue(id, out var wixFileRow))
278 {
279 tuple.DirectoryRef = FieldAsString(wixFileRow, 4);
280 tuple.DiskId = FieldAsNullableInt(wixFileRow, 5) ?? 0;
281 tuple.Source = new IntermediateFieldPathValue() { Path = FieldAsString(wixFileRow, 6) };
282 tuple.PatchGroup = FieldAsInt(wixFileRow, 8);
283 tuple.Attributes |= FieldAsInt(wixFileRow, 9) != 0 ? FileTupleAttributes.GeneratedShortFileName : 0;
284 tuple.PatchAttributes = (PatchAttributeType)FieldAsInt(wixFileRow, 10);
285 }
286
287 return tuple;
288 }
289 case "Font":
290 return null;
291 case "Icon":
292 return DefaultTupleFromRow(typeof(IconTuple), row, columnZeroIsId: true);
293 case "InstallExecuteSequence":
294 return DefaultTupleFromRow(typeof(InstallExecuteSequenceTuple), row, columnZeroIsId: false);
295 case "LockPermissions":
296 return DefaultTupleFromRow(typeof(LockPermissionsTuple), row, columnZeroIsId: false);
297 case "Media":
298 {
299 var diskId = FieldAsInt(row, 0);
300 var tuple = new MediaTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, diskId))
301 {
302 DiskId = diskId,
303 LastSequence = FieldAsNullableInt(row, 1),
304 DiskPrompt = FieldAsString(row, 2),
305 Cabinet = FieldAsString(row, 3),
306 VolumeLabel = FieldAsString(row, 4),
307 Source = FieldAsString(row, 5)
308 };
309
310 if (wixMediaByDiskId.TryGetValue(diskId, out var wixMediaRow))
311 {
312 var compressionLevel = FieldAsString(wixMediaRow, 1);
313
314 tuple.CompressionLevel = String.IsNullOrEmpty(compressionLevel) ? null : (CompressionLevel?)Enum.Parse(typeof(CompressionLevel), compressionLevel, true);
315 tuple.Layout = wixMediaRow.Layout;
316 }
317
318 return tuple;
319 }
320 case "MIME":
321 return DefaultTupleFromRow(typeof(MIMETuple), row, columnZeroIsId: false);
322 case "ModuleIgnoreTable":
323 return DefaultTupleFromRow(typeof(ModuleIgnoreTableTuple), row, columnZeroIsId: true);
324 case "MoveFile":
325 return DefaultTupleFromRow(typeof(MoveFileTuple), row, columnZeroIsId: true);
326 case "MsiAssembly":
327 {
328 var componentId = FieldAsString(row, 0);
329 if (componentsById.TryGetValue(componentId, out var componentRow))
330 {
331 return new AssemblyTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(componentRow, 5)))
332 {
333 ComponentRef = componentId,
334 FeatureRef = FieldAsString(row, 1),
335 ManifestFileRef = FieldAsString(row, 2),
336 ApplicationFileRef = FieldAsString(row, 3),
337 Type = FieldAsNullableInt(row, 4) == 1 ? AssemblyType.Win32Assembly : AssemblyType.DotNetAssembly,
338 };
339 }
340
341 return null;
342 }
343 case "MsiLockPermissionsEx":
344 return DefaultTupleFromRow(typeof(MsiLockPermissionsExTuple), row, columnZeroIsId: true);
345 case "MsiShortcutProperty":
346 return DefaultTupleFromRow(typeof(MsiShortcutPropertyTuple), row, columnZeroIsId: true);
347 case "ODBCDataSource":
348 return DefaultTupleFromRow(typeof(ODBCDataSourceTuple), row, columnZeroIsId: true);
349 case "ODBCDriver":
350 return DefaultTupleFromRow(typeof(ODBCDriverTuple), row, columnZeroIsId: true);
351 case "ODBCTranslator":
352 return DefaultTupleFromRow(typeof(ODBCTranslatorTuple), row, columnZeroIsId: true);
353 case "ProgId":
354 return DefaultTupleFromRow(typeof(ProgIdTuple), row, columnZeroIsId: false);
355 case "Property":
356 return DefaultTupleFromRow(typeof(PropertyTuple), row, columnZeroIsId: true);
357 case "PublishComponent":
358 return DefaultTupleFromRow(typeof(PublishComponentTuple), row, columnZeroIsId: false);
359 case "Registry":
360 {
361 var value = FieldAsString(row, 4);
362 var valueType = RegistryValueType.String;
363 var valueAction = RegistryValueActionType.Write;
364
365 if (!String.IsNullOrEmpty(value))
366 {
367 if (value.StartsWith("#x", StringComparison.Ordinal))
368 {
369 valueType = RegistryValueType.Binary;
370 value = value.Substring(2);
371 }
372 else if (value.StartsWith("#%", StringComparison.Ordinal))
373 {
374 valueType = RegistryValueType.Expandable;
375 value = value.Substring(2);
376 }
377 else if (value.StartsWith("#", StringComparison.Ordinal))
378 {
379 valueType = RegistryValueType.Integer;
380 value = value.Substring(1);
381 }
382 else if (value.StartsWith("[~]", StringComparison.Ordinal) && value.EndsWith("[~]", StringComparison.Ordinal))
383 {
384 value = value.Substring(3, value.Length - 6);
385 valueType = RegistryValueType.MultiString;
386 valueAction = RegistryValueActionType.Write;
387 }
388 else if (value.StartsWith("[~]", StringComparison.Ordinal))
389 {
390 value = value.Substring(3);
391 valueType = RegistryValueType.MultiString;
392 valueAction = RegistryValueActionType.Append;
393 }
394 else if (value.EndsWith("[~]", StringComparison.Ordinal))
395 {
396 value = value.Substring(0, value.Length - 3);
397 valueType = RegistryValueType.MultiString;
398 valueAction = RegistryValueActionType.Prepend;
399 }
400 }
401
402 return new RegistryTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0)))
403 {
404 Root = (RegistryRootType)FieldAsInt(row, 1),
405 Key = FieldAsString(row, 2),
406 Name = FieldAsString(row, 3),
407 Value = value,
408 ComponentRef = FieldAsString(row, 5),
409 ValueAction = valueAction,
410 ValueType = valueType,
411 };
412 }
413 case "RegLocator":
414 {
415 var type = FieldAsInt(row, 4);
416
417 return new RegLocatorTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0)))
418 {
419 Root = (RegistryRootType)FieldAsInt(row, 1),
420 Key = FieldAsString(row, 2),
421 Name = FieldAsString(row, 3),
422 Type = (RegLocatorType)(type & 0xF),
423 Win64 = (type & WindowsInstallerConstants.MsidbLocatorType64bit) == WindowsInstallerConstants.MsidbLocatorType64bit
424 };
425 }
426 case "RemoveFile":
427 {
428 var installMode = FieldAsInt(row, 4);
429 return new RemoveFileTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0)))
430 {
431 ComponentRef = FieldAsString(row, 1),
432 FileName = FieldAsString(row, 2),
433 DirProperty = FieldAsString(row, 3),
434 OnInstall = (installMode & WindowsInstallerConstants.MsidbRemoveFileInstallModeOnInstall) == WindowsInstallerConstants.MsidbRemoveFileInstallModeOnInstall ? (bool?)true : null,
435 OnUninstall = (installMode & WindowsInstallerConstants.MsidbRemoveFileInstallModeOnRemove) == WindowsInstallerConstants.MsidbRemoveFileInstallModeOnRemove ? (bool?)true : null
436 };
437 }
438 case "RemoveRegistry":
439 {
440 return new RemoveRegistryTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0)))
441 {
442 Action = RemoveRegistryActionType.RemoveOnInstall,
443 Root = (RegistryRootType)FieldAsInt(row, 1),
444 Key = FieldAsString(row, 2),
445 Name = FieldAsString(row, 3),
446 ComponentRef = FieldAsString(row, 4),
447 };
448 }
449
450 case "ReserveCost":
451 return DefaultTupleFromRow(typeof(ReserveCostTuple), row, columnZeroIsId: true);
452 case "SelfReg":
453 return null;
454 case "ServiceControl":
455 {
456 var events = FieldAsInt(row, 2);
457 var wait = FieldAsNullableInt(row, 4);
458 return new ServiceControlTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0)))
459 {
460 Name = FieldAsString(row, 1),
461 Arguments = FieldAsString(row, 3),
462 Wait = !wait.HasValue || wait.Value == 1,
463 ComponentRef = FieldAsString(row, 5),
464 InstallRemove = (events & WindowsInstallerConstants.MsidbServiceControlEventDelete) == WindowsInstallerConstants.MsidbServiceControlEventDelete,
465 UninstallRemove = (events & WindowsInstallerConstants.MsidbServiceControlEventUninstallDelete) == WindowsInstallerConstants.MsidbServiceControlEventUninstallDelete,
466 InstallStart = (events & WindowsInstallerConstants.MsidbServiceControlEventStart) == WindowsInstallerConstants.MsidbServiceControlEventStart,
467 UninstallStart = (events & WindowsInstallerConstants.MsidbServiceControlEventUninstallStart) == WindowsInstallerConstants.MsidbServiceControlEventUninstallStart,
468 InstallStop = (events & WindowsInstallerConstants.MsidbServiceControlEventStop) == WindowsInstallerConstants.MsidbServiceControlEventStop,
469 UninstallStop = (events & WindowsInstallerConstants.MsidbServiceControlEventUninstallStop) == WindowsInstallerConstants.MsidbServiceControlEventUninstallStop,
470 };
471 }
472
473 case "ServiceInstall":
474 return DefaultTupleFromRow(typeof(ServiceInstallTuple), row, columnZeroIsId: true);
475 case "Shortcut":
476 {
477 var splitName = FieldAsString(row, 2).Split('|');
478
479 return new ShortcutTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0)))
480 {
481 DirectoryRef = FieldAsString(row, 1),
482 Name = splitName.Length > 1 ? splitName[1] : splitName[0],
483 ShortName = splitName.Length > 1 ? splitName[0] : null,
484 ComponentRef = FieldAsString(row, 3),
485 Target = FieldAsString(row, 4),
486 Arguments = FieldAsString(row, 5),
487 Description = FieldAsString(row, 6),
488 Hotkey = FieldAsNullableInt(row, 7),
489 IconRef = FieldAsString(row, 8),
490 IconIndex = FieldAsNullableInt(row, 9),
491 Show = (ShortcutShowType?)FieldAsNullableInt(row, 10),
492 WorkingDirectory = FieldAsString(row, 11),
493 DisplayResourceDll = FieldAsString(row, 12),
494 DisplayResourceId = FieldAsNullableInt(row, 13),
495 DescriptionResourceDll = FieldAsString(row, 14),
496 DescriptionResourceId= FieldAsNullableInt(row, 15),
497 };
498 }
499 case "Signature":
500 return DefaultTupleFromRow(typeof(SignatureTuple), row, columnZeroIsId: false);
501 case "UIText":
502 return DefaultTupleFromRow(typeof(UITextTuple), row, columnZeroIsId: true);
503 case "Upgrade":
504 {
505 var attributes = FieldAsInt(row, 4);
506 return new UpgradeTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0)))
507 {
508 UpgradeCode = FieldAsString(row, 0),
509 VersionMin = FieldAsString(row, 1),
510 VersionMax = FieldAsString(row, 2),
511 Language = FieldAsString(row, 3),
512 Remove = FieldAsString(row, 5),
513 ActionProperty = FieldAsString(row, 6),
514 MigrateFeatures = (attributes & WindowsInstallerConstants.MsidbUpgradeAttributesMigrateFeatures) == WindowsInstallerConstants.MsidbUpgradeAttributesMigrateFeatures,
515 OnlyDetect = (attributes & WindowsInstallerConstants.MsidbUpgradeAttributesOnlyDetect) == WindowsInstallerConstants.MsidbUpgradeAttributesOnlyDetect,
516 IgnoreRemoveFailures = (attributes & WindowsInstallerConstants.MsidbUpgradeAttributesIgnoreRemoveFailure) == WindowsInstallerConstants.MsidbUpgradeAttributesIgnoreRemoveFailure,
517 VersionMinInclusive = (attributes & WindowsInstallerConstants.MsidbUpgradeAttributesVersionMinInclusive) == WindowsInstallerConstants.MsidbUpgradeAttributesVersionMinInclusive,
518 VersionMaxInclusive = (attributes & WindowsInstallerConstants.MsidbUpgradeAttributesVersionMaxInclusive) == WindowsInstallerConstants.MsidbUpgradeAttributesVersionMaxInclusive,
519 ExcludeLanguages = (attributes & WindowsInstallerConstants.MsidbUpgradeAttributesLanguagesExclusive) == WindowsInstallerConstants.MsidbUpgradeAttributesLanguagesExclusive,
520 };
521 }
522 case "Verb":
523 return DefaultTupleFromRow(typeof(VerbTuple), row, columnZeroIsId: false);
524 case "WixAction":
525 {
526 var sequenceTable = FieldAsString(row, 0);
527 return new WixActionTuple(SourceLineNumber4(row.SourceLineNumbers))
528 {
529 SequenceTable = (SequenceTable)Enum.Parse(typeof(SequenceTable), sequenceTable == "AdvtExecuteSequence" ? nameof(SequenceTable.AdvertiseExecuteSequence) : sequenceTable),
530 Action = FieldAsString(row, 1),
531 Condition = FieldAsString(row, 2),
532 Sequence = FieldAsNullableInt(row, 3),
533 Before = FieldAsString(row, 4),
534 After = FieldAsString(row, 5),
535 Overridable = FieldAsNullableInt(row, 6) != 0,
536 };
537 }
538 case "WixBootstrapperApplication":
539 return DefaultTupleFromRow(typeof(WixBootstrapperApplicationTuple), row, columnZeroIsId: true);
540 case "WixBundleContainer":
541 return DefaultTupleFromRow(typeof(WixBundleContainerTuple), row, columnZeroIsId: true);
542 case "WixBundleVariable":
543 return DefaultTupleFromRow(typeof(WixBundleVariableTuple), row, columnZeroIsId: true);
544 case "WixChainItem":
545 return DefaultTupleFromRow(typeof(WixChainItemTuple), row, columnZeroIsId: true);
546 case "WixCustomTable":
547 return DefaultTupleFromRow(typeof(WixCustomTableTuple), row, columnZeroIsId: true);
548 case "WixDirectory":
549 return null;
550 case "WixFile":
551 return null;
552 case "WixInstanceTransforms":
553 return DefaultTupleFromRow(typeof(WixInstanceTransformsTuple), row, columnZeroIsId: true);
554 case "WixMedia":
555 return null;
556 case "WixMerge":
557 return DefaultTupleFromRow(typeof(WixMergeTuple), row, columnZeroIsId: true);
558 case "WixPatchBaseline":
559 return DefaultTupleFromRow(typeof(WixPatchBaselineTuple), row, columnZeroIsId: true);
560 case "WixProperty":
561 {
562 var attributes = FieldAsInt(row, 1);
563 return new WixPropertyTuple(SourceLineNumber4(row.SourceLineNumbers))
564 {
565 PropertyRef = FieldAsString(row, 0),
566 Admin = (attributes & 0x1) == 0x1,
567 Hidden = (attributes & 0x2) == 0x2,
568 Secure = (attributes & 0x4) == 0x4,
569 };
570 }
571 case "WixSuppressModularization":
572 return DefaultTupleFromRow(typeof(WixSuppressModularizationTuple), row, columnZeroIsId: true);
573 case "WixUI":
574 return DefaultTupleFromRow(typeof(WixUITuple), row, columnZeroIsId: true);
575 case "WixVariable":
576 return DefaultTupleFromRow(typeof(WixVariableTuple), row, columnZeroIsId: true);
577 default:
578 return GenericTupleFromCustomRow(row, columnZeroIsId: false);
579 }
580 }
581
582 private static CustomActionTargetType DetermineCustomActionTargetType(int type)
583 {
584 var targetType = default(CustomActionTargetType);
585
586 if ((type & WindowsInstallerConstants.MsidbCustomActionTypeVBScript) == WindowsInstallerConstants.MsidbCustomActionTypeVBScript)
587 {
588 targetType = CustomActionTargetType.VBScript;
589 }
590 else if ((type & WindowsInstallerConstants.MsidbCustomActionTypeJScript) == WindowsInstallerConstants.MsidbCustomActionTypeJScript)
591 {
592 targetType = CustomActionTargetType.JScript;
593 }
594 else if ((type & WindowsInstallerConstants.MsidbCustomActionTypeTextData) == WindowsInstallerConstants.MsidbCustomActionTypeTextData)
595 {
596 targetType = CustomActionTargetType.TextData;
597 }
598 else if ((type & WindowsInstallerConstants.MsidbCustomActionTypeExe) == WindowsInstallerConstants.MsidbCustomActionTypeExe)
599 {
600 targetType = CustomActionTargetType.Exe;
601 }
602 else if ((type & WindowsInstallerConstants.MsidbCustomActionTypeDll) == WindowsInstallerConstants.MsidbCustomActionTypeDll)
603 {
604 targetType = CustomActionTargetType.Dll;
605 }
606
607 return targetType;
608 }
609
610 private static CustomActionSourceType DetermineCustomActionSourceType(int type)
611 {
612 var sourceType = CustomActionSourceType.Binary;
613
614 if ((type & WindowsInstallerConstants.MsidbCustomActionTypeProperty) == WindowsInstallerConstants.MsidbCustomActionTypeProperty)
615 {
616 sourceType = CustomActionSourceType.Property;
617 }
618 else if ((type & WindowsInstallerConstants.MsidbCustomActionTypeDirectory) == WindowsInstallerConstants.MsidbCustomActionTypeDirectory)
619 {
620 sourceType = CustomActionSourceType.Directory;
621 }
622 else if ((type & WindowsInstallerConstants.MsidbCustomActionTypeSourceFile) == WindowsInstallerConstants.MsidbCustomActionTypeSourceFile)
623 {
624 sourceType = CustomActionSourceType.File;
625 }
626
627 return sourceType;
628 }
629
630 private static CustomActionExecutionType DetermineCustomActionExecutionType(int type)
631 {
632 var executionType = CustomActionExecutionType.Immediate;
633
634 if ((type & (WindowsInstallerConstants.MsidbCustomActionTypeInScript | WindowsInstallerConstants.MsidbCustomActionTypeCommit)) == (WindowsInstallerConstants.MsidbCustomActionTypeInScript | WindowsInstallerConstants.MsidbCustomActionTypeCommit))
635 {
636 executionType = CustomActionExecutionType.Commit;
637 }
638 else if ((type & (WindowsInstallerConstants.MsidbCustomActionTypeInScript | WindowsInstallerConstants.MsidbCustomActionTypeRollback)) == (WindowsInstallerConstants.MsidbCustomActionTypeInScript | WindowsInstallerConstants.MsidbCustomActionTypeRollback))
639 {
640 executionType = CustomActionExecutionType.Rollback;
641 }
642 else if ((type & WindowsInstallerConstants.MsidbCustomActionTypeInScript) == WindowsInstallerConstants.MsidbCustomActionTypeInScript)
643 {
644 executionType = CustomActionExecutionType.Deferred;
645 }
646 else if ((type & WindowsInstallerConstants.MsidbCustomActionTypeClientRepeat) == WindowsInstallerConstants.MsidbCustomActionTypeClientRepeat)
647 {
648 executionType = CustomActionExecutionType.ClientRepeat;
649 }
650 else if ((type & WindowsInstallerConstants.MsidbCustomActionTypeOncePerProcess) == WindowsInstallerConstants.MsidbCustomActionTypeOncePerProcess)
651 {
652 executionType = CustomActionExecutionType.OncePerProcess;
653 }
654 else if ((type & WindowsInstallerConstants.MsidbCustomActionTypeFirstSequence) == WindowsInstallerConstants.MsidbCustomActionTypeFirstSequence)
655 {
656 executionType = CustomActionExecutionType.FirstSequence;
657 }
658
659 return executionType;
660 }
661
662 private static IntermediateFieldType ColumnType3ToIntermediateFieldType4(Wix3.ColumnType columnType)
663 {
664 switch (columnType)
665 {
666 case Wix3.ColumnType.Number:
667 return IntermediateFieldType.Number;
668 case Wix3.ColumnType.Object:
669 return IntermediateFieldType.Path;
670 case Wix3.ColumnType.Unknown:
671 case Wix3.ColumnType.String:
672 case Wix3.ColumnType.Localized:
673 case Wix3.ColumnType.Preserved:
674 default:
675 return IntermediateFieldType.String;
676 }
677 }
678
679 private static IntermediateTuple DefaultTupleFromRow(Type tupleType, Wix3.Row row, bool columnZeroIsId)
680 {
681 var tuple = Activator.CreateInstance(tupleType) as IntermediateTuple;
682
683 SetTupleFieldsFromRow(row, tuple, columnZeroIsId);
684
685 tuple.SourceLineNumbers = SourceLineNumber4(row.SourceLineNumbers);
686 return tuple;
687 }
688
689 private static IntermediateTuple GenericTupleFromCustomRow(Wix3.Row row, bool columnZeroIsId)
690 {
691 var columnDefinitions = row.Table.Definition.Columns.Cast<Wix3.ColumnDefinition>();
692 var fieldDefinitions = columnDefinitions.Select(columnDefinition =>
693 new IntermediateFieldDefinition(columnDefinition.Name, ColumnType3ToIntermediateFieldType4(columnDefinition.Type))).ToArray();
694 var tupleDefinition = new IntermediateTupleDefinition(row.Table.Name, fieldDefinitions, null);
695 var tuple = new IntermediateTuple(tupleDefinition, SourceLineNumber4(row.SourceLineNumbers));
696
697 SetTupleFieldsFromRow(row, tuple, columnZeroIsId);
698
699 return tuple;
700 }
701
702 private static void SetTupleFieldsFromRow(Wix3.Row row, IntermediateTuple tuple, bool columnZeroIsId)
703 {
704 int offset = 0;
705 if (columnZeroIsId)
706 {
707 tuple.Id = GetIdentifierForRow(row);
708 offset = 1;
709 }
710
711 for (var i = offset; i < row.Fields.Length; ++i)
712 {
713 var column = row.Fields[i].Column;
714 switch (column.Type)
715 {
716 case Wix3.ColumnType.String:
717 case Wix3.ColumnType.Localized:
718 case Wix3.ColumnType.Object:
719 case Wix3.ColumnType.Preserved:
720 tuple.Set(i - offset, FieldAsString(row, i));
721 break;
722 case Wix3.ColumnType.Number:
723 int? nullableValue = FieldAsNullableInt(row, i);
724 // TODO: Consider whether null values should be coerced to their default value when
725 // a column is not nullable. For now, just pass through the null.
726 //int value = FieldAsInt(row, i);
727 //tuple.Set(i - offset, column.IsNullable ? nullableValue : value);
728 tuple.Set(i - offset, nullableValue);
729 break;
730 case Wix3.ColumnType.Unknown:
731 break;
732 }
733 }
734 }
735
736 private static Identifier GetIdentifierForRow(Wix3.Row row)
737 {
738 var column = row.Fields[0].Column;
739 switch (column.Type)
740 {
741 case Wix3.ColumnType.String:
742 case Wix3.ColumnType.Localized:
743 case Wix3.ColumnType.Object:
744 case Wix3.ColumnType.Preserved:
745 return new Identifier(AccessModifier.Public, (string)row.Fields[0].Data);
746 case Wix3.ColumnType.Number:
747 return new Identifier(AccessModifier.Public, FieldAsInt(row, 0));
748 default:
749 return null;
750 }
751 }
752
753 private static SectionType OutputType3ToSectionType4(Wix3.OutputType outputType)
754 {
755 switch (outputType)
756 {
757 case Wix3.OutputType.Bundle:
758 return SectionType.Bundle;
759 case Wix3.OutputType.Module:
760 return SectionType.Module;
761 case Wix3.OutputType.Patch:
762 return SectionType.Patch;
763 case Wix3.OutputType.PatchCreation:
764 return SectionType.PatchCreation;
765 case Wix3.OutputType.Product:
766 return SectionType.Product;
767 case Wix3.OutputType.Transform:
768 case Wix3.OutputType.Unknown:
769 default:
770 return SectionType.Unknown;
771 }
772 }
773
774 private static SourceLineNumber SourceLineNumber4(Wix3.SourceLineNumberCollection source)
775 {
776 return String.IsNullOrEmpty(source?.EncodedSourceLineNumbers) ? null : SourceLineNumber.CreateFromEncoded(source.EncodedSourceLineNumbers);
777 }
778
779 private static string FieldAsString(Wix3.Row row, int column)
780 {
781 return (string)row[column];
782 }
783
784 private static int FieldAsInt(Wix3.Row row, int column)
785 {
786 return Convert.ToInt32(row[column]);
787 }
788
789 private static int? FieldAsNullableInt(Wix3.Row row, int column)
790 {
791 var field = row.Fields[column];
792 if (field.Data == null)
793 {
794 return null;
795 }
796 else
797 {
798 return Convert.ToInt32(field.Data);
799 }
800 }
801
802 private static string[] SplitDefaultDir(string defaultDir)
803 {
804 var split1 = defaultDir.Split(':');
805 var targetSplit = split1.Length > 1 ? split1[1].Split('|') : split1[0].Split('|');
806 var sourceSplit = split1.Length > 1 ? split1[0].Split('|') : new[] { String.Empty };
807 return new[]
808 {
809 targetSplit.Length > 1 ? targetSplit[1] : targetSplit[0],
810 targetSplit.Length > 1 ? targetSplit[0] : null,
811 sourceSplit.Length > 1 ? sourceSplit[1] : sourceSplit[0],
812 sourceSplit.Length > 1 ? sourceSplit[0] : null
813 };
814 }
815 }
816}