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