main
cs 1,713 lines 79.2 KB
Raw
1 // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3 namespace WixToolset.Core.WindowsInstaller.Bind
4 {
5 using System;
6 using System.Collections.Generic;
7 using System.Globalization;
8 using System.IO;
9 using System.Linq;
10 using System.Security.Cryptography;
11 using System.Text;
12 using WixToolset.Data;
13 using WixToolset.Data.Symbols;
14 using WixToolset.Data.WindowsInstaller;
15 using WixToolset.Data.WindowsInstaller.Rows;
16 using WixToolset.Extensibility;
17 using WixToolset.Extensibility.Services;
18
19 internal class CreateWindowsInstallerDataFromIRCommand
20 {
21 private static readonly char[] PathSeparatorChars = new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar };
22
23 public CreateWindowsInstallerDataFromIRCommand(IMessaging messaging, IntermediateSection section, TableDefinitionCollection tableDefinitions, int codepage, IEnumerable<IWindowsInstallerBackendBinderExtension> backendExtensions, IWindowsInstallerBackendHelper backendHelper)
24 {
25 this.Messaging = messaging;
26 this.Section = section;
27 this.TableDefinitions = tableDefinitions;
28 this.Codepage = codepage;
29 this.BackendExtensions = backendExtensions;
30 this.BackendHelper = backendHelper;
31 this.GeneratedShortNames = new Dictionary<string, List<FileSymbol>>();
32 }
33
34 private IEnumerable<IWindowsInstallerBackendBinderExtension> BackendExtensions { get; }
35
36 private IWindowsInstallerBackendHelper BackendHelper { get; }
37
38 private IMessaging Messaging { get; }
39
40 private TableDefinitionCollection TableDefinitions { get; }
41
42 private int Codepage { get; }
43
44 private IntermediateSection Section { get; }
45
46 private Dictionary<string, List<FileSymbol>> GeneratedShortNames { get; }
47
48 public WindowsInstallerData Data { get; private set; }
49
50 public WindowsInstallerData Execute()
51 {
52 this.Data = new WindowsInstallerData(this.Section.Symbols.First().SourceLineNumbers)
53 {
54 Codepage = this.Codepage,
55 Type = SectionTypeToOutputType(this.Section.Type)
56 };
57
58 this.AddSectionToData();
59
60 return this.Data;
61 }
62
63 private void AddSectionToData()
64 {
65 var cellsByTableAndRowId = new Dictionary<string, List<WixCustomTableCellSymbol>>();
66
67 foreach (var symbol in this.Section.Symbols)
68 {
69 var unknownSymbol = false;
70 switch (symbol.Definition.Type)
71 {
72 case SymbolDefinitionType.AppSearch:
73 this.AddSymbolDefaultly(symbol);
74 this.Data.EnsureTable(this.TableDefinitions["Signature"]);
75 break;
76
77 case SymbolDefinitionType.Assembly:
78 this.AddAssemblySymbol((AssemblySymbol)symbol);
79 break;
80
81 case SymbolDefinitionType.BBControl:
82 this.AddBBControlSymbol((BBControlSymbol)symbol);
83 break;
84
85 case SymbolDefinitionType.Class:
86 this.AddClassSymbol((ClassSymbol)symbol);
87 break;
88
89 case SymbolDefinitionType.Control:
90 this.AddControlSymbol((ControlSymbol)symbol);
91 break;
92
93 case SymbolDefinitionType.ControlEvent:
94 this.AddControlEventSymbol((ControlEventSymbol)symbol);
95 break;
96
97 case SymbolDefinitionType.Component:
98 this.AddComponentSymbol((ComponentSymbol)symbol);
99 break;
100
101 case SymbolDefinitionType.CustomAction:
102 this.AddCustomActionSymbol((CustomActionSymbol)symbol);
103 break;
104
105 case SymbolDefinitionType.Dialog:
106 this.AddDialogSymbol((DialogSymbol)symbol);
107 break;
108
109 case SymbolDefinitionType.Directory:
110 this.AddDirectorySymbol((DirectorySymbol)symbol);
111 break;
112
113 case SymbolDefinitionType.DuplicateFile:
114 this.AddDuplicateFileSymbol((DuplicateFileSymbol)symbol);
115 break;
116
117 case SymbolDefinitionType.Environment:
118 this.AddEnvironmentSymbol((EnvironmentSymbol)symbol);
119 break;
120
121 case SymbolDefinitionType.Error:
122 this.AddErrorSymbol((ErrorSymbol)symbol);
123 break;
124
125 case SymbolDefinitionType.Feature:
126 this.AddFeatureSymbol((FeatureSymbol)symbol);
127 break;
128
129 case SymbolDefinitionType.File:
130 this.AddFileSymbol((FileSymbol)symbol);
131 break;
132
133 case SymbolDefinitionType.IniFile:
134 this.AddIniFileSymbol((IniFileSymbol)symbol);
135 break;
136
137 case SymbolDefinitionType.IniLocator:
138 this.AddIniLocatorSymbol((IniLocatorSymbol)symbol);
139 break;
140
141 case SymbolDefinitionType.Media:
142 this.AddMediaSymbol((MediaSymbol)symbol);
143 break;
144
145 case SymbolDefinitionType.ModuleConfiguration:
146 this.AddModuleConfigurationSymbol((ModuleConfigurationSymbol)symbol);
147 this.EnsureModuleIgnoredTable(symbol, "ModuleConfiguration");
148 break;
149
150 case SymbolDefinitionType.ModuleSubstitution:
151 this.AddSymbolDefaultly(symbol);
152 this.EnsureModuleIgnoredTable(symbol, "ModuleSubstitution");
153 break;
154
155 case SymbolDefinitionType.MsiEmbeddedUI:
156 this.AddMsiEmbeddedUISymbol((MsiEmbeddedUISymbol)symbol);
157 break;
158
159 case SymbolDefinitionType.MsiServiceConfig:
160 this.AddMsiServiceConfigSymbol((MsiServiceConfigSymbol)symbol);
161 break;
162
163 case SymbolDefinitionType.MsiServiceConfigFailureActions:
164 this.AddMsiServiceConfigFailureActionsSymbol((MsiServiceConfigFailureActionsSymbol)symbol);
165 break;
166
167 case SymbolDefinitionType.MoveFile:
168 this.AddMoveFileSymbol((MoveFileSymbol)symbol);
169 break;
170
171 case SymbolDefinitionType.ProgId:
172 this.AddSymbolDefaultly(symbol);
173 this.Data.EnsureTable(this.TableDefinitions["Extension"]);
174 break;
175
176 case SymbolDefinitionType.Property:
177 this.AddPropertySymbol((PropertySymbol)symbol);
178 break;
179
180 case SymbolDefinitionType.RemoveFile:
181 this.AddRemoveFileSymbol((RemoveFileSymbol)symbol);
182 break;
183
184 case SymbolDefinitionType.Registry:
185 this.AddRegistrySymbol((RegistrySymbol)symbol);
186 break;
187
188 case SymbolDefinitionType.RegLocator:
189 this.AddRegLocatorSymbol((RegLocatorSymbol)symbol);
190 break;
191
192 case SymbolDefinitionType.RemoveRegistry:
193 this.AddRemoveRegistrySymbol((RemoveRegistrySymbol)symbol);
194 break;
195
196 case SymbolDefinitionType.ServiceControl:
197 this.AddServiceControlSymbol((ServiceControlSymbol)symbol);
198 break;
199
200 case SymbolDefinitionType.ServiceInstall:
201 this.AddServiceInstallSymbol((ServiceInstallSymbol)symbol);
202 break;
203
204 case SymbolDefinitionType.Shortcut:
205 this.AddShortcutSymbol((ShortcutSymbol)symbol);
206 break;
207
208 case SymbolDefinitionType.TextStyle:
209 this.AddTextStyleSymbol((TextStyleSymbol)symbol);
210 break;
211
212 case SymbolDefinitionType.Upgrade:
213 this.AddUpgradeSymbol((UpgradeSymbol)symbol);
214 break;
215
216 case SymbolDefinitionType.WixAction:
217 this.AddWixActionSymbol((WixActionSymbol)symbol);
218 break;
219
220 case SymbolDefinitionType.WixCustomTableCell:
221 this.IndexCustomTableCellSymbol((WixCustomTableCellSymbol)symbol, cellsByTableAndRowId);
222 break;
223
224 case SymbolDefinitionType.WixEnsureTable:
225 this.AddWixEnsureTableSymbol((WixEnsureTableSymbol)symbol);
226 break;
227
228 case SymbolDefinitionType.WixModule:
229 this.AddWixModuleSymbol((WixModuleSymbol)symbol);
230 break;
231
232 case SymbolDefinitionType.WixPackage:
233 this.AddWixPackageSymbol((WixPackageSymbol)symbol);
234 break;
235
236 // Symbols used internally and are not added to the output.
237 case SymbolDefinitionType.HarvestFiles:
238 case SymbolDefinitionType.WixBuildInfo:
239 case SymbolDefinitionType.WixBindUpdatedFiles:
240 case SymbolDefinitionType.WixComponentGroup:
241 case SymbolDefinitionType.WixComplexReference:
242 case SymbolDefinitionType.WixDeltaPatchFile:
243 case SymbolDefinitionType.WixDeltaPatchSymbolPaths:
244 case SymbolDefinitionType.WixFragment:
245 case SymbolDefinitionType.WixFeatureGroup:
246 case SymbolDefinitionType.WixInstanceComponent:
247 case SymbolDefinitionType.WixInstanceTransforms:
248 case SymbolDefinitionType.WixFeatureModules:
249 case SymbolDefinitionType.WixGroup:
250 case SymbolDefinitionType.WixMediaTemplate:
251 case SymbolDefinitionType.WixMerge:
252 case SymbolDefinitionType.WixOrdering:
253 case SymbolDefinitionType.WixPatchBaseline:
254 case SymbolDefinitionType.WixPatchFamilyGroup:
255 case SymbolDefinitionType.WixPatch:
256 case SymbolDefinitionType.WixPatchRef:
257 case SymbolDefinitionType.WixPatchTarget:
258 case SymbolDefinitionType.WixProperty:
259 case SymbolDefinitionType.WixPackageTag:
260 case SymbolDefinitionType.WixSimpleReference:
261 case SymbolDefinitionType.WixSuppressAction:
262 case SymbolDefinitionType.WixSuppressModularization:
263 case SymbolDefinitionType.WixUI:
264 case SymbolDefinitionType.WixVariable:
265 break;
266
267 // Already processed by LoadTableDefinitions.
268 case SymbolDefinitionType.WixCustomTable:
269 case SymbolDefinitionType.WixCustomTableColumn:
270 break;
271
272 case SymbolDefinitionType.MustBeFromAnExtension:
273 if (!this.AddSymbolFromExtension(symbol))
274 {
275 unknownSymbol = !this.AddSymbolDefaultly(symbol);
276 }
277 break;
278
279 default:
280 unknownSymbol = !this.AddSymbolDefaultly(symbol);
281 break;
282 }
283
284 if (unknownSymbol)
285 {
286 this.Messaging.Write(WarningMessages.SymbolNotTranslatedToOutput(symbol));
287 }
288 }
289
290 this.AddIndexedCellSymbols(cellsByTableAndRowId);
291 this.EnsureRequiredTables();
292 this.ReportGeneratedShortFileNameConflicts();
293 this.ReportIllegalTables();
294 this.ReportMismatchedModularizations();
295 this.ReportWindowsInstallerDataInconsistencies();
296 }
297
298 private void AddAssemblySymbol(AssemblySymbol symbol)
299 {
300 var attributes = symbol.Type == AssemblyType.Win32Assembly ? 1 : (int?)null;
301
302 var row = this.CreateRow(symbol, "MsiAssembly");
303 row[0] = symbol.ComponentRef;
304 row[1] = symbol.FeatureRef;
305 row[2] = symbol.ManifestFileRef;
306 row[3] = symbol.ApplicationFileRef;
307 row[4] = attributes;
308 }
309
310 private void AddBBControlSymbol(BBControlSymbol symbol)
311 {
312 var attributes = symbol.Attributes;
313 attributes |= symbol.Enabled ? WindowsInstallerConstants.MsidbControlAttributesEnabled : 0;
314 attributes |= symbol.Indirect ? WindowsInstallerConstants.MsidbControlAttributesIndirect : 0;
315 attributes |= symbol.Integer ? WindowsInstallerConstants.MsidbControlAttributesInteger : 0;
316 attributes |= symbol.LeftScroll ? WindowsInstallerConstants.MsidbControlAttributesLeftScroll : 0;
317 attributes |= symbol.RightAligned ? WindowsInstallerConstants.MsidbControlAttributesRightAligned : 0;
318 attributes |= symbol.RightToLeft ? WindowsInstallerConstants.MsidbControlAttributesRTLRO : 0;
319 attributes |= symbol.Sunken ? WindowsInstallerConstants.MsidbControlAttributesSunken : 0;
320 attributes |= symbol.Visible ? WindowsInstallerConstants.MsidbControlAttributesVisible : 0;
321
322 var row = this.CreateRow(symbol, "BBControl");
323 row[0] = symbol.BillboardRef;
324 row[1] = symbol.BBControl;
325 row[2] = symbol.Type;
326 row[3] = symbol.X;
327 row[4] = symbol.Y;
328 row[5] = symbol.Width;
329 row[6] = symbol.Height;
330 row[7] = attributes;
331 row[8] = symbol.Text;
332 }
333
334 private void AddClassSymbol(ClassSymbol symbol)
335 {
336 var row = this.CreateRow(symbol, "Class");
337 row[0] = symbol.CLSID;
338 row[1] = symbol.Context;
339 row[2] = symbol.ComponentRef;
340 row[3] = symbol.DefaultProgIdRef;
341 row[4] = symbol.Description;
342 row[5] = symbol.AppIdRef;
343 row[6] = symbol.FileTypeMask;
344 row[7] = symbol.IconRef;
345 row[8] = symbol.IconIndex;
346 row[9] = symbol.DefInprocHandler;
347 row[10] = symbol.Argument;
348 row[11] = symbol.FeatureRef;
349 row[12] = symbol.RelativePath ? (int?)1 : null;
350 }
351
352 private void AddControlSymbol(ControlSymbol symbol)
353 {
354 var text = symbol.Text;
355 var attributes = symbol.Attributes;
356 attributes |= symbol.Enabled ? WindowsInstallerConstants.MsidbControlAttributesEnabled : 0;
357 attributes |= symbol.Indirect ? WindowsInstallerConstants.MsidbControlAttributesIndirect : 0;
358 attributes |= symbol.Integer ? WindowsInstallerConstants.MsidbControlAttributesInteger : 0;
359 attributes |= symbol.LeftScroll ? WindowsInstallerConstants.MsidbControlAttributesLeftScroll : 0;
360 attributes |= symbol.RightAligned ? WindowsInstallerConstants.MsidbControlAttributesRightAligned : 0;
361 attributes |= symbol.RightToLeft ? WindowsInstallerConstants.MsidbControlAttributesRTLRO : 0;
362 attributes |= symbol.Sunken ? WindowsInstallerConstants.MsidbControlAttributesSunken : 0;
363 attributes |= symbol.Visible ? WindowsInstallerConstants.MsidbControlAttributesVisible : 0;
364
365 // If we're tracking disk space, and this is a non-FormatSize Text control,
366 // and the text attribute starts with '[' and ends with ']', add a space.
367 // It is not necessary for the whole string to be a property, just those
368 // two characters matter.
369 if (symbol.TrackDiskSpace &&
370 "Text" == symbol.Type &&
371 WindowsInstallerConstants.MsidbControlAttributesFormatSize != (attributes & WindowsInstallerConstants.MsidbControlAttributesFormatSize) &&
372 null != text && text.StartsWith("[", StringComparison.Ordinal) && text.EndsWith("]", StringComparison.Ordinal))
373 {
374 text = String.Concat(text, " ");
375 }
376
377 var row = this.CreateRow(symbol, "Control");
378 row[0] = symbol.DialogRef;
379 row[1] = symbol.Control;
380 row[2] = symbol.Type;
381 row[3] = symbol.X;
382 row[4] = symbol.Y;
383 row[5] = symbol.Width;
384 row[6] = symbol.Height;
385 row[7] = attributes;
386 row[8] = symbol.Property;
387 row[9] = text;
388 row[10] = symbol.NextControlRef;
389 row[11] = symbol.Help;
390 }
391
392 private void AddControlEventSymbol(ControlEventSymbol symbol)
393 {
394 var row = this.CreateRow(symbol, "ControlEvent");
395 row[0] = symbol.DialogRef;
396 row[1] = symbol.ControlRef;
397 row[2] = symbol.Event;
398 row[3] = symbol.Argument;
399 row[4] = String.IsNullOrEmpty(symbol.Condition) ? "1" : symbol.Condition;
400 row[5] = symbol.Ordering;
401 }
402
403 private void AddComponentSymbol(ComponentSymbol symbol)
404 {
405 var attributes = ComponentLocation.Either == symbol.Location ? WindowsInstallerConstants.MsidbComponentAttributesOptional : 0;
406 attributes |= ComponentLocation.SourceOnly == symbol.Location ? WindowsInstallerConstants.MsidbComponentAttributesSourceOnly : 0;
407 attributes |= ComponentKeyPathType.Registry == symbol.KeyPathType ? WindowsInstallerConstants.MsidbComponentAttributesRegistryKeyPath : 0;
408 attributes |= ComponentKeyPathType.OdbcDataSource == symbol.KeyPathType ? WindowsInstallerConstants.MsidbComponentAttributesODBCDataSource : 0;
409 attributes |= symbol.DisableRegistryReflection ? WindowsInstallerConstants.MsidbComponentAttributesDisableRegistryReflection : 0;
410 attributes |= symbol.NeverOverwrite ? WindowsInstallerConstants.MsidbComponentAttributesNeverOverwrite : 0;
411 attributes |= symbol.Permanent ? WindowsInstallerConstants.MsidbComponentAttributesPermanent : 0;
412 attributes |= symbol.SharedDllRefCount ? WindowsInstallerConstants.MsidbComponentAttributesSharedDllRefCount : 0;
413 attributes |= symbol.Shared ? WindowsInstallerConstants.MsidbComponentAttributesShared : 0;
414 attributes |= symbol.Transitive ? WindowsInstallerConstants.MsidbComponentAttributesTransitive : 0;
415 attributes |= symbol.UninstallWhenSuperseded ? WindowsInstallerConstants.MsidbComponentAttributesUninstallOnSupersedence : 0;
416 attributes |= symbol.Win64 ? WindowsInstallerConstants.MsidbComponentAttributes64bit : 0;
417
418 var row = this.CreateRow(symbol, "Component");
419 row[0] = symbol.Id.Id;
420 row[1] = symbol.ComponentId;
421 row[2] = symbol.DirectoryRef;
422 row[3] = attributes;
423 row[4] = symbol.Condition;
424 row[5] = symbol.KeyPath;
425 }
426
427 private void AddCustomActionSymbol(CustomActionSymbol symbol)
428 {
429 var type = symbol.Win64 ? WindowsInstallerConstants.MsidbCustomActionType64BitScript : 0;
430 type |= symbol.IgnoreResult ? WindowsInstallerConstants.MsidbCustomActionTypeContinue : 0;
431 type |= symbol.Hidden ? WindowsInstallerConstants.MsidbCustomActionTypeHideTarget : 0;
432 type |= symbol.Async ? WindowsInstallerConstants.MsidbCustomActionTypeAsync : 0;
433 type |= CustomActionExecutionType.FirstSequence == symbol.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeFirstSequence : 0;
434 type |= CustomActionExecutionType.OncePerProcess == symbol.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeOncePerProcess : 0;
435 type |= CustomActionExecutionType.ClientRepeat == symbol.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeClientRepeat : 0;
436 type |= CustomActionExecutionType.Deferred == symbol.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeInScript : 0;
437 type |= CustomActionExecutionType.Rollback == symbol.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeInScript | WindowsInstallerConstants.MsidbCustomActionTypeRollback : 0;
438 type |= CustomActionExecutionType.Commit == symbol.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeInScript | WindowsInstallerConstants.MsidbCustomActionTypeCommit : 0;
439 type |= CustomActionSourceType.File == symbol.SourceType ? WindowsInstallerConstants.MsidbCustomActionTypeSourceFile : 0;
440 type |= CustomActionSourceType.Directory == symbol.SourceType ? WindowsInstallerConstants.MsidbCustomActionTypeDirectory : 0;
441 type |= CustomActionSourceType.Property == symbol.SourceType ? WindowsInstallerConstants.MsidbCustomActionTypeProperty : 0;
442 type |= CustomActionTargetType.Dll == symbol.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeDll : 0;
443 type |= CustomActionTargetType.Exe == symbol.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeExe : 0;
444 type |= CustomActionTargetType.TextData == symbol.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeTextData : 0;
445 type |= CustomActionTargetType.JScript == symbol.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeJScript : 0;
446 type |= CustomActionTargetType.VBScript == symbol.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeVBScript : 0;
447
448 if (WindowsInstallerConstants.MsidbCustomActionTypeInScript == (type & WindowsInstallerConstants.MsidbCustomActionTypeInScript))
449 {
450 type |= symbol.Impersonate ? 0 : WindowsInstallerConstants.MsidbCustomActionTypeNoImpersonate;
451 type |= symbol.TSAware ? WindowsInstallerConstants.MsidbCustomActionTypeTSAware : 0;
452 }
453
454 var row = this.CreateRow(symbol, "CustomAction");
455 row[0] = symbol.Id.Id;
456 row[1] = type;
457 row[2] = symbol.Source;
458 row[3] = symbol.Target;
459 row[4] = symbol.PatchUninstall ? (int?)WindowsInstallerConstants.MsidbCustomActionTypePatchUninstall : null;
460
461 if (OutputType.Module == this.Data.Type)
462 {
463 this.Data.EnsureTable(this.TableDefinitions["AdminExecuteSequence"]);
464 this.Data.EnsureTable(this.TableDefinitions["AdminUISequence"]);
465 this.Data.EnsureTable(this.TableDefinitions["AdvtExecuteSequence"]);
466 this.Data.EnsureTable(this.TableDefinitions["InstallExecuteSequence"]);
467 this.Data.EnsureTable(this.TableDefinitions["InstallUISequence"]);
468 }
469 }
470
471 private void AddDialogSymbol(DialogSymbol symbol)
472 {
473 var attributes = symbol.Visible ? WindowsInstallerConstants.MsidbDialogAttributesVisible : 0;
474 attributes |= symbol.Modal ? WindowsInstallerConstants.MsidbDialogAttributesModal : 0;
475 attributes |= symbol.Minimize ? WindowsInstallerConstants.MsidbDialogAttributesMinimize : 0;
476 attributes |= symbol.CustomPalette ? WindowsInstallerConstants.MsidbDialogAttributesUseCustomPalette : 0;
477 attributes |= symbol.ErrorDialog ? WindowsInstallerConstants.MsidbDialogAttributesError : 0;
478 attributes |= symbol.LeftScroll ? WindowsInstallerConstants.MsidbDialogAttributesLeftScroll : 0;
479 attributes |= symbol.KeepModeless ? WindowsInstallerConstants.MsidbDialogAttributesKeepModeless : 0;
480 attributes |= symbol.RightAligned ? WindowsInstallerConstants.MsidbDialogAttributesRightAligned : 0;
481 attributes |= symbol.RightToLeft ? WindowsInstallerConstants.MsidbDialogAttributesRTLRO : 0;
482 attributes |= symbol.SystemModal ? WindowsInstallerConstants.MsidbDialogAttributesSysModal : 0;
483 attributes |= symbol.TrackDiskSpace ? WindowsInstallerConstants.MsidbDialogAttributesTrackDiskSpace : 0;
484
485 var row = this.CreateRow(symbol, "Dialog");
486 row[0] = symbol.Id.Id;
487 row[1] = symbol.HCentering;
488 row[2] = symbol.VCentering;
489 row[3] = symbol.Width;
490 row[4] = symbol.Height;
491 row[5] = attributes;
492 row[6] = symbol.Title;
493 row[7] = symbol.FirstControlRef;
494 row[8] = symbol.DefaultControlRef;
495 row[9] = symbol.CancelControlRef;
496
497 this.Data.EnsureTable(this.TableDefinitions["ListBox"]);
498 }
499
500 private void AddDirectorySymbol(DirectorySymbol symbol)
501 {
502 (var name, var parentDir) = this.AddDirectorySubdirectories(symbol);
503
504 var shortName = symbol.ShortName;
505 var sourceShortname = symbol.SourceShortName;
506
507 if (String.IsNullOrEmpty(shortName) && name != null && name != "." && name != "SourceDir" && !this.BackendHelper.IsValidShortFilename(name, false))
508 {
509 shortName = this.CreateShortName(name, false, "Directory", symbol.ParentDirectoryRef);
510 }
511
512 if (String.IsNullOrEmpty(sourceShortname) && !String.IsNullOrEmpty(symbol.SourceName) && symbol.SourceName != "." && !this.BackendHelper.IsValidShortFilename(symbol.SourceName, false))
513 {
514 sourceShortname = this.CreateShortName(symbol.SourceName, false, "Directory", symbol.ParentDirectoryRef);
515 }
516
517 var sourceName = CreateMsiFilename(sourceShortname, symbol.SourceName);
518 var targetName = CreateMsiFilename(shortName, name);
519
520 if (String.IsNullOrEmpty(targetName))
521 {
522 targetName = ".";
523 }
524
525 var defaultDir = String.IsNullOrEmpty(sourceName) || sourceName == targetName ? targetName : targetName + ":" + sourceName;
526
527 var row = this.CreateRow(symbol, "Directory");
528 row[0] = symbol.Id.Id;
529 row[1] = parentDir;
530 row[2] = defaultDir;
531
532 if (OutputType.Module == this.Data.Type)
533 {
534 var directoryId = symbol.Id.Id;
535
536 if (WindowsInstallerStandard.IsStandardDirectory(directoryId))
537 {
538 // If the directory table contains references to standard windows folders
539 // mergemod.dll will add customactions to set the MSM directory to
540 // the same directory as the standard windows folder and will add references to
541 // custom action to all the standard sequence tables. A problem will occur
542 // if the MSI does not have these tables as mergemod.dll does not add these
543 // tables to the MSI if absent. This code adds the tables in case mergemod.dll
544 // needs them.
545 this.Data.EnsureTable(this.TableDefinitions["CustomAction"]);
546 this.Data.EnsureTable(this.TableDefinitions["AdminExecuteSequence"]);
547 this.Data.EnsureTable(this.TableDefinitions["AdminUISequence"]);
548 this.Data.EnsureTable(this.TableDefinitions["AdvtExecuteSequence"]);
549 this.Data.EnsureTable(this.TableDefinitions["InstallExecuteSequence"]);
550 this.Data.EnsureTable(this.TableDefinitions["InstallUISequence"]);
551 }
552 else
553 {
554 foreach (var standardDirectoryId in WindowsInstallerStandard.StandardDirectoryIds())
555 {
556 if (directoryId.StartsWith(standardDirectoryId, StringComparison.Ordinal))
557 {
558 this.Messaging.Write(WarningMessages.StandardDirectoryConflictInMergeModule(symbol.SourceLineNumbers, directoryId, standardDirectoryId));
559 }
560 }
561 }
562 }
563 }
564
565 private void AddDuplicateFileSymbol(DuplicateFileSymbol symbol)
566 {
567 var name = symbol.DestinationName;
568 if (null == symbol.DestinationShortName && null != name && !this.BackendHelper.IsValidShortFilename(name, false))
569 {
570 symbol.DestinationShortName = this.CreateShortName(name, true, "CopyFile", symbol.ComponentRef, symbol.FileRef);
571 }
572
573 var row = this.CreateRow(symbol, "DuplicateFile");
574 row[0] = symbol.Id.Id;
575 row[1] = symbol.ComponentRef;
576 row[2] = symbol.FileRef;
577 row[3] = CreateMsiFilename(symbol.DestinationShortName, symbol.DestinationName);
578 row[4] = symbol.DestinationFolder;
579 }
580
581 private void AddEnvironmentSymbol(EnvironmentSymbol symbol)
582 {
583 var action = String.Empty;
584 var system = symbol.System ? "*" : String.Empty;
585 var uninstall = symbol.Permanent ? String.Empty : "-";
586 var value = symbol.Value;
587
588 switch (symbol.Action)
589 {
590 case EnvironmentActionType.Create:
591 action = "+";
592 break;
593 case EnvironmentActionType.Set:
594 action = "=";
595 break;
596 case EnvironmentActionType.Remove:
597 action = "!";
598 break;
599 }
600
601 switch (symbol.Part)
602 {
603 case EnvironmentPartType.First:
604 value = String.Concat(value, symbol.Separator, "[~]");
605 break;
606 case EnvironmentPartType.Last:
607 value = String.Concat("[~]", symbol.Separator, value);
608 break;
609 }
610
611 var row = this.CreateRow(symbol, "Environment");
612 row[0] = symbol.Id.Id;
613 row[1] = String.Concat(action, uninstall, system, symbol.Name);
614 row[2] = value;
615 row[3] = symbol.ComponentRef;
616 }
617
618 private void AddErrorSymbol(ErrorSymbol symbol)
619 {
620 var row = this.CreateRow(symbol, "Error");
621 row[0] = Convert.ToInt32(symbol.Id.Id);
622 row[1] = symbol.Message;
623 }
624
625 private void AddFeatureSymbol(FeatureSymbol symbol)
626 {
627 var attributes = symbol.DisallowAbsent ? WindowsInstallerConstants.MsidbFeatureAttributesUIDisallowAbsent : 0;
628 attributes |= symbol.DisallowAdvertise ? WindowsInstallerConstants.MsidbFeatureAttributesDisallowAdvertise : 0;
629 attributes |= FeatureInstallDefault.FollowParent == symbol.InstallDefault ? WindowsInstallerConstants.MsidbFeatureAttributesFollowParent : 0;
630 attributes |= FeatureInstallDefault.Source == symbol.InstallDefault ? WindowsInstallerConstants.MsidbFeatureAttributesFavorSource : 0;
631 attributes |= FeatureTypicalDefault.Advertise == symbol.TypicalDefault ? WindowsInstallerConstants.MsidbFeatureAttributesFavorAdvertise : 0;
632
633 var row = this.CreateRow(symbol, "Feature");
634 row[0] = symbol.Id.Id;
635 row[1] = symbol.ParentFeatureRef;
636 row[2] = symbol.Title;
637 row[3] = symbol.Description;
638 row[4] = symbol.Display;
639 row[5] = symbol.Level;
640 row[6] = symbol.DirectoryRef;
641 row[7] = attributes;
642 }
643
644 private void AddFileSymbol(FileSymbol symbol)
645 {
646 var name = symbol.Name;
647 if (null == symbol.ShortName && null != name && !this.BackendHelper.IsValidShortFilename(name, false))
648 {
649 symbol.ShortName = this.CreateShortName(name, true, "File", symbol.DirectoryRef);
650
651 if (!this.GeneratedShortNames.TryGetValue(symbol.ShortName, out var potentialConflicts))
652 {
653 potentialConflicts = new List<FileSymbol>();
654 this.GeneratedShortNames.Add(symbol.ShortName, potentialConflicts);
655 }
656
657 potentialConflicts.Add(symbol);
658 }
659
660 var row = (FileRow)this.CreateRow(symbol, "File");
661 row.File = symbol.Id.Id;
662 row.Component = symbol.ComponentRef;
663 row.FileName = CreateMsiFilename(symbol.ShortName, name);
664 row.FileSize = symbol.FileSize;
665 row.Version = symbol.Version;
666 row.Language = symbol.Language;
667 row.Sequence = symbol.Sequence;
668 row.DiskId = symbol.DiskId ?? throw new InvalidDataException("FileSymbol.DiskId should have been initialized before creating WindowsInstallerData from IntermediateRepresentation.");
669 row.Source = symbol.Source.Path;
670
671 var previousSourceField = symbol.Fields[(int)FileSymbolFields.Source]?.PreviousValue;
672 row.PreviousSource = previousSourceField?.AsPath().Path;
673
674 var attributes = (symbol.Attributes & FileSymbolAttributes.Checksum) == FileSymbolAttributes.Checksum ? WindowsInstallerConstants.MsidbFileAttributesChecksum : 0;
675 attributes |= (symbol.Attributes & FileSymbolAttributes.Compressed) == FileSymbolAttributes.Compressed ? WindowsInstallerConstants.MsidbFileAttributesCompressed : 0;
676 attributes |= (symbol.Attributes & FileSymbolAttributes.Uncompressed) == FileSymbolAttributes.Uncompressed ? WindowsInstallerConstants.MsidbFileAttributesNoncompressed : 0;
677 attributes |= (symbol.Attributes & FileSymbolAttributes.Hidden) == FileSymbolAttributes.Hidden ? WindowsInstallerConstants.MsidbFileAttributesHidden : 0;
678 attributes |= (symbol.Attributes & FileSymbolAttributes.ReadOnly) == FileSymbolAttributes.ReadOnly ? WindowsInstallerConstants.MsidbFileAttributesReadOnly : 0;
679 attributes |= (symbol.Attributes & FileSymbolAttributes.System) == FileSymbolAttributes.System ? WindowsInstallerConstants.MsidbFileAttributesSystem : 0;
680 attributes |= (symbol.Attributes & FileSymbolAttributes.Vital) == FileSymbolAttributes.Vital ? WindowsInstallerConstants.MsidbFileAttributesVital : 0;
681 row.Attributes = attributes;
682
683 // Note that TrueType fonts are denoted by the empty string in the FontTitle
684 // field. So, non-null means a font is present.
685 if (symbol.FontTitle != null)
686 {
687 var fontRow = this.CreateRow(symbol, "Font");
688 fontRow[0] = symbol.Id.Id;
689 fontRow[1] = symbol.FontTitle;
690 }
691
692 if (symbol.SelfRegCost.HasValue)
693 {
694 var selfRegRow = this.CreateRow(symbol, "SelfReg");
695 selfRegRow[0] = symbol.Id.Id;
696 selfRegRow[1] = symbol.SelfRegCost.Value;
697 }
698 }
699
700 private void AddIniFileSymbol(IniFileSymbol symbol)
701 {
702 var tableName = (IniFileActionType.AddLine == symbol.Action || IniFileActionType.AddTag == symbol.Action || IniFileActionType.CreateLine == symbol.Action) ? "IniFile" : "RemoveIniFile";
703
704 var name = symbol.FileName;
705 if (null == symbol.ShortFileName && null != name && !this.BackendHelper.IsValidShortFilename(name, false))
706 {
707 symbol.ShortFileName = this.CreateShortName(name, true, "IniFile", symbol.ComponentRef);
708 }
709
710 var row = this.CreateRow(symbol, tableName);
711 row[0] = symbol.Id.Id;
712 row[1] = CreateMsiFilename(symbol.ShortFileName, name);
713 row[2] = symbol.DirProperty;
714 row[3] = symbol.Section;
715 row[4] = symbol.Key;
716 row[5] = symbol.Value;
717 row[6] = symbol.Action;
718 row[7] = symbol.ComponentRef;
719 }
720
721 private void AddIniLocatorSymbol(IniLocatorSymbol symbol)
722 {
723 var name = symbol.FileName;
724 if (null == symbol.ShortFileName && null != name && !this.BackendHelper.IsValidShortFilename(name, false))
725 {
726 symbol.ShortFileName = this.CreateShortName(name, true, "IniFileSearch");
727 }
728
729 var row = this.CreateRow(symbol, "IniLocator");
730 row[0] = symbol.Id.Id;
731 row[1] = CreateMsiFilename(symbol.ShortFileName, name);
732 row[2] = symbol.Section;
733 row[3] = symbol.Key;
734 row[4] = symbol.Field;
735 row[5] = symbol.Type;
736 }
737
738 private void AddMediaSymbol(MediaSymbol symbol)
739 {
740 if (this.Section.Type != SectionType.Module)
741 {
742 var row = (MediaRow)this.CreateRow(symbol, "Media");
743 row.DiskId = symbol.DiskId;
744 row.LastSequence = symbol.LastSequence ?? 0;
745 row.DiskPrompt = symbol.DiskPrompt;
746 row.Cabinet = symbol.Cabinet;
747 row.VolumeLabel = symbol.VolumeLabel;
748 row.Source = symbol.Source;
749 }
750 }
751
752 private void AddModuleConfigurationSymbol(ModuleConfigurationSymbol symbol)
753 {
754 var row = this.CreateRow(symbol, "ModuleConfiguration");
755 row[0] = symbol.Id.Id;
756 row[1] = symbol.Format;
757 row[2] = symbol.Type;
758 row[3] = symbol.ContextData;
759 row[4] = symbol.DefaultValue;
760 row[5] = (symbol.KeyNoOrphan ? WindowsInstallerConstants.MsidbMsmConfigurableOptionKeyNoOrphan : 0) |
761 (symbol.NonNullable ? WindowsInstallerConstants.MsidbMsmConfigurableOptionNonNullable : 0);
762 row[6] = symbol.DisplayName;
763 row[7] = symbol.Description;
764 row[8] = symbol.HelpLocation;
765 row[9] = symbol.HelpKeyword;
766 }
767
768 private void AddMsiEmbeddedUISymbol(MsiEmbeddedUISymbol symbol)
769 {
770 var attributes = symbol.EntryPoint ? WindowsInstallerConstants.MsidbEmbeddedUI : 0;
771 attributes |= symbol.SupportsBasicUI ? WindowsInstallerConstants.MsidbEmbeddedHandlesBasic : 0;
772
773 var row = this.CreateRow(symbol, "MsiEmbeddedUI");
774 row[0] = symbol.Id.Id;
775 row[1] = symbol.FileName;
776 row[2] = attributes;
777 row[3] = symbol.MessageFilter;
778 row[4] = symbol.Source;
779 }
780
781 private void AddMsiServiceConfigSymbol(MsiServiceConfigSymbol symbol)
782 {
783 var events = symbol.OnInstall ? WindowsInstallerConstants.MsidbServiceConfigEventInstall : 0;
784 events |= symbol.OnReinstall ? WindowsInstallerConstants.MsidbServiceConfigEventReinstall : 0;
785 events |= symbol.OnUninstall ? WindowsInstallerConstants.MsidbServiceConfigEventUninstall : 0;
786
787 var row = this.CreateRow(symbol, "MsiServiceConfig");
788 row[0] = symbol.Id.Id;
789 row[1] = symbol.Name;
790 row[2] = events;
791 row[3] = symbol.ConfigType;
792 row[4] = symbol.Argument;
793 row[5] = symbol.ComponentRef;
794 }
795
796 private void AddMsiServiceConfigFailureActionsSymbol(MsiServiceConfigFailureActionsSymbol symbol)
797 {
798 var events = symbol.OnInstall ? WindowsInstallerConstants.MsidbServiceConfigEventInstall : 0;
799 events |= symbol.OnReinstall ? WindowsInstallerConstants.MsidbServiceConfigEventReinstall : 0;
800 events |= symbol.OnUninstall ? WindowsInstallerConstants.MsidbServiceConfigEventUninstall : 0;
801
802 var row = this.CreateRow(symbol, "MsiServiceConfigFailureActions");
803 row[0] = symbol.Id.Id;
804 row[1] = symbol.Name;
805 row[2] = events;
806 row[3] = symbol.ResetPeriod.HasValue ? symbol.ResetPeriod : null;
807 row[4] = symbol.RebootMessage ?? "[~]";
808 row[5] = symbol.Command ?? "[~]";
809 row[6] = symbol.Actions;
810 row[7] = symbol.DelayActions;
811 row[8] = symbol.ComponentRef;
812 }
813
814 private void AddMoveFileSymbol(MoveFileSymbol symbol)
815 {
816 var name = symbol.DestinationName;
817 if (null == symbol.DestinationShortName && null != name && !this.BackendHelper.IsValidShortFilename(name, false))
818 {
819 symbol.DestinationShortName = this.CreateShortName(name, true, "MoveFile", symbol.ComponentRef);
820 }
821
822 var row = this.CreateRow(symbol, "MoveFile");
823 row[0] = symbol.Id.Id;
824 row[1] = symbol.ComponentRef;
825 row[2] = symbol.SourceName;
826 row[3] = CreateMsiFilename(symbol.DestinationShortName, symbol.DestinationName);
827 row[4] = symbol.SourceFolder;
828 row[5] = symbol.DestFolder;
829 row[6] = symbol.Delete ? WindowsInstallerConstants.MsidbMoveFileOptionsMove : 0;
830 }
831
832 private void AddPropertySymbol(PropertySymbol symbol)
833 {
834 if (String.IsNullOrEmpty(symbol.Value))
835 {
836 return;
837 }
838
839 var row = (PropertyRow)this.CreateRow(symbol, "Property");
840 row.Property = symbol.Id.Id;
841 row.Value = symbol.Value;
842 }
843
844 private void AddRemoveFileSymbol(RemoveFileSymbol symbol)
845 {
846 var name = symbol.FileName;
847 if (null == symbol.ShortFileName && null != name && !this.BackendHelper.IsValidShortFilename(name, false))
848 {
849 symbol.ShortFileName = this.CreateShortName(name, true, "RemoveFile", symbol.ComponentRef);
850 }
851
852 var installMode = symbol.OnInstall == true ? WindowsInstallerConstants.MsidbRemoveFileInstallModeOnInstall : 0;
853 installMode |= symbol.OnUninstall == true ? WindowsInstallerConstants.MsidbRemoveFileInstallModeOnRemove : 0;
854
855 var row = this.CreateRow(symbol, "RemoveFile");
856 row[0] = symbol.Id.Id;
857 row[1] = symbol.ComponentRef;
858 row[2] = CreateMsiFilename(symbol.ShortFileName, symbol.FileName);
859 row[3] = symbol.DirPropertyRef;
860 row[4] = installMode;
861 }
862
863 private void AddRegistrySymbol(RegistrySymbol symbol)
864 {
865 var value = symbol.Value;
866
867 switch (symbol.ValueType)
868 {
869 case RegistryValueType.Binary:
870 value = String.Concat("#x", value);
871 break;
872 case RegistryValueType.Expandable:
873 value = String.Concat("#%", value);
874 break;
875 case RegistryValueType.Integer:
876 value = String.Concat("#", value);
877 break;
878 case RegistryValueType.MultiString:
879 switch (symbol.ValueAction)
880 {
881 case RegistryValueActionType.Append:
882 value = String.Concat("[~]", value);
883 break;
884 case RegistryValueActionType.Prepend:
885 value = String.Concat(value, "[~]");
886 break;
887 case RegistryValueActionType.Write:
888 default:
889 if (null != value && -1 == value.IndexOf("[~]", StringComparison.Ordinal))
890 {
891 value = String.Format(CultureInfo.InvariantCulture, "[~]{0}[~]", value);
892 }
893 break;
894 }
895 break;
896 case RegistryValueType.String:
897 // escape the leading '#' character for string registry keys
898 if (null != value && value.StartsWith("#", StringComparison.Ordinal))
899 {
900 value = String.Concat("#", value);
901 }
902 break;
903 }
904
905 var row = this.CreateRow(symbol, "Registry");
906 row[0] = symbol.Id.Id;
907 row[1] = symbol.Root;
908 row[2] = symbol.Key;
909 row[3] = symbol.Name;
910 row[4] = value;
911 row[5] = symbol.ComponentRef;
912 }
913
914 private void AddRegLocatorSymbol(RegLocatorSymbol symbol)
915 {
916 var type = (int)symbol.Type;
917 type |= symbol.Win64 ? WindowsInstallerConstants.MsidbLocatorType64bit : 0;
918
919 var row = this.CreateRow(symbol, "RegLocator");
920 row[0] = symbol.Id.Id;
921 row[1] = symbol.Root;
922 row[2] = symbol.Key;
923 row[3] = symbol.Name;
924 row[4] = type;
925 }
926
927 private void AddRemoveRegistrySymbol(RemoveRegistrySymbol symbol)
928 {
929 if (symbol.Action == RemoveRegistryActionType.RemoveOnInstall)
930 {
931 var row = this.CreateRow(symbol, "RemoveRegistry");
932 row[0] = symbol.Id.Id;
933 row[1] = symbol.Root;
934 row[2] = symbol.Key;
935 row[3] = symbol.Name;
936 row[4] = symbol.ComponentRef;
937 }
938 else // Registry table is used to remove registry keys on uninstall.
939 {
940 var row = this.CreateRow(symbol, "Registry");
941 row[0] = symbol.Id.Id;
942 row[1] = symbol.Root;
943 row[2] = symbol.Key;
944 row[3] = symbol.Name;
945 row[5] = symbol.ComponentRef;
946 }
947 }
948
949 private void AddServiceControlSymbol(ServiceControlSymbol symbol)
950 {
951 var events = symbol.InstallRemove ? WindowsInstallerConstants.MsidbServiceControlEventDelete : 0;
952 events |= symbol.UninstallRemove ? WindowsInstallerConstants.MsidbServiceControlEventUninstallDelete : 0;
953 events |= symbol.InstallStart ? WindowsInstallerConstants.MsidbServiceControlEventStart : 0;
954 events |= symbol.UninstallStart ? WindowsInstallerConstants.MsidbServiceControlEventUninstallStart : 0;
955 events |= symbol.InstallStop ? WindowsInstallerConstants.MsidbServiceControlEventStop : 0;
956 events |= symbol.UninstallStop ? WindowsInstallerConstants.MsidbServiceControlEventUninstallStop : 0;
957
958 var row = this.CreateRow(symbol, "ServiceControl");
959 row[0] = symbol.Id.Id;
960 row[1] = symbol.Name;
961 row[2] = events;
962 row[3] = symbol.Arguments;
963 if (symbol.Wait.HasValue)
964 {
965 row[4] = symbol.Wait.Value ? 1 : 0;
966 }
967 row[5] = symbol.ComponentRef;
968 }
969
970 private void AddServiceInstallSymbol(ServiceInstallSymbol symbol)
971 {
972 var errorControl = (int)symbol.ErrorControl;
973 errorControl |= symbol.Vital ? WindowsInstallerConstants.MsidbServiceInstallErrorControlVital : 0;
974
975 var serviceType = (int)symbol.ServiceType;
976 serviceType |= symbol.Interactive ? WindowsInstallerConstants.MsidbServiceInstallInteractive : 0;
977
978 var row = this.CreateRow(symbol, "ServiceInstall");
979 row[0] = symbol.Id.Id;
980 row[1] = symbol.Name;
981 row[2] = symbol.DisplayName;
982 row[3] = serviceType;
983 row[4] = (int)symbol.StartType;
984 row[5] = errorControl;
985 row[6] = symbol.LoadOrderGroup;
986 row[7] = symbol.Dependencies;
987 row[8] = symbol.StartName;
988 row[9] = symbol.Password;
989 row[10] = symbol.Arguments;
990 row[11] = symbol.ComponentRef;
991 row[12] = symbol.Description;
992 }
993
994 private void AddShortcutSymbol(ShortcutSymbol symbol)
995 {
996 var name = symbol.Name;
997 if (null == symbol.ShortName && null != name && !this.BackendHelper.IsValidShortFilename(name, false))
998 {
999 symbol.ShortName = this.CreateShortName(name, true, "Shortcut", symbol.ComponentRef, symbol.DirectoryRef);
1000 }
1001
1002 var row = this.CreateRow(symbol, "Shortcut");
1003 row[0] = symbol.Id.Id;
1004 row[1] = symbol.DirectoryRef;
1005 row[2] = CreateMsiFilename(symbol.ShortName, name);
1006 row[3] = symbol.ComponentRef;
1007 row[4] = symbol.Target;
1008 row[5] = symbol.Arguments;
1009 row[6] = symbol.Description;
1010 row[7] = symbol.Hotkey;
1011 row[8] = symbol.IconRef;
1012 row[9] = symbol.IconIndex;
1013 row[10] = (int?)symbol.Show;
1014 row[11] = symbol.WorkingDirectory;
1015 row[12] = symbol.DisplayResourceDll;
1016 row[13] = symbol.DisplayResourceId;
1017 row[14] = symbol.DescriptionResourceDll;
1018 row[15] = symbol.DescriptionResourceId;
1019 }
1020
1021 private void AddTextStyleSymbol(TextStyleSymbol symbol)
1022 {
1023 var styleBits = symbol.Bold ? WindowsInstallerConstants.MsidbTextStyleStyleBitsBold : 0;
1024 styleBits |= symbol.Italic ? WindowsInstallerConstants.MsidbTextStyleStyleBitsItalic : 0;
1025 styleBits |= symbol.Strike ? WindowsInstallerConstants.MsidbTextStyleStyleBitsStrike : 0;
1026 styleBits |= symbol.Underline ? WindowsInstallerConstants.MsidbTextStyleStyleBitsUnderline : 0;
1027
1028 long? color = null;
1029
1030 if (symbol.Red.HasValue || symbol.Green.HasValue || symbol.Blue.HasValue)
1031 {
1032 color = symbol.Red ?? 0;
1033 color += (long)(symbol.Green ?? 0) * 256;
1034 color += (long)(symbol.Blue ?? 0) * 65536;
1035 }
1036
1037 var row = this.CreateRow(symbol, "TextStyle");
1038 row[0] = symbol.Id.Id;
1039 row[1] = symbol.FaceName;
1040 row[2] = symbol.Size;
1041 row[3] = color;
1042 row[4] = styleBits == 0 ? null : (int?)styleBits;
1043 }
1044
1045 private void AddUpgradeSymbol(UpgradeSymbol symbol)
1046 {
1047 if (this.CheckUpgradeVersion(symbol, symbol.VersionMin, out var changedVersion))
1048 {
1049 symbol.VersionMin = changedVersion;
1050 }
1051
1052 if (this.CheckUpgradeVersion(symbol, symbol.VersionMax, out changedVersion))
1053 {
1054 symbol.VersionMax = changedVersion;
1055 }
1056
1057 var row = (UpgradeRow)this.CreateRow(symbol, "Upgrade");
1058 row.UpgradeCode = symbol.UpgradeCode;
1059 row.VersionMin = symbol.VersionMin;
1060 row.VersionMax = symbol.VersionMax;
1061 row.Language = symbol.Language;
1062 row.Remove = symbol.Remove;
1063 row.ActionProperty = symbol.ActionProperty;
1064
1065 var attributes = symbol.MigrateFeatures ? WindowsInstallerConstants.MsidbUpgradeAttributesMigrateFeatures : 0;
1066 attributes |= symbol.OnlyDetect ? WindowsInstallerConstants.MsidbUpgradeAttributesOnlyDetect : 0;
1067 attributes |= symbol.IgnoreRemoveFailures ? WindowsInstallerConstants.MsidbUpgradeAttributesIgnoreRemoveFailure : 0;
1068 attributes |= symbol.VersionMinInclusive ? WindowsInstallerConstants.MsidbUpgradeAttributesVersionMinInclusive : 0;
1069 attributes |= symbol.VersionMaxInclusive ? WindowsInstallerConstants.MsidbUpgradeAttributesVersionMaxInclusive : 0;
1070 attributes |= symbol.ExcludeLanguages ? WindowsInstallerConstants.MsidbUpgradeAttributesLanguagesExclusive : 0;
1071 row.Attributes = attributes;
1072 }
1073
1074 private void AddWixActionSymbol(WixActionSymbol symbol)
1075 {
1076 // Get the table definition for the action (and ensure the proper table exists for a module).
1077 string sequenceTableName = null;
1078 switch (symbol.SequenceTable)
1079 {
1080 case SequenceTable.AdminExecuteSequence:
1081 if (OutputType.Module == this.Data.Type)
1082 {
1083 this.Data.EnsureTable(this.TableDefinitions["AdminExecuteSequence"]);
1084 sequenceTableName = "ModuleAdminExecuteSequence";
1085 }
1086 else
1087 {
1088 sequenceTableName = "AdminExecuteSequence";
1089 }
1090 break;
1091 case SequenceTable.AdminUISequence:
1092 if (OutputType.Module == this.Data.Type)
1093 {
1094 this.Data.EnsureTable(this.TableDefinitions["AdminUISequence"]);
1095 sequenceTableName = "ModuleAdminUISequence";
1096 }
1097 else
1098 {
1099 sequenceTableName = "AdminUISequence";
1100 }
1101 break;
1102 case SequenceTable.AdvertiseExecuteSequence:
1103 if (OutputType.Module == this.Data.Type)
1104 {
1105 this.Data.EnsureTable(this.TableDefinitions["AdvtExecuteSequence"]);
1106 sequenceTableName = "ModuleAdvtExecuteSequence";
1107 }
1108 else
1109 {
1110 sequenceTableName = "AdvtExecuteSequence";
1111 }
1112 break;
1113 case SequenceTable.InstallExecuteSequence:
1114 if (OutputType.Module == this.Data.Type)
1115 {
1116 this.Data.EnsureTable(this.TableDefinitions["InstallExecuteSequence"]);
1117 sequenceTableName = "ModuleInstallExecuteSequence";
1118 }
1119 else
1120 {
1121 sequenceTableName = "InstallExecuteSequence";
1122 }
1123 break;
1124 case SequenceTable.InstallUISequence:
1125 if (OutputType.Module == this.Data.Type)
1126 {
1127 this.Data.EnsureTable(this.TableDefinitions["InstallUISequence"]);
1128 sequenceTableName = "ModuleInstallUISequence";
1129 }
1130 else
1131 {
1132 sequenceTableName = "InstallUISequence";
1133 }
1134 break;
1135 }
1136
1137 // create the action sequence row in the output
1138 var row = this.CreateRow(symbol, sequenceTableName);
1139
1140 if (SectionType.Module == this.Section.Type)
1141 {
1142 row[0] = symbol.Action;
1143 if (symbol.Sequence.HasValue && symbol.Sequence.Value != 0)
1144 {
1145 row[1] = symbol.Sequence;
1146 }
1147 else
1148 {
1149 var after = (null == symbol.Before);
1150 row[2] = after ? symbol.After : symbol.Before;
1151 row[3] = after ? 1 : 0;
1152 }
1153 row[4] = symbol.Condition;
1154 }
1155 else
1156 {
1157 row[0] = symbol.Action;
1158 row[1] = symbol.Condition;
1159 row[2] = symbol.Sequence;
1160 }
1161 }
1162
1163 private void IndexCustomTableCellSymbol(WixCustomTableCellSymbol wixCustomTableCellSymbol, Dictionary<string, List<WixCustomTableCellSymbol>> cellsByTableAndRowId)
1164 {
1165 var tableAndRowId = wixCustomTableCellSymbol.TableRef + "/" + wixCustomTableCellSymbol.RowId;
1166 if (!cellsByTableAndRowId.TryGetValue(tableAndRowId, out var cells))
1167 {
1168 cells = new List<WixCustomTableCellSymbol>();
1169 cellsByTableAndRowId.Add(tableAndRowId, cells);
1170 }
1171
1172 cells.Add(wixCustomTableCellSymbol);
1173 }
1174
1175 private void AddIndexedCellSymbols(Dictionary<string, List<WixCustomTableCellSymbol>> cellsByTableAndRowId)
1176 {
1177 foreach (var rowOfCells in cellsByTableAndRowId.Values)
1178 {
1179 var firstCellSymbol = rowOfCells[0];
1180 var customTableDefinition = this.TableDefinitions[firstCellSymbol.TableRef];
1181
1182 if (customTableDefinition.Unreal)
1183 {
1184 continue;
1185 }
1186
1187 var customRow = this.CreateRow(firstCellSymbol, customTableDefinition);
1188 var customRowFieldsByColumnName = customRow.Fields.ToDictionary(f => f.Column.Name);
1189
1190 foreach (var cell in rowOfCells)
1191 {
1192 var data = cell.Data;
1193
1194 if (customRowFieldsByColumnName.TryGetValue(cell.ColumnRef, out var rowField))
1195 {
1196 if (!String.IsNullOrEmpty(data))
1197 {
1198 if (rowField.Column.Type == ColumnType.Number)
1199 {
1200 try
1201 {
1202 rowField.Data = Convert.ToInt32(data, CultureInfo.InvariantCulture);
1203 }
1204 catch (FormatException)
1205 {
1206 this.Messaging.Write(ErrorMessages.IllegalIntegerValue(cell.SourceLineNumbers, rowField.Column.Name, customTableDefinition.Name, data));
1207 }
1208 catch (OverflowException)
1209 {
1210 this.Messaging.Write(ErrorMessages.IllegalIntegerValue(cell.SourceLineNumbers, rowField.Column.Name, customTableDefinition.Name, data));
1211 }
1212 }
1213 else if (rowField.Column.Category == ColumnCategory.Identifier)
1214 {
1215 if (this.BackendHelper.IsValidIdentifier(data) || this.BackendHelper.IsValidBinderVariable(data) || ColumnCategory.Formatted == rowField.Column.Category)
1216 {
1217 rowField.Data = data;
1218 }
1219 else
1220 {
1221 this.Messaging.Write(ErrorMessages.IllegalIdentifier(cell.SourceLineNumbers, "Data", data));
1222 }
1223 }
1224 else
1225 {
1226 rowField.Data = data;
1227 }
1228 }
1229 }
1230 else
1231 {
1232 this.Messaging.Write(ErrorMessages.UnexpectedCustomTableColumn(cell.SourceLineNumbers, cell.ColumnRef));
1233 }
1234 }
1235
1236 for (var i = 0; i < customTableDefinition.Columns.Length; ++i)
1237 {
1238 if (!customTableDefinition.Columns[i].Nullable && (null == customRow.Fields[i].Data || 0 == customRow.Fields[i].Data.ToString().Length))
1239 {
1240 this.Messaging.Write(ErrorMessages.NoDataForColumn(firstCellSymbol.SourceLineNumbers, customTableDefinition.Columns[i].Name, customTableDefinition.Name));
1241 }
1242 }
1243 }
1244 }
1245
1246 private void AddWixEnsureTableSymbol(WixEnsureTableSymbol symbol)
1247 {
1248 try
1249 {
1250 var tableDefinition = this.TableDefinitions[symbol.Table];
1251 this.Data.EnsureTable(tableDefinition);
1252 }
1253 catch (WixMissingTableDefinitionException e)
1254 {
1255 this.Messaging.Write(e.Error);
1256 }
1257 }
1258
1259 private void AddWixModuleSymbol(WixModuleSymbol symbol)
1260 {
1261 if (!String.IsNullOrEmpty(symbol.Version) && this.BackendHelper.TryParseFourPartVersion(symbol.Version, out var version))
1262 {
1263 var row = this.CreateRow(symbol, "ModuleSignature");
1264 row[0] = symbol.ModuleId;
1265 row[1] = symbol.Language;
1266 row[2] = version;
1267 }
1268 else
1269 {
1270 this.Messaging.Write(WindowsInstallerBackendErrors.InvalidModuleVersion(symbol.SourceLineNumbers, symbol.Version));
1271 }
1272 }
1273
1274 private void AddWixPackageSymbol(WixPackageSymbol symbol)
1275 {
1276 // TODO: Remove the following from the compiler and do it here instead.
1277 //this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Global, "Manufacturer"), manufacturer, false, false, false, true);
1278 //this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Global, "ProductCode"), productCode, false, false, false, true);
1279 //this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Global, "ProductLanguage"), productLanguage, false, false, false, true);
1280 //this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Global, "ProductName"), this.activeName, false, false, false, true);
1281 //this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Global, "ProductVersion"), version, false, false, false, true);
1282 //if (null != upgradeCode)
1283 //{
1284 // this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Global, "UpgradeCode"), upgradeCode, false, false, false, true);
1285 //}
1286
1287 //if (isPerMachine)
1288 //{
1289 // this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Global, "ALLUSERS"), "1", false, false, false, false);
1290 //}
1291 }
1292
1293 private bool AddSymbolFromExtension(IntermediateSymbol symbol)
1294 {
1295 foreach (var extension in this.BackendExtensions)
1296 {
1297 if (extension.TryProcessSymbol(this.Section, symbol, this.Data, this.TableDefinitions))
1298 {
1299 return true;
1300 }
1301 }
1302
1303 return false;
1304 }
1305
1306 private bool AddSymbolDefaultly(IntermediateSymbol symbol)
1307 {
1308 return this.BackendHelper.TryAddSymbolToMatchingTableDefinitions(this.Section, symbol, this.Data, this.TableDefinitions);
1309 }
1310
1311 private void EnsureModuleIgnoredTable(IntermediateSymbol symbol, string ignoredTable)
1312 {
1313 var tableDefinition = this.TableDefinitions["ModuleIgnoreTable"];
1314 var table = this.Data.EnsureTable(tableDefinition);
1315 if (!table.Rows.Any(r => r.FieldAsString(0) == ignoredTable))
1316 {
1317 var row = this.CreateRow(symbol, tableDefinition);
1318 row[0] = ignoredTable;
1319 }
1320 }
1321
1322 private (string, string) AddDirectorySubdirectories(DirectorySymbol symbol)
1323 {
1324 var directory = symbol.Name.Trim(PathSeparatorChars);
1325 var parentDir = symbol.ParentDirectoryRef ?? (symbol.Id.Id == "TARGETDIR" ? null : "TARGETDIR");
1326 var directoryRows = this.Data.TryGetTable("Directory", out var table) ? table.Rows.ToDictionary(row => row.FieldAsString(0)) : new Dictionary<string, Row>();
1327
1328 var start = 0;
1329 var end = directory.IndexOfAny(PathSeparatorChars);
1330 var path = String.Empty;
1331
1332 while (start <= end)
1333 {
1334 var subdirectoryName = directory.Substring(start, end - start);
1335
1336 if (!String.IsNullOrEmpty(subdirectoryName))
1337 {
1338 path = Path.Combine(path, subdirectoryName);
1339
1340 var id = this.BackendHelper.GenerateIdentifier("d", symbol.ParentDirectoryRef, path);
1341 var shortnameSubdirectory = this.BackendHelper.IsValidShortFilename(subdirectoryName, false) ? null : this.CreateShortName(subdirectoryName, false, "Directory", symbol.ParentDirectoryRef);
1342
1343 if (!directoryRows.ContainsKey(id))
1344 {
1345 var subdirectoryRow = this.CreateRow(symbol, "Directory");
1346 subdirectoryRow[0] = id;
1347 subdirectoryRow[1] = parentDir;
1348 subdirectoryRow[2] = CreateMsiFilename(shortnameSubdirectory, subdirectoryName);
1349
1350 directoryRows.Add(id, subdirectoryRow);
1351 }
1352
1353 parentDir = id;
1354 }
1355
1356 start = end + 1;
1357 end = symbol.Name.IndexOfAny(PathSeparatorChars, start);
1358 }
1359
1360 var name = (start == 0) ? directory : directory.Substring(start);
1361
1362 return (name, parentDir);
1363 }
1364
1365 private void EnsureRequiredTables()
1366 {
1367 // check for missing table and add them or display an error as appropriate
1368 switch (this.Data.Type)
1369 {
1370 case OutputType.Module:
1371 this.Data.EnsureTable(this.TableDefinitions["Component"]);
1372 this.Data.EnsureTable(this.TableDefinitions["Directory"]);
1373 this.Data.EnsureTable(this.TableDefinitions["FeatureComponents"]);
1374 this.Data.EnsureTable(this.TableDefinitions["File"]);
1375 this.Data.EnsureTable(this.TableDefinitions["ModuleComponents"]);
1376 this.Data.EnsureTable(this.TableDefinitions["ModuleSignature"]);
1377 break;
1378
1379 case OutputType.PatchCreation:
1380 var imageFamiliesCount = this.Data.Tables["ImageFamilies"]?.Rows.Count ?? 0;
1381 var targetImagesCount = this.Data.Tables["TargetImages"]?.Rows.Count ?? 0;
1382 var upgradedImagesCount = this.Data.Tables["UpgradedImages"]?.Rows.Count ?? 0;
1383
1384 if (imageFamiliesCount < 1)
1385 {
1386 this.Messaging.Write(ErrorMessages.ExpectedRowInPatchCreationPackage("ImageFamilies"));
1387 }
1388
1389 if (targetImagesCount < 1)
1390 {
1391 this.Messaging.Write(ErrorMessages.ExpectedRowInPatchCreationPackage("TargetImages"));
1392 }
1393
1394 if (upgradedImagesCount < 1)
1395 {
1396 this.Messaging.Write(ErrorMessages.ExpectedRowInPatchCreationPackage("UpgradedImages"));
1397 }
1398
1399 this.Data.EnsureTable(this.TableDefinitions["Properties"]);
1400 break;
1401
1402 case OutputType.Package:
1403 this.Data.EnsureTable(this.TableDefinitions["File"]);
1404 this.Data.EnsureTable(this.TableDefinitions["Media"]);
1405 break;
1406 }
1407 }
1408
1409 private void ReportGeneratedShortFileNameConflicts()
1410 {
1411 foreach (var conflicts in this.GeneratedShortNames.Values.Where(l => l.Count > 1))
1412 {
1413 this.Messaging.Write(WarningMessages.GeneratedShortFileNameConflict(conflicts[0].SourceLineNumbers, conflicts[0].ShortName));
1414 for (var i = 1; i < conflicts.Count; ++i)
1415 {
1416 this.Messaging.Write(WarningMessages.GeneratedShortFileNameConflict2(conflicts[i].SourceLineNumbers));
1417 }
1418 }
1419 }
1420
1421 private void ReportIllegalTables()
1422 {
1423 foreach (var table in this.Data.Tables)
1424 {
1425 switch (this.Data.Type)
1426 {
1427 case OutputType.Module:
1428 if ("BBControl" == table.Name ||
1429 "Billboard" == table.Name ||
1430 "CCPSearch" == table.Name ||
1431 "Feature" == table.Name ||
1432 "LaunchCondition" == table.Name ||
1433 "Media" == table.Name ||
1434 "Patch" == table.Name ||
1435 "Upgrade" == table.Name ||
1436 "WixMerge" == table.Name)
1437 {
1438 foreach (Row row in table.Rows)
1439 {
1440 this.Messaging.Write(ErrorMessages.UnexpectedTableInMergeModule(row.SourceLineNumbers, table.Name));
1441 }
1442 }
1443 else if ("Error" == table.Name)
1444 {
1445 foreach (var row in table.Rows)
1446 {
1447 this.Messaging.Write(WarningMessages.DangerousTableInMergeModule(row.SourceLineNumbers, table.Name));
1448 }
1449 }
1450 else if (31 < table.Name.Length)
1451 {
1452 foreach (var row in table.Rows)
1453 {
1454 this.Messaging.Write(ErrorMessages.OverlengthTableNameInProductOrMergeModule(row.SourceLineNumbers, table.Name));
1455 }
1456 }
1457 break;
1458
1459 case OutputType.PatchCreation:
1460 if (!table.Definition.Unreal &&
1461 "_SummaryInformation" != table.Name &&
1462 "ExternalFiles" != table.Name &&
1463 "FamilyFileRanges" != table.Name &&
1464 "ImageFamilies" != table.Name &&
1465 "PatchMetadata" != table.Name &&
1466 "PatchSequence" != table.Name &&
1467 "Properties" != table.Name &&
1468 "TargetFiles_OptionalData" != table.Name &&
1469 "TargetImages" != table.Name &&
1470 "UpgradedFiles_OptionalData" != table.Name &&
1471 "UpgradedFilesToIgnore" != table.Name &&
1472 "UpgradedImages" != table.Name)
1473 {
1474 foreach (var row in table.Rows)
1475 {
1476 this.Messaging.Write(ErrorMessages.UnexpectedTableInPatchCreationPackage(row.SourceLineNumbers, table.Name));
1477 }
1478 }
1479 break;
1480
1481 case OutputType.Patch:
1482 if (!table.Definition.Unreal &&
1483 "_SummaryInformation" != table.Name &&
1484 "Media" != table.Name &&
1485 "MsiFileHash" != table.Name &&
1486 "MsiPatchMetadata" != table.Name &&
1487 "MsiPatchSequence" != table.Name)
1488 {
1489 foreach (var row in table.Rows)
1490 {
1491 this.Messaging.Write(ErrorMessages.UnexpectedTableInPatch(row.SourceLineNumbers, table.Name));
1492 }
1493 }
1494 break;
1495
1496 case OutputType.Package:
1497 if ("ModuleAdminExecuteSequence" == table.Name ||
1498 "ModuleAdminUISequence" == table.Name ||
1499 "ModuleAdvtExecuteSequence" == table.Name ||
1500 "ModuleAdvtUISequence" == table.Name ||
1501 "ModuleComponents" == table.Name ||
1502 "ModuleConfiguration" == table.Name ||
1503 "ModuleDependency" == table.Name ||
1504 "ModuleExclusion" == table.Name ||
1505 "ModuleIgnoreTable" == table.Name ||
1506 "ModuleInstallExecuteSequence" == table.Name ||
1507 "ModuleInstallUISequence" == table.Name ||
1508 "ModuleSignature" == table.Name ||
1509 "ModuleSubstitution" == table.Name)
1510 {
1511 foreach (var row in table.Rows)
1512 {
1513 this.Messaging.Write(WarningMessages.UnexpectedTableInProduct(row.SourceLineNumbers, table.Name));
1514 }
1515 }
1516 else if (31 < table.Name.Length)
1517 {
1518 foreach (var row in table.Rows)
1519 {
1520 this.Messaging.Write(ErrorMessages.OverlengthTableNameInProductOrMergeModule(row.SourceLineNumbers, table.Name));
1521 }
1522 }
1523 break;
1524 }
1525 }
1526 }
1527
1528 private void ReportMismatchedModularizations()
1529 {
1530 // verify that modularization types match for foreign key relationships
1531 foreach (var tableDefinition in this.TableDefinitions)
1532 {
1533 foreach (var columnDefinition in tableDefinition.Columns)
1534 {
1535 if (null != columnDefinition.KeyTable && 0 > columnDefinition.KeyTable.IndexOf(';') && columnDefinition.KeyColumn.HasValue)
1536 {
1537 if (this.TableDefinitions.TryGet(columnDefinition.KeyTable, out var keyTableDefinition))
1538 {
1539 var keyColumnIndex = columnDefinition.KeyColumn ?? -1;
1540
1541 if (keyColumnIndex <= 0 || keyColumnIndex > keyTableDefinition.Columns.Length)
1542 {
1543 this.Messaging.Write(ErrorMessages.InvalidKeyColumn(tableDefinition.Name, columnDefinition.Name, columnDefinition.KeyTable, keyColumnIndex));
1544 }
1545 else if (keyTableDefinition.Columns[keyColumnIndex - 1].ModularizeType != columnDefinition.ModularizeType && ColumnModularizeType.CompanionFile != columnDefinition.ModularizeType)
1546 {
1547 this.Messaging.Write(WarningMessages.CollidingModularizationTypes(tableDefinition.Name, columnDefinition.Name, columnDefinition.KeyTable, keyColumnIndex, columnDefinition.ModularizeType.ToString(), keyTableDefinition.Columns[keyColumnIndex - 1].ModularizeType.ToString()));
1548 }
1549 }
1550 // else - ignore missing table definitions as that error is caught in other places
1551 }
1552 }
1553 }
1554 }
1555
1556 private void ReportWindowsInstallerDataInconsistencies()
1557 {
1558 // Get the output's minimum installer version
1559 var outputInstallerVersion = Int32.MaxValue;
1560
1561 if (this.Data.Tables.TryGetTable("_SummaryInformation", out var summaryInformationTable))
1562 {
1563 outputInstallerVersion = summaryInformationTable.Rows.FirstOrDefault(r => 14 == r.FieldAsInteger(0))?.FieldAsInteger(1) ?? Int32.MaxValue;
1564 }
1565
1566 // Ensure the Error table exists if output is marked for MSI 1.0 or below (see ICE40).
1567 if (outputInstallerVersion <= 100 && OutputType.Package == this.Data.Type)
1568 {
1569 this.Data.EnsureTable(this.TableDefinitions["Error"]);
1570 }
1571
1572 // Check for the presence of tables/rows/columns that require MSI 1.1 or later.
1573 if (outputInstallerVersion < 110)
1574 {
1575 if (this.Data.Tables.TryGetTable("IsolatedComponent", out var isolatedComponentTable))
1576 {
1577 foreach (var row in isolatedComponentTable.Rows)
1578 {
1579 this.Messaging.Write(WarningMessages.TableIncompatibleWithInstallerVersion(row.SourceLineNumbers, "IsolatedComponent", outputInstallerVersion));
1580 }
1581 }
1582 }
1583
1584 // Check for the presence of tables/rows/columns that require MSI 4.0 or later
1585 if (outputInstallerVersion < 400)
1586 {
1587 if (this.Data.Tables.TryGetTable("Shortcut", out var shortcutTable))
1588 {
1589 foreach (var row in shortcutTable.Rows)
1590 {
1591 if (null != row[12] || null != row[13] || null != row[14] || null != row[15])
1592 {
1593 this.Messaging.Write(WarningMessages.ColumnsIncompatibleWithInstallerVersion(row.SourceLineNumbers, "Shortcut", outputInstallerVersion));
1594 }
1595 }
1596 }
1597 }
1598 }
1599
1600 private static OutputType SectionTypeToOutputType(SectionType type)
1601 {
1602 switch (type)
1603 {
1604 case SectionType.Bundle:
1605 return OutputType.Bundle;
1606 case SectionType.Module:
1607 return OutputType.Module;
1608 case SectionType.Package:
1609 return OutputType.Package;
1610 case SectionType.PatchCreation:
1611 return OutputType.PatchCreation;
1612 case SectionType.Patch:
1613 return OutputType.Patch;
1614
1615 default:
1616 throw new ArgumentOutOfRangeException(nameof(type));
1617 }
1618 }
1619
1620 private Row CreateRow(IntermediateSymbol symbol, string tableDefinitionName)
1621 {
1622 return this.CreateRow(symbol, this.TableDefinitions[tableDefinitionName]);
1623 }
1624
1625 private Row CreateRow(IntermediateSymbol symbol, TableDefinition tableDefinition)
1626 {
1627 return this.BackendHelper.CreateRow(this.Section, symbol, this.Data, tableDefinition);
1628 }
1629
1630 private bool CheckUpgradeVersion(UpgradeSymbol symbol, string version, out string changedVersion)
1631 {
1632 if (String.IsNullOrEmpty(version))
1633 {
1634 // Null is allowed.
1635 }
1636 else if (this.BackendHelper.TryParseMsiProductVersion(version, strict: false, out var parsedVersionMin))
1637 {
1638 // If the strictly parsed value is different, update the symbol.
1639 if (version != parsedVersionMin)
1640 {
1641 changedVersion = parsedVersionMin;
1642 return true;
1643 }
1644 }
1645 else
1646 {
1647 this.Messaging.Write(WarningMessages.InvalidMsiProductVersion(symbol.SourceLineNumbers, version));
1648 }
1649
1650 changedVersion = null;
1651 return false;
1652 }
1653
1654 private string CreateShortName(string longName, bool keepExtension, params string[] args)
1655 {
1656 longName = longName.ToLowerInvariant();
1657
1658 // collect all the data
1659 var strings = new List<string>(1 + args.Length);
1660 strings.Add(longName);
1661 strings.AddRange(args);
1662
1663 // prepare for hashing
1664 var stringData = String.Join("|", strings);
1665 var data = Encoding.UTF8.GetBytes(stringData);
1666
1667 // hash the data
1668 byte[] hash;
1669 using (var sha1 = new SHA1CryptoServiceProvider())
1670 {
1671 hash = sha1.ComputeHash(data);
1672 }
1673
1674 // generate the short file/directory name without an extension
1675 var shortName = new StringBuilder(Convert.ToBase64String(hash));
1676 shortName.Length = 8;
1677 shortName.Replace('+', '-').Replace('/', '_');
1678
1679 if (keepExtension)
1680 {
1681 var extension = Path.GetExtension(longName);
1682
1683 if (4 < extension.Length)
1684 {
1685 extension = extension.Substring(0, 4);
1686 }
1687
1688 shortName.Append(extension);
1689
1690 // check the generated short name to ensure its still legal (the extension may not be legal)
1691 if (!this.BackendHelper.IsValidShortFilename(shortName.ToString(), false))
1692 {
1693 // remove the extension (by truncating the generated file name back to the generated characters)
1694 shortName.Length -= extension.Length;
1695 }
1696 }
1697
1698 return shortName.ToString().ToLowerInvariant();
1699 }
1700
1701 private static string CreateMsiFilename(string shortName, string longName)
1702 {
1703 if (String.IsNullOrEmpty(shortName) || String.Equals(shortName, longName, StringComparison.OrdinalIgnoreCase))
1704 {
1705 return longName;
1706 }
1707 else
1708 {
1709 return shortName + "|" + longName;
1710 }
1711 }
1712 }
1713 }