aboutsummaryrefslogtreecommitdiff
path: root/src/WixToolset.Core.WindowsInstaller/Decompiler.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/WixToolset.Core.WindowsInstaller/Decompiler.cs')
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Decompiler.cs9357
1 files changed, 9357 insertions, 0 deletions
diff --git a/src/WixToolset.Core.WindowsInstaller/Decompiler.cs b/src/WixToolset.Core.WindowsInstaller/Decompiler.cs
new file mode 100644
index 00000000..d353cc16
--- /dev/null
+++ b/src/WixToolset.Core.WindowsInstaller/Decompiler.cs
@@ -0,0 +1,9357 @@
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
4{
5 using System;
6 using System.Collections;
7 using System.Collections.Generic;
8 using System.Collections.Specialized;
9 using System.Diagnostics.CodeAnalysis;
10 using System.Globalization;
11 using System.IO;
12 using System.Text;
13 using System.Text.RegularExpressions;
14 using WixToolset.Data;
15 using WixToolset.Data.Rows;
16 using WixToolset.Extensibility;
17 using WixToolset.Core.Native;
18 using Wix = WixToolset.Data.Serialize;
19 using WixToolset.Core;
20
21 /// <summary>
22 /// Decompiles an msi database into WiX source.
23 /// </summary>
24 public class Decompiler
25 {
26 private static readonly Regex NullSplitter = new Regex(@"\[~]");
27#if TODO
28 private int codepage;
29 private bool compressed;
30 private bool shortNames;
31 private DecompilerCore core;
32 private string exportFilePath;
33 private List<IDecompilerExtension> extensions;
34 private Dictionary<string, IDecompilerExtension> extensionsByTableName;
35 private string modularizationGuid;
36 private OutputType outputType;
37 private Hashtable patchTargetFiles;
38 private Hashtable sequenceElements;
39 private bool showPedanticMessages;
40 private WixActionRowCollection standardActions;
41 private bool suppressCustomTables;
42 private bool suppressDroppingEmptyTables;
43 private bool suppressRelativeActionSequencing;
44 private bool suppressUI;
45 private TableDefinitionCollection tableDefinitions;
46 // private TempFileCollection tempFiles;
47 private bool treatProductAsModule;
48
49 /// <summary>
50 /// Creates a new decompiler object with a default set of table definitions.
51 /// </summary>
52 public Decompiler()
53 {
54 this.standardActions = WindowsInstallerStandard.GetStandardActions();
55
56 this.extensions = new List<IDecompilerExtension>();
57 this.extensionsByTableName = new Dictionary<string,IDecompilerExtension>();
58 this.patchTargetFiles = new Hashtable();
59 this.sequenceElements = new Hashtable();
60 this.tableDefinitions = new TableDefinitionCollection();
61 this.exportFilePath = "SourceDir";
62 }
63
64 /// <summary>
65 /// Gets or sets the base source file path.
66 /// </summary>
67 /// <value>Base source file path.</value>
68 public string ExportFilePath
69 {
70 get { return this.exportFilePath; }
71 set { this.exportFilePath = value; }
72 }
73
74 /// <summary>
75 /// Gets or sets the option to show pedantic messages.
76 /// </summary>
77 /// <value>The option to show pedantic messages.</value>
78 public bool ShowPedanticMessages
79 {
80 get { return this.showPedanticMessages; }
81 set { this.showPedanticMessages = value; }
82 }
83
84 /// <summary>
85 /// Gets or sets the option to suppress custom tables.
86 /// </summary>
87 /// <value>The option to suppress dropping empty tables.</value>
88 public bool SuppressCustomTables
89 {
90 get { return this.suppressCustomTables; }
91 set { this.suppressCustomTables = value; }
92 }
93
94 /// <summary>
95 /// Gets or sets the option to suppress dropping empty tables.
96 /// </summary>
97 /// <value>The option to suppress dropping empty tables.</value>
98 public bool SuppressDroppingEmptyTables
99 {
100 get { return this.suppressDroppingEmptyTables; }
101 set { this.suppressDroppingEmptyTables = value; }
102 }
103
104 /// <summary>
105 /// Gets or sets the option to suppress decompiling with relative action sequencing (uses sequence numbers).
106 /// </summary>
107 /// <value>The option to suppress decompiling with relative action sequencing (uses sequence numbers).</value>
108 public bool SuppressRelativeActionSequencing
109 {
110 get { return this.suppressRelativeActionSequencing; }
111 set { this.suppressRelativeActionSequencing = value; }
112 }
113
114 /// <summary>
115 /// Gets or sets the option to suppress decompiling UI-related tables.
116 /// </summary>
117 /// <value>The option to suppress decompiling UI-related tables.</value>
118 public bool SuppressUI
119 {
120 get { return this.suppressUI; }
121 set { this.suppressUI = value; }
122 }
123
124 /// <summary>
125 /// Gets or sets the temporary path for the Decompiler. If left null, the decompiler
126 /// will use %TEMP% environment variable.
127 /// </summary>
128 /// <value>Path to temp files.</value>
129 public string TempFilesLocation
130 {
131 get
132 {
133 // return null == this.tempFiles ? String.Empty : this.tempFiles.BasePath;
134 return Path.GetTempPath();
135 }
136
137 // set
138 // {
139 // if (null == value)
140 // {
141 // this.tempFiles = new TempFileCollection();
142 // }
143 // else
144 // {
145 // this.tempFiles = new TempFileCollection(value);
146 // }
147 // }
148 }
149
150 /// <summary>
151 /// Gets or sets whether the decompiler should use module logic on a product output.
152 /// </summary>
153 /// <value>The option to treat a product like a module</value>
154 public bool TreatProductAsModule
155 {
156 get { return this.treatProductAsModule; }
157 set { this.treatProductAsModule = value; }
158 }
159
160 /// <summary>
161 /// Decompile the database file.
162 /// </summary>
163 /// <param name="output">The output to decompile.</param>
164 /// <returns>The serialized WiX source code.</returns>
165 [SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters", MessageId = "System.InvalidOperationException.#ctor(System.String)")]
166 public Wix.Wix Decompile(Output output)
167 {
168 if (null == output)
169 {
170 throw new ArgumentNullException("output");
171 }
172
173 this.codepage = output.Codepage;
174 this.outputType = output.Type;
175
176 // collect the table definitions from the output
177 this.tableDefinitions.Clear();
178 foreach (Table table in output.Tables)
179 {
180 this.tableDefinitions.Add(table.Definition);
181 }
182
183 // add any missing standard and wix-specific table definitions
184 foreach (TableDefinition tableDefinition in WindowsInstallerStandard.GetTableDefinitions())
185 {
186 if (!this.tableDefinitions.Contains(tableDefinition.Name))
187 {
188 this.tableDefinitions.Add(tableDefinition);
189 }
190 }
191
192 // add any missing extension table definitions
193 foreach (IDecompilerExtension extension in this.extensions)
194 {
195 if (null != extension.TableDefinitions)
196 {
197 foreach (TableDefinition tableDefinition in extension.TableDefinitions)
198 {
199 if (!this.tableDefinitions.Contains(tableDefinition.Name))
200 {
201 this.tableDefinitions.Add(tableDefinition);
202 }
203 }
204 }
205 }
206
207 // if we don't have the temporary files object yet, get one
208#if REDO_IN_NETCORE
209 if (null == this.tempFiles)
210 {
211 this.TempFilesLocation = null;
212 }
213#endif
214 Directory.CreateDirectory(this.TempFilesLocation); // ensure the base path is there
215
216 bool encounteredError = false;
217 Wix.IParentElement rootElement;
218 Wix.Wix wixElement = new Wix.Wix();
219
220 switch (this.outputType)
221 {
222 case OutputType.Module:
223 rootElement = new Wix.Module();
224 break;
225 case OutputType.PatchCreation:
226 rootElement = new Wix.PatchCreation();
227 break;
228 case OutputType.Product:
229 rootElement = new Wix.Product();
230 break;
231 default:
232 throw new InvalidOperationException(WixStrings.EXP_UnknownOutputType);
233 }
234 wixElement.AddChild((Wix.ISchemaElement)rootElement);
235
236 // try to decompile the database file
237 try
238 {
239 this.core = new DecompilerCore(rootElement);
240 this.core.ShowPedanticMessages = this.showPedanticMessages;
241
242 // stop processing if an error previously occurred
243 if (this.core.EncounteredError)
244 {
245 return null;
246 }
247
248 // initialize the decompiler and its extensions
249 foreach (IDecompilerExtension extension in this.extensions)
250 {
251 extension.Core = this.core;
252 extension.Initialize(output.Tables);
253 }
254 this.InitializeDecompile(output.Tables);
255
256 // stop processing if an error previously occurred
257 if (this.core.EncounteredError)
258 {
259 return null;
260 }
261
262 // decompile the tables
263 this.DecompileTables(output);
264
265 // finalize the decompiler and its extensions
266 this.FinalizeDecompile(output.Tables);
267 foreach (IDecompilerExtension extension in this.extensions)
268 {
269 extension.Finish(output.Tables);
270 }
271 }
272 finally
273 {
274 encounteredError = this.core.EncounteredError;
275
276 this.core = null;
277 foreach (IDecompilerExtension extension in this.extensions)
278 {
279 extension.Core = null;
280 }
281 }
282
283 // return the root element only if decompilation completed successfully
284 return (encounteredError ? null : wixElement);
285 }
286
287 /// <summary>
288 /// Adds an extension.
289 /// </summary>
290 /// <param name="extension">The extension to add.</param>
291 public void AddExtension(IDecompilerExtension extension)
292 {
293 this.extensions.Add(extension);
294
295 if (null != extension.TableDefinitions)
296 {
297 foreach (TableDefinition tableDefinition in extension.TableDefinitions)
298 {
299 if (!this.extensionsByTableName.ContainsKey(tableDefinition.Name))
300 {
301 this.extensionsByTableName.Add(tableDefinition.Name, extension);
302 }
303 else
304 {
305 Messaging.Instance.OnMessage(WixErrors.DuplicateExtensionTable(extension.GetType().ToString(), tableDefinition.Name));
306 }
307 }
308 }
309 }
310
311 /// <summary>
312 /// Cleans up the temp files used by the Decompiler.
313 /// </summary>
314 /// <returns>True if all files were deleted, false otherwise.</returns>
315 /// <remarks>
316 /// This should be called after every call to Decompile to ensure there
317 /// are no conflicts between each decompiled database.
318 /// </remarks>
319 public bool DeleteTempFiles()
320 {
321#if REDO_IN_NETCORE
322 if (null == this.tempFiles)
323 {
324 return true; // no work to do
325 }
326 else
327 {
328 bool deleted = Common.DeleteTempFiles(this.tempFiles.BasePath, this.core);
329
330 if (deleted)
331 {
332 this.tempFiles = null; // temp files have been deleted, no need to remember this now
333 }
334
335 return deleted;
336 }
337#endif
338 return true;
339 }
340
341 /// <summary>
342 /// Set the common control attributes in a control element.
343 /// </summary>
344 /// <param name="attributes">The control attributes.</param>
345 /// <param name="control">The control element.</param>
346 private static void SetControlAttributes(int attributes, Wix.Control control)
347 {
348 if (0 == (attributes & MsiInterop.MsidbControlAttributesEnabled))
349 {
350 control.Disabled = Wix.YesNoType.yes;
351 }
352
353 if (MsiInterop.MsidbControlAttributesIndirect == (attributes & MsiInterop.MsidbControlAttributesIndirect))
354 {
355 control.Indirect = Wix.YesNoType.yes;
356 }
357
358 if (MsiInterop.MsidbControlAttributesInteger == (attributes & MsiInterop.MsidbControlAttributesInteger))
359 {
360 control.Integer = Wix.YesNoType.yes;
361 }
362
363 if (MsiInterop.MsidbControlAttributesLeftScroll == (attributes & MsiInterop.MsidbControlAttributesLeftScroll))
364 {
365 control.LeftScroll = Wix.YesNoType.yes;
366 }
367
368 if (MsiInterop.MsidbControlAttributesRightAligned == (attributes & MsiInterop.MsidbControlAttributesRightAligned))
369 {
370 control.RightAligned = Wix.YesNoType.yes;
371 }
372
373 if (MsiInterop.MsidbControlAttributesRTLRO == (attributes & MsiInterop.MsidbControlAttributesRTLRO))
374 {
375 control.RightToLeft = Wix.YesNoType.yes;
376 }
377
378 if (MsiInterop.MsidbControlAttributesSunken == (attributes & MsiInterop.MsidbControlAttributesSunken))
379 {
380 control.Sunken = Wix.YesNoType.yes;
381 }
382
383 if (0 == (attributes & MsiInterop.MsidbControlAttributesVisible))
384 {
385 control.Hidden = Wix.YesNoType.yes;
386 }
387 }
388
389 /// <summary>
390 /// Creates an action element.
391 /// </summary>
392 /// <param name="actionRow">The action row from which the element should be created.</param>
393 private void CreateActionElement(WixActionRow actionRow)
394 {
395 Wix.ISchemaElement actionElement = null;
396
397 if (null != this.core.GetIndexedElement("CustomAction", actionRow.Action)) // custom action
398 {
399 Wix.Custom custom = new Wix.Custom();
400
401 custom.Action = actionRow.Action;
402
403 if (null != actionRow.Condition)
404 {
405 custom.Content = actionRow.Condition;
406 }
407
408 switch (actionRow.Sequence)
409 {
410 case (-4):
411 custom.OnExit = Wix.ExitType.suspend;
412 break;
413 case (-3):
414 custom.OnExit = Wix.ExitType.error;
415 break;
416 case (-2):
417 custom.OnExit = Wix.ExitType.cancel;
418 break;
419 case (-1):
420 custom.OnExit = Wix.ExitType.success;
421 break;
422 default:
423 if (null != actionRow.Before)
424 {
425 custom.Before = actionRow.Before;
426 }
427 else if (null != actionRow.After)
428 {
429 custom.After = actionRow.After;
430 }
431 else if (0 < actionRow.Sequence)
432 {
433 custom.Sequence = actionRow.Sequence;
434 }
435 break;
436 }
437
438 actionElement = custom;
439 }
440 else if (null != this.core.GetIndexedElement("Dialog", actionRow.Action)) // dialog
441 {
442 Wix.Show show = new Wix.Show();
443
444 show.Dialog = actionRow.Action;
445
446 if (null != actionRow.Condition)
447 {
448 show.Content = actionRow.Condition;
449 }
450
451 switch (actionRow.Sequence)
452 {
453 case (-4):
454 show.OnExit = Wix.ExitType.suspend;
455 break;
456 case (-3):
457 show.OnExit = Wix.ExitType.error;
458 break;
459 case (-2):
460 show.OnExit = Wix.ExitType.cancel;
461 break;
462 case (-1):
463 show.OnExit = Wix.ExitType.success;
464 break;
465 default:
466 if (null != actionRow.Before)
467 {
468 show.Before = actionRow.Before;
469 }
470 else if (null != actionRow.After)
471 {
472 show.After = actionRow.After;
473 }
474 else if (0 < actionRow.Sequence)
475 {
476 show.Sequence = actionRow.Sequence;
477 }
478 break;
479 }
480
481 actionElement = show;
482 }
483 else // possibly a standard action without suggested sequence information
484 {
485 actionElement = this.CreateStandardActionElement(actionRow);
486 }
487
488 // add the action element to the appropriate sequence element
489 if (null != actionElement)
490 {
491 string sequenceTable = actionRow.SequenceTable.ToString();
492 Wix.IParentElement sequenceElement = (Wix.IParentElement)this.sequenceElements[sequenceTable];
493
494 if (null == sequenceElement)
495 {
496 switch (actionRow.SequenceTable)
497 {
498 case SequenceTable.AdminExecuteSequence:
499 sequenceElement = new Wix.AdminExecuteSequence();
500 break;
501 case SequenceTable.AdminUISequence:
502 sequenceElement = new Wix.AdminUISequence();
503 break;
504 case SequenceTable.AdvtExecuteSequence:
505 sequenceElement = new Wix.AdvertiseExecuteSequence();
506 break;
507 case SequenceTable.InstallExecuteSequence:
508 sequenceElement = new Wix.InstallExecuteSequence();
509 break;
510 case SequenceTable.InstallUISequence:
511 sequenceElement = new Wix.InstallUISequence();
512 break;
513 default:
514 throw new InvalidOperationException(WixStrings.EXP_UnknowSequenceTable);
515 }
516
517 this.core.RootElement.AddChild((Wix.ISchemaElement)sequenceElement);
518 this.sequenceElements.Add(sequenceTable, sequenceElement);
519 }
520
521 try
522 {
523 sequenceElement.AddChild(actionElement);
524 }
525 catch (System.ArgumentException) // action/dialog is not valid for this sequence
526 {
527 this.core.OnMessage(WixWarnings.IllegalActionInSequence(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action));
528 }
529 }
530 }
531
532 /// <summary>
533 /// Creates a standard action element.
534 /// </summary>
535 /// <param name="actionRow">The action row from which the element should be created.</param>
536 /// <returns>The created element.</returns>
537 private Wix.ISchemaElement CreateStandardActionElement(WixActionRow actionRow)
538 {
539 Wix.ActionSequenceType actionElement = null;
540
541 switch (actionRow.Action)
542 {
543 case "AllocateRegistrySpace":
544 actionElement = new Wix.AllocateRegistrySpace();
545 break;
546 case "AppSearch":
547 WixActionRow appSearchActionRow = this.standardActions[actionRow.SequenceTable, actionRow.Action];
548
549 if (null != actionRow.Before || null != actionRow.After || (null != appSearchActionRow && actionRow.Sequence != appSearchActionRow.Sequence))
550 {
551 Wix.AppSearch appSearch = new Wix.AppSearch();
552
553 if (null != actionRow.Condition)
554 {
555 appSearch.Content = actionRow.Condition;
556 }
557
558 if (null != actionRow.Before)
559 {
560 appSearch.Before = actionRow.Before;
561 }
562 else if (null != actionRow.After)
563 {
564 appSearch.After = actionRow.After;
565 }
566 else if (0 < actionRow.Sequence)
567 {
568 appSearch.Sequence = actionRow.Sequence;
569 }
570
571 return appSearch;
572 }
573 break;
574 case "BindImage":
575 actionElement = new Wix.BindImage();
576 break;
577 case "CCPSearch":
578 Wix.CCPSearch ccpSearch = new Wix.CCPSearch();
579 Decompiler.SequenceRelativeAction(actionRow, ccpSearch);
580 return ccpSearch;
581 case "CostFinalize":
582 actionElement = new Wix.CostFinalize();
583 break;
584 case "CostInitialize":
585 actionElement = new Wix.CostInitialize();
586 break;
587 case "CreateFolders":
588 actionElement = new Wix.CreateFolders();
589 break;
590 case "CreateShortcuts":
591 actionElement = new Wix.CreateShortcuts();
592 break;
593 case "DeleteServices":
594 actionElement = new Wix.DeleteServices();
595 break;
596 case "DisableRollback":
597 Wix.DisableRollback disableRollback = new Wix.DisableRollback();
598 Decompiler.SequenceRelativeAction(actionRow, disableRollback);
599 return disableRollback;
600 case "DuplicateFiles":
601 actionElement = new Wix.DuplicateFiles();
602 break;
603 case "ExecuteAction":
604 actionElement = new Wix.ExecuteAction();
605 break;
606 case "FileCost":
607 actionElement = new Wix.FileCost();
608 break;
609 case "FindRelatedProducts":
610 Wix.FindRelatedProducts findRelatedProducts = new Wix.FindRelatedProducts();
611 Decompiler.SequenceRelativeAction(actionRow, findRelatedProducts);
612 return findRelatedProducts;
613 case "ForceReboot":
614 Wix.ForceReboot forceReboot = new Wix.ForceReboot();
615 Decompiler.SequenceRelativeAction(actionRow, forceReboot);
616 return forceReboot;
617 case "InstallAdminPackage":
618 actionElement = new Wix.InstallAdminPackage();
619 break;
620 case "InstallExecute":
621 Wix.InstallExecute installExecute = new Wix.InstallExecute();
622 Decompiler.SequenceRelativeAction(actionRow, installExecute);
623 return installExecute;
624 case "InstallExecuteAgain":
625 Wix.InstallExecuteAgain installExecuteAgain = new Wix.InstallExecuteAgain();
626 Decompiler.SequenceRelativeAction(actionRow, installExecuteAgain);
627 return installExecuteAgain;
628 case "InstallFiles":
629 actionElement = new Wix.InstallFiles();
630 break;
631 case "InstallFinalize":
632 actionElement = new Wix.InstallFinalize();
633 break;
634 case "InstallInitialize":
635 actionElement = new Wix.InstallInitialize();
636 break;
637 case "InstallODBC":
638 actionElement = new Wix.InstallODBC();
639 break;
640 case "InstallServices":
641 actionElement = new Wix.InstallServices();
642 break;
643 case "InstallValidate":
644 actionElement = new Wix.InstallValidate();
645 break;
646 case "IsolateComponents":
647 actionElement = new Wix.IsolateComponents();
648 break;
649 case "LaunchConditions":
650 Wix.LaunchConditions launchConditions = new Wix.LaunchConditions();
651 Decompiler.SequenceRelativeAction(actionRow, launchConditions);
652 return launchConditions;
653 case "MigrateFeatureStates":
654 actionElement = new Wix.MigrateFeatureStates();
655 break;
656 case "MoveFiles":
657 actionElement = new Wix.MoveFiles();
658 break;
659 case "MsiPublishAssemblies":
660 actionElement = new Wix.MsiPublishAssemblies();
661 break;
662 case "MsiUnpublishAssemblies":
663 actionElement = new Wix.MsiUnpublishAssemblies();
664 break;
665 case "PatchFiles":
666 actionElement = new Wix.PatchFiles();
667 break;
668 case "ProcessComponents":
669 actionElement = new Wix.ProcessComponents();
670 break;
671 case "PublishComponents":
672 actionElement = new Wix.PublishComponents();
673 break;
674 case "PublishFeatures":
675 actionElement = new Wix.PublishFeatures();
676 break;
677 case "PublishProduct":
678 actionElement = new Wix.PublishProduct();
679 break;
680 case "RegisterClassInfo":
681 actionElement = new Wix.RegisterClassInfo();
682 break;
683 case "RegisterComPlus":
684 actionElement = new Wix.RegisterComPlus();
685 break;
686 case "RegisterExtensionInfo":
687 actionElement = new Wix.RegisterExtensionInfo();
688 break;
689 case "RegisterFonts":
690 actionElement = new Wix.RegisterFonts();
691 break;
692 case "RegisterMIMEInfo":
693 actionElement = new Wix.RegisterMIMEInfo();
694 break;
695 case "RegisterProduct":
696 actionElement = new Wix.RegisterProduct();
697 break;
698 case "RegisterProgIdInfo":
699 actionElement = new Wix.RegisterProgIdInfo();
700 break;
701 case "RegisterTypeLibraries":
702 actionElement = new Wix.RegisterTypeLibraries();
703 break;
704 case "RegisterUser":
705 actionElement = new Wix.RegisterUser();
706 break;
707 case "RemoveDuplicateFiles":
708 actionElement = new Wix.RemoveDuplicateFiles();
709 break;
710 case "RemoveEnvironmentStrings":
711 actionElement = new Wix.RemoveEnvironmentStrings();
712 break;
713 case "RemoveExistingProducts":
714 Wix.RemoveExistingProducts removeExistingProducts = new Wix.RemoveExistingProducts();
715 Decompiler.SequenceRelativeAction(actionRow, removeExistingProducts);
716 return removeExistingProducts;
717 case "RemoveFiles":
718 actionElement = new Wix.RemoveFiles();
719 break;
720 case "RemoveFolders":
721 actionElement = new Wix.RemoveFolders();
722 break;
723 case "RemoveIniValues":
724 actionElement = new Wix.RemoveIniValues();
725 break;
726 case "RemoveODBC":
727 actionElement = new Wix.RemoveODBC();
728 break;
729 case "RemoveRegistryValues":
730 actionElement = new Wix.RemoveRegistryValues();
731 break;
732 case "RemoveShortcuts":
733 actionElement = new Wix.RemoveShortcuts();
734 break;
735 case "ResolveSource":
736 Wix.ResolveSource resolveSource = new Wix.ResolveSource();
737 Decompiler.SequenceRelativeAction(actionRow, resolveSource);
738 return resolveSource;
739 case "RMCCPSearch":
740 Wix.RMCCPSearch rmccpSearch = new Wix.RMCCPSearch();
741 Decompiler.SequenceRelativeAction(actionRow, rmccpSearch);
742 return rmccpSearch;
743 case "ScheduleReboot":
744 Wix.ScheduleReboot scheduleReboot = new Wix.ScheduleReboot();
745 Decompiler.SequenceRelativeAction(actionRow, scheduleReboot);
746 return scheduleReboot;
747 case "SelfRegModules":
748 actionElement = new Wix.SelfRegModules();
749 break;
750 case "SelfUnregModules":
751 actionElement = new Wix.SelfUnregModules();
752 break;
753 case "SetODBCFolders":
754 actionElement = new Wix.SetODBCFolders();
755 break;
756 case "StartServices":
757 actionElement = new Wix.StartServices();
758 break;
759 case "StopServices":
760 actionElement = new Wix.StopServices();
761 break;
762 case "UnpublishComponents":
763 actionElement = new Wix.UnpublishComponents();
764 break;
765 case "UnpublishFeatures":
766 actionElement = new Wix.UnpublishFeatures();
767 break;
768 case "UnregisterClassInfo":
769 actionElement = new Wix.UnregisterClassInfo();
770 break;
771 case "UnregisterComPlus":
772 actionElement = new Wix.UnregisterComPlus();
773 break;
774 case "UnregisterExtensionInfo":
775 actionElement = new Wix.UnregisterExtensionInfo();
776 break;
777 case "UnregisterFonts":
778 actionElement = new Wix.UnregisterFonts();
779 break;
780 case "UnregisterMIMEInfo":
781 actionElement = new Wix.UnregisterMIMEInfo();
782 break;
783 case "UnregisterProgIdInfo":
784 actionElement = new Wix.UnregisterProgIdInfo();
785 break;
786 case "UnregisterTypeLibraries":
787 actionElement = new Wix.UnregisterTypeLibraries();
788 break;
789 case "ValidateProductID":
790 actionElement = new Wix.ValidateProductID();
791 break;
792 case "WriteEnvironmentStrings":
793 actionElement = new Wix.WriteEnvironmentStrings();
794 break;
795 case "WriteIniValues":
796 actionElement = new Wix.WriteIniValues();
797 break;
798 case "WriteRegistryValues":
799 actionElement = new Wix.WriteRegistryValues();
800 break;
801 default:
802 this.core.OnMessage(WixWarnings.UnknownAction(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action));
803 return null;
804 }
805
806 if (actionElement != null)
807 {
808 this.SequenceStandardAction(actionRow, actionElement);
809 }
810
811 return actionElement;
812 }
813
814 /// <summary>
815 /// Applies the condition and sequence to a standard action element based on the action row data.
816 /// </summary>
817 /// <param name="actionRow">Action row data from the database.</param>
818 /// <param name="actionElement">Element to be sequenced.</param>
819 private void SequenceStandardAction(WixActionRow actionRow, Wix.ActionSequenceType actionElement)
820 {
821 if (null != actionRow.Condition)
822 {
823 actionElement.Content = actionRow.Condition;
824 }
825
826 if ((null != actionRow.Before || null != actionRow.After) && 0 == actionRow.Sequence)
827 {
828 this.core.OnMessage(WixWarnings.DecompiledStandardActionRelativelyScheduledInModule(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action));
829 }
830 else if (0 < actionRow.Sequence)
831 {
832 actionElement.Sequence = actionRow.Sequence;
833 }
834 }
835
836 /// <summary>
837 /// Applies the condition and relative sequence to an action element based on the action row data.
838 /// </summary>
839 /// <param name="actionRow">Action row data from the database.</param>
840 /// <param name="actionElement">Element to be sequenced.</param>
841 private static void SequenceRelativeAction(WixActionRow actionRow, Wix.ActionModuleSequenceType actionElement)
842 {
843 if (null != actionRow.Condition)
844 {
845 actionElement.Content = actionRow.Condition;
846 }
847
848 if (null != actionRow.Before)
849 {
850 actionElement.Before = actionRow.Before;
851 }
852 else if (null != actionRow.After)
853 {
854 actionElement.After = actionRow.After;
855 }
856 else if (0 < actionRow.Sequence)
857 {
858 actionElement.Sequence = actionRow.Sequence;
859 }
860 }
861
862 /// <summary>
863 /// Ensure that a particular property exists in the decompiled output.
864 /// </summary>
865 /// <param name="id">The identifier of the property.</param>
866 /// <returns>The property element.</returns>
867 private Wix.Property EnsureProperty(string id)
868 {
869 Wix.Property property = (Wix.Property)this.core.GetIndexedElement("Property", id);
870
871 if (null == property)
872 {
873 property = new Wix.Property();
874 property.Id = id;
875
876 // create a dummy row for indexing
877 Row row = new Row(null, this.tableDefinitions["Property"]);
878 row[0] = id;
879
880 this.core.RootElement.AddChild(property);
881 this.core.IndexElement(row, property);
882 }
883
884 return property;
885 }
886
887 /// <summary>
888 /// Finalize decompilation.
889 /// </summary>
890 /// <param name="tables">The collection of all tables.</param>
891 private void FinalizeDecompile(TableIndexedCollection tables)
892 {
893 if (OutputType.PatchCreation == this.outputType)
894 {
895 this.FinalizeFamilyFileRangesTable(tables);
896 }
897 else
898 {
899 this.FinalizeCheckBoxTable(tables);
900 this.FinalizeComponentTable(tables);
901 this.FinalizeDialogTable(tables);
902 this.FinalizeDuplicateMoveFileTables(tables);
903 this.FinalizeFeatureComponentsTable(tables);
904 this.FinalizeFileTable(tables);
905 this.FinalizeMIMETable(tables);
906 this.FinalizeMsiLockPermissionsExTable(tables);
907 this.FinalizeLockPermissionsTable(tables);
908 this.FinalizeProgIdTable(tables);
909 this.FinalizePropertyTable(tables);
910 this.FinalizeRemoveFileTable(tables);
911 this.FinalizeSearchTables(tables);
912 this.FinalizeUpgradeTable(tables);
913 this.FinalizeSequenceTables(tables);
914 this.FinalizeVerbTable(tables);
915 }
916 }
917
918 /// <summary>
919 /// Finalize the CheckBox table.
920 /// </summary>
921 /// <param name="tables">The collection of all tables.</param>
922 /// <remarks>
923 /// Enumerates through all the Control rows, looking for controls of type "CheckBox" with
924 /// a value in the Property column. This is then possibly matched up with a CheckBox row
925 /// to retrieve a CheckBoxValue. There is no foreign key from the Control to CheckBox table.
926 /// </remarks>
927 private void FinalizeCheckBoxTable(TableIndexedCollection tables)
928 {
929 // if the user has requested to suppress the UI elements, we have nothing to do
930 if (this.suppressUI)
931 {
932 return;
933 }
934
935 Table checkBoxTable = tables["CheckBox"];
936 Table controlTable = tables["Control"];
937
938 Hashtable checkBoxes = new Hashtable();
939 Hashtable checkBoxProperties = new Hashtable();
940
941 // index the CheckBox table
942 if (null != checkBoxTable)
943 {
944 foreach (Row row in checkBoxTable.Rows)
945 {
946 checkBoxes.Add(row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), row);
947 checkBoxProperties.Add(row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), false);
948 }
949 }
950
951 // enumerate through the Control table, adding CheckBox values where appropriate
952 if (null != controlTable)
953 {
954 foreach (Row row in controlTable.Rows)
955 {
956 Wix.Control control = (Wix.Control)this.core.GetIndexedElement(row);
957
958 if ("CheckBox" == Convert.ToString(row[2]) && null != row[8])
959 {
960 Row checkBoxRow = (Row)checkBoxes[row[8]];
961
962 if (null == checkBoxRow)
963 {
964 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, "Control", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Property", Convert.ToString(row[8]), "CheckBox"));
965 }
966 else
967 {
968 // if we've seen this property already, create a reference to it
969 if (Convert.ToBoolean(checkBoxProperties[row[8]]))
970 {
971 control.CheckBoxPropertyRef = Convert.ToString(row[8]);
972 }
973 else
974 {
975 control.Property = Convert.ToString(row[8]);
976 checkBoxProperties[row[8]] = true;
977 }
978
979 if (null != checkBoxRow[1])
980 {
981 control.CheckBoxValue = Convert.ToString(checkBoxRow[1]);
982 }
983 }
984 }
985 }
986 }
987 }
988
989 /// <summary>
990 /// Finalize the Component table.
991 /// </summary>
992 /// <param name="tables">The collection of all tables.</param>
993 /// <remarks>
994 /// Set the keypaths for each component.
995 /// </remarks>
996 private void FinalizeComponentTable(TableIndexedCollection tables)
997 {
998 Table componentTable = tables["Component"];
999 Table fileTable = tables["File"];
1000 Table odbcDataSourceTable = tables["ODBCDataSource"];
1001 Table registryTable = tables["Registry"];
1002
1003 // set the component keypaths
1004 if (null != componentTable)
1005 {
1006 foreach (Row row in componentTable.Rows)
1007 {
1008 int attributes = Convert.ToInt32(row[3]);
1009
1010 if (null == row[5])
1011 {
1012 Wix.Component component = (Wix.Component)this.core.GetIndexedElement("Component", Convert.ToString(row[0]));
1013
1014 component.KeyPath = Wix.YesNoType.yes;
1015 }
1016 else if (MsiInterop.MsidbComponentAttributesRegistryKeyPath == (attributes & MsiInterop.MsidbComponentAttributesRegistryKeyPath))
1017 {
1018 object registryObject = this.core.GetIndexedElement("Registry", Convert.ToString(row[5]));
1019
1020 if (null != registryObject)
1021 {
1022 Wix.RegistryValue registryValue = registryObject as Wix.RegistryValue;
1023
1024 if (null != registryValue)
1025 {
1026 registryValue.KeyPath = Wix.YesNoType.yes;
1027 }
1028 else
1029 {
1030 this.core.OnMessage(WixWarnings.IllegalRegistryKeyPath(row.SourceLineNumbers, "Component", Convert.ToString(row[5])));
1031 }
1032 }
1033 else
1034 {
1035 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, "Component", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "KeyPath", Convert.ToString(row[5]), "Registry"));
1036 }
1037 }
1038 else if (MsiInterop.MsidbComponentAttributesODBCDataSource == (attributes & MsiInterop.MsidbComponentAttributesODBCDataSource))
1039 {
1040 Wix.ODBCDataSource odbcDataSource = (Wix.ODBCDataSource)this.core.GetIndexedElement("ODBCDataSource", Convert.ToString(row[5]));
1041
1042 if (null != odbcDataSource)
1043 {
1044 odbcDataSource.KeyPath = Wix.YesNoType.yes;
1045 }
1046 else
1047 {
1048 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, "Component", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "KeyPath", Convert.ToString(row[5]), "ODBCDataSource"));
1049 }
1050 }
1051 else
1052 {
1053 Wix.File file = (Wix.File)this.core.GetIndexedElement("File", Convert.ToString(row[5]));
1054
1055 if (null != file)
1056 {
1057 file.KeyPath = Wix.YesNoType.yes;
1058 }
1059 else
1060 {
1061 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, "Component", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "KeyPath", Convert.ToString(row[5]), "File"));
1062 }
1063 }
1064 }
1065 }
1066
1067 // add the File children elements
1068 if (null != fileTable)
1069 {
1070 foreach (FileRow fileRow in fileTable.Rows)
1071 {
1072 Wix.Component component = (Wix.Component)this.core.GetIndexedElement("Component", fileRow.Component);
1073 Wix.File file = (Wix.File)this.core.GetIndexedElement(fileRow);
1074
1075 if (null != component)
1076 {
1077 component.AddChild(file);
1078 }
1079 else
1080 {
1081 this.core.OnMessage(WixWarnings.ExpectedForeignRow(fileRow.SourceLineNumbers, "File", fileRow.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", fileRow.Component, "Component"));
1082 }
1083 }
1084 }
1085
1086 // add the ODBCDataSource children elements
1087 if (null != odbcDataSourceTable)
1088 {
1089 foreach (Row row in odbcDataSourceTable.Rows)
1090 {
1091 Wix.Component component = (Wix.Component)this.core.GetIndexedElement("Component", Convert.ToString(row[1]));
1092 Wix.ODBCDataSource odbcDataSource = (Wix.ODBCDataSource)this.core.GetIndexedElement(row);
1093
1094 if (null != component)
1095 {
1096 component.AddChild(odbcDataSource);
1097 }
1098 else
1099 {
1100 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, "ODBCDataSource", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", Convert.ToString(row[1]), "Component"));
1101 }
1102 }
1103 }
1104
1105 // add the Registry children elements
1106 if (null != registryTable)
1107 {
1108 foreach (Row row in registryTable.Rows)
1109 {
1110 Wix.Component component = (Wix.Component)this.core.GetIndexedElement("Component", Convert.ToString(row[5]));
1111 Wix.ISchemaElement registryElement = (Wix.ISchemaElement)this.core.GetIndexedElement(row);
1112
1113 if (null != component)
1114 {
1115 component.AddChild(registryElement);
1116 }
1117 else
1118 {
1119 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, "Registry", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", Convert.ToString(row[5]), "Component"));
1120 }
1121 }
1122 }
1123 }
1124
1125 /// <summary>
1126 /// Finalize the Dialog table.
1127 /// </summary>
1128 /// <param name="tables">The collection of all tables.</param>
1129 /// <remarks>
1130 /// Sets the first, default, and cancel control for each dialog and adds all child control
1131 /// elements to the dialog.
1132 /// </remarks>
1133 private void FinalizeDialogTable(TableIndexedCollection tables)
1134 {
1135 // if the user has requested to suppress the UI elements, we have nothing to do
1136 if (this.suppressUI)
1137 {
1138 return;
1139 }
1140
1141 Table controlTable = tables["Control"];
1142 Table dialogTable = tables["Dialog"];
1143
1144 Hashtable addedControls = new Hashtable();
1145 Hashtable controlRows = new Hashtable();
1146
1147 // index the rows in the control rows (because we need the Control_Next value)
1148 if (null != controlTable)
1149 {
1150 foreach (Row row in controlTable.Rows)
1151 {
1152 controlRows.Add(row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), row);
1153 }
1154 }
1155
1156 if (null != dialogTable)
1157 {
1158 foreach (Row row in dialogTable.Rows)
1159 {
1160 Wix.Dialog dialog = (Wix.Dialog)this.core.GetIndexedElement(row);
1161 string dialogId = Convert.ToString(row[0]);
1162
1163 Wix.Control control = (Wix.Control)this.core.GetIndexedElement("Control", dialogId, Convert.ToString(row[7]));
1164 if (null == control)
1165 {
1166 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, "Dialog", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Dialog", dialogId, "Control_First", Convert.ToString(row[7]), "Control"));
1167 }
1168
1169 // add tabbable controls
1170 while (null != control)
1171 {
1172 Row controlRow = (Row)controlRows[String.Concat(dialogId, DecompilerConstants.PrimaryKeyDelimiter, control.Id)];
1173
1174 control.TabSkip = Wix.YesNoType.no;
1175 dialog.AddChild(control);
1176 addedControls.Add(control, null);
1177
1178 if (null != controlRow[10])
1179 {
1180 control = (Wix.Control)this.core.GetIndexedElement("Control", dialogId, Convert.ToString(controlRow[10]));
1181 if (null != control)
1182 {
1183 // looped back to the first control in the dialog
1184 if (addedControls.Contains(control))
1185 {
1186 control = null;
1187 }
1188 }
1189 else
1190 {
1191 this.core.OnMessage(WixWarnings.ExpectedForeignRow(controlRow.SourceLineNumbers, "Control", controlRow.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Dialog_", dialogId, "Control_Next", Convert.ToString(controlRow[10]), "Control"));
1192 }
1193 }
1194 else
1195 {
1196 control = null;
1197 }
1198 }
1199
1200 // set default control
1201 if (null != row[8])
1202 {
1203 Wix.Control defaultControl = (Wix.Control)this.core.GetIndexedElement("Control", dialogId, Convert.ToString(row[8]));
1204
1205 if (null != defaultControl)
1206 {
1207 defaultControl.Default = Wix.YesNoType.yes;
1208 }
1209 else
1210 {
1211 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, "Dialog", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Dialog", dialogId, "Control_Default", Convert.ToString(row[8]), "Control"));
1212 }
1213 }
1214
1215 // set cancel control
1216 if (null != row[9])
1217 {
1218 Wix.Control cancelControl = (Wix.Control)this.core.GetIndexedElement("Control", dialogId, Convert.ToString(row[9]));
1219
1220 if (null != cancelControl)
1221 {
1222 cancelControl.Cancel = Wix.YesNoType.yes;
1223 }
1224 else
1225 {
1226 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, "Dialog", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Dialog", dialogId, "Control_Cancel", Convert.ToString(row[9]), "Control"));
1227 }
1228 }
1229 }
1230 }
1231
1232 // add the non-tabbable controls to the dialog
1233 if (null != controlTable)
1234 {
1235 foreach (Row row in controlTable.Rows)
1236 {
1237 Wix.Control control = (Wix.Control)this.core.GetIndexedElement(row);
1238 Wix.Dialog dialog = (Wix.Dialog)this.core.GetIndexedElement("Dialog", Convert.ToString(row[0]));
1239
1240 if (null == dialog)
1241 {
1242 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, "Control", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Dialog_", Convert.ToString(row[0]), "Dialog"));
1243 continue;
1244 }
1245
1246 if (!addedControls.Contains(control))
1247 {
1248 control.TabSkip = Wix.YesNoType.yes;
1249 dialog.AddChild(control);
1250 }
1251 }
1252 }
1253 }
1254
1255 /// <summary>
1256 /// Finalize the DuplicateFile and MoveFile tables.
1257 /// </summary>
1258 /// <param name="tables">The collection of all tables.</param>
1259 /// <remarks>
1260 /// Sets the source/destination property/directory for each DuplicateFile or
1261 /// MoveFile row.
1262 /// </remarks>
1263 private void FinalizeDuplicateMoveFileTables(TableIndexedCollection tables)
1264 {
1265 Table duplicateFileTable = tables["DuplicateFile"];
1266 Table moveFileTable = tables["MoveFile"];
1267
1268 if (null != duplicateFileTable)
1269 {
1270 foreach (Row row in duplicateFileTable.Rows)
1271 {
1272 Wix.CopyFile copyFile = (Wix.CopyFile)this.core.GetIndexedElement(row);
1273
1274 if (null != row[4])
1275 {
1276 if (null != this.core.GetIndexedElement("Directory", Convert.ToString(row[4])))
1277 {
1278 copyFile.DestinationDirectory = Convert.ToString(row[4]);
1279 }
1280 else
1281 {
1282 copyFile.DestinationProperty = Convert.ToString(row[4]);
1283 }
1284 }
1285 }
1286 }
1287
1288 if (null != moveFileTable)
1289 {
1290 foreach (Row row in moveFileTable.Rows)
1291 {
1292 Wix.CopyFile copyFile = (Wix.CopyFile)this.core.GetIndexedElement(row);
1293
1294 if (null != row[4])
1295 {
1296 if (null != this.core.GetIndexedElement("Directory", Convert.ToString(row[4])))
1297 {
1298 copyFile.SourceDirectory = Convert.ToString(row[4]);
1299 }
1300 else
1301 {
1302 copyFile.SourceProperty = Convert.ToString(row[4]);
1303 }
1304 }
1305
1306 if (null != this.core.GetIndexedElement("Directory", Convert.ToString(row[5])))
1307 {
1308 copyFile.DestinationDirectory = Convert.ToString(row[5]);
1309 }
1310 else
1311 {
1312 copyFile.DestinationProperty = Convert.ToString(row[5]);
1313 }
1314 }
1315 }
1316 }
1317
1318 /// <summary>
1319 /// Finalize the FamilyFileRanges table.
1320 /// </summary>
1321 /// <param name="tables">The collection of all tables.</param>
1322 private void FinalizeFamilyFileRangesTable(TableIndexedCollection tables)
1323 {
1324 Table externalFilesTable = tables["ExternalFiles"];
1325 Table familyFileRangesTable = tables["FamilyFileRanges"];
1326 Table targetFiles_OptionalDataTable = tables["TargetFiles_OptionalData"];
1327
1328 Hashtable usedProtectRanges = new Hashtable();
1329
1330 if (null != familyFileRangesTable)
1331 {
1332 foreach (Row row in familyFileRangesTable.Rows)
1333 {
1334 Wix.ProtectRange protectRange = new Wix.ProtectRange();
1335
1336 if (null != row[2] && null != row[3])
1337 {
1338 string[] retainOffsets = (Convert.ToString(row[2])).Split(',');
1339 string[] retainLengths = (Convert.ToString(row[3])).Split(',');
1340
1341 if (retainOffsets.Length == retainLengths.Length)
1342 {
1343 for (int i = 0; i < retainOffsets.Length; i++)
1344 {
1345 if (retainOffsets[i].StartsWith("0x", StringComparison.Ordinal))
1346 {
1347 protectRange.Offset = Convert.ToInt32(retainOffsets[i].Substring(2), 16);
1348 }
1349 else
1350 {
1351 protectRange.Offset = Convert.ToInt32(retainOffsets[i], CultureInfo.InvariantCulture);
1352 }
1353
1354 if (retainLengths[i].StartsWith("0x", StringComparison.Ordinal))
1355 {
1356 protectRange.Length = Convert.ToInt32(retainLengths[i].Substring(2), 16);
1357 }
1358 else
1359 {
1360 protectRange.Length = Convert.ToInt32(retainLengths[i], CultureInfo.InvariantCulture);
1361 }
1362 }
1363 }
1364 else
1365 {
1366 // TODO: warn
1367 }
1368 }
1369 else if (null != row[2] || null != row[3])
1370 {
1371 // TODO: warn about mismatch between columns
1372 }
1373
1374 this.core.IndexElement(row, protectRange);
1375 }
1376 }
1377
1378 if (null != externalFilesTable)
1379 {
1380 foreach (Row row in externalFilesTable.Rows)
1381 {
1382 Wix.ExternalFile externalFile = (Wix.ExternalFile)this.core.GetIndexedElement(row);
1383
1384 Wix.ProtectRange protectRange = (Wix.ProtectRange)this.core.GetIndexedElement("FamilyFileRanges", Convert.ToString(row[0]), Convert.ToString(row[1]));
1385 if (null != protectRange)
1386 {
1387 externalFile.AddChild(protectRange);
1388 usedProtectRanges[protectRange] = null;
1389 }
1390 }
1391 }
1392
1393 if (null != targetFiles_OptionalDataTable)
1394 {
1395 Table targetImagesTable = tables["TargetImages"];
1396 Table upgradedImagesTable = tables["UpgradedImages"];
1397
1398 Hashtable targetImageRows = new Hashtable();
1399 Hashtable upgradedImagesRows = new Hashtable();
1400
1401 // index the TargetImages table
1402 if (null != targetImagesTable)
1403 {
1404 foreach (Row row in targetImagesTable.Rows)
1405 {
1406 targetImageRows.Add(row[0], row);
1407 }
1408 }
1409
1410 // index the UpgradedImages table
1411 if (null != upgradedImagesTable)
1412 {
1413 foreach (Row row in upgradedImagesTable.Rows)
1414 {
1415 upgradedImagesRows.Add(row[0], row);
1416 }
1417 }
1418
1419 foreach (Row row in targetFiles_OptionalDataTable.Rows)
1420 {
1421 Wix.TargetFile targetFile = (Wix.TargetFile)this.patchTargetFiles[row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter)];
1422
1423 Row targetImageRow = (Row)targetImageRows[row[0]];
1424 if (null == targetImageRow)
1425 {
1426 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, targetFiles_OptionalDataTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Target", Convert.ToString(row[0]), "TargetImages"));
1427 continue;
1428 }
1429
1430 Row upgradedImagesRow = (Row)upgradedImagesRows[targetImageRow[3]];
1431 if (null == upgradedImagesRow)
1432 {
1433 this.core.OnMessage(WixWarnings.ExpectedForeignRow(targetImageRow.SourceLineNumbers, targetImageRow.Table.Name, targetImageRow.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Upgraded", Convert.ToString(row[3]), "UpgradedImages"));
1434 continue;
1435 }
1436
1437 Wix.ProtectRange protectRange = (Wix.ProtectRange)this.core.GetIndexedElement("FamilyFileRanges", Convert.ToString(upgradedImagesRow[4]), Convert.ToString(row[1]));
1438 if (null != protectRange)
1439 {
1440 targetFile.AddChild(protectRange);
1441 usedProtectRanges[protectRange] = null;
1442 }
1443 }
1444 }
1445
1446 if (null != familyFileRangesTable)
1447 {
1448 foreach (Row row in familyFileRangesTable.Rows)
1449 {
1450 Wix.ProtectRange protectRange = (Wix.ProtectRange)this.core.GetIndexedElement(row);
1451
1452 if (!usedProtectRanges.Contains(protectRange))
1453 {
1454 Wix.ProtectFile protectFile = new Wix.ProtectFile();
1455
1456 protectFile.File = Convert.ToString(row[1]);
1457
1458 protectFile.AddChild(protectRange);
1459
1460 Wix.Family family = (Wix.Family)this.core.GetIndexedElement("ImageFamilies", Convert.ToString(row[0]));
1461 if (null != family)
1462 {
1463 family.AddChild(protectFile);
1464 }
1465 else
1466 {
1467 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, familyFileRangesTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Family", Convert.ToString(row[0]), "ImageFamilies"));
1468 }
1469 }
1470 }
1471 }
1472 }
1473
1474 /// <summary>
1475 /// Finalize the FeatureComponents table.
1476 /// </summary>
1477 /// <param name="tables">The collection of all tables.</param>
1478 /// <remarks>
1479 /// Since tables specifying references to the FeatureComponents table have references to
1480 /// the Feature and Component table separately, but not the FeatureComponents table specifically,
1481 /// the FeatureComponents table and primary features must be decompiled during finalization.
1482 /// </remarks>
1483 private void FinalizeFeatureComponentsTable(TableIndexedCollection tables)
1484 {
1485 Table classTable = tables["Class"];
1486 Table extensionTable = tables["Extension"];
1487 Table msiAssemblyTable = tables["MsiAssembly"];
1488 Table publishComponentTable = tables["PublishComponent"];
1489 Table shortcutTable = tables["Shortcut"];
1490 Table typeLibTable = tables["TypeLib"];
1491
1492 if (null != classTable)
1493 {
1494 foreach (Row row in classTable.Rows)
1495 {
1496 this.SetPrimaryFeature(row, 11, 2);
1497 }
1498 }
1499
1500 if (null != extensionTable)
1501 {
1502 foreach (Row row in extensionTable.Rows)
1503 {
1504 this.SetPrimaryFeature(row, 4, 1);
1505 }
1506 }
1507
1508 if (null != msiAssemblyTable)
1509 {
1510 foreach (Row row in msiAssemblyTable.Rows)
1511 {
1512 this.SetPrimaryFeature(row, 1, 0);
1513 }
1514 }
1515
1516 if (null != publishComponentTable)
1517 {
1518 foreach (Row row in publishComponentTable.Rows)
1519 {
1520 this.SetPrimaryFeature(row, 4, 2);
1521 }
1522 }
1523
1524 if (null != shortcutTable)
1525 {
1526 foreach (Row row in shortcutTable.Rows)
1527 {
1528 string target = Convert.ToString(row[4]);
1529
1530 if (!target.StartsWith("[", StringComparison.Ordinal) && !target.EndsWith("]", StringComparison.Ordinal))
1531 {
1532 this.SetPrimaryFeature(row, 4, 3);
1533 }
1534 }
1535 }
1536
1537 if (null != typeLibTable)
1538 {
1539 foreach (Row row in typeLibTable.Rows)
1540 {
1541 this.SetPrimaryFeature(row, 6, 2);
1542 }
1543 }
1544 }
1545
1546 /// <summary>
1547 /// Finalize the File table.
1548 /// </summary>
1549 /// <param name="tables">The collection of all tables.</param>
1550 /// <remarks>
1551 /// Sets the source, diskId, and assembly information for each file.
1552 /// </remarks>
1553 private void FinalizeFileTable(TableIndexedCollection tables)
1554 {
1555 Table fileTable = tables["File"];
1556 Table mediaTable = tables["Media"];
1557 Table msiAssemblyTable = tables["MsiAssembly"];
1558 Table typeLibTable = tables["TypeLib"];
1559
1560 // index the media table by media id
1561 RowDictionary<MediaRow> mediaRows;
1562 if (null != mediaTable)
1563 {
1564 mediaRows = new RowDictionary<MediaRow>(mediaTable);
1565 }
1566
1567 // set the disk identifiers and sources for files
1568 if (null != fileTable)
1569 {
1570 foreach (FileRow fileRow in fileTable.Rows)
1571 {
1572 Wix.File file = (Wix.File)this.core.GetIndexedElement("File", fileRow.File);
1573
1574 // Don't bother processing files that are orphaned (and won't show up in the output anyway)
1575 if (null != file.ParentElement)
1576 {
1577 // set the diskid
1578 if (null != mediaTable)
1579 {
1580 foreach (MediaRow mediaRow in mediaTable.Rows)
1581 {
1582 if (fileRow.Sequence <= mediaRow.LastSequence)
1583 {
1584 file.DiskId = Convert.ToString(mediaRow.DiskId);
1585 break;
1586 }
1587 }
1588 }
1589
1590 // set the source (done here because it requires information from the Directory table)
1591 if (OutputType.Module == this.outputType)
1592 {
1593 file.Source = String.Concat(this.exportFilePath, Path.DirectorySeparatorChar, "File", Path.DirectorySeparatorChar, file.Id, '.', this.modularizationGuid.Substring(1, 36).Replace('-', '_'));
1594 }
1595 else if (Wix.YesNoDefaultType.yes == file.Compressed || (Wix.YesNoDefaultType.no != file.Compressed && this.compressed))
1596 {
1597 file.Source = String.Concat(this.exportFilePath, Path.DirectorySeparatorChar, "File", Path.DirectorySeparatorChar, file.Id);
1598 }
1599 else // uncompressed
1600 {
1601 string fileName = (null != file.ShortName ? file.ShortName : file.Name);
1602
1603 if (!this.shortNames && null != file.Name)
1604 {
1605 fileName = file.Name;
1606 }
1607
1608 if (this.compressed) // uncompressed at the root of the source image
1609 {
1610 file.Source = String.Concat("SourceDir", Path.DirectorySeparatorChar, fileName);
1611 }
1612 else
1613 {
1614 string sourcePath = this.GetSourcePath(file);
1615
1616 file.Source = Path.Combine(sourcePath, fileName);
1617 }
1618 }
1619 }
1620 }
1621 }
1622
1623 // set the file assemblies and manifests
1624 if (null != msiAssemblyTable)
1625 {
1626 foreach (Row row in msiAssemblyTable.Rows)
1627 {
1628 Wix.Component component = (Wix.Component)this.core.GetIndexedElement("Component", Convert.ToString(row[0]));
1629
1630 if (null == component)
1631 {
1632 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, "MsiAssembly", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", Convert.ToString(row[0]), "Component"));
1633 }
1634 else
1635 {
1636 foreach (Wix.ISchemaElement element in component.Children)
1637 {
1638 Wix.File file = element as Wix.File;
1639
1640 if (null != file && Wix.YesNoType.yes == file.KeyPath)
1641 {
1642 if (null != row[2])
1643 {
1644 file.AssemblyManifest = Convert.ToString(row[2]);
1645 }
1646
1647 if (null != row[3])
1648 {
1649 file.AssemblyApplication = Convert.ToString(row[3]);
1650 }
1651
1652 if (null == row[4] || 0 == Convert.ToInt32(row[4]))
1653 {
1654 file.Assembly = Wix.File.AssemblyType.net;
1655 }
1656 else
1657 {
1658 file.Assembly = Wix.File.AssemblyType.win32;
1659 }
1660 }
1661 }
1662 }
1663 }
1664 }
1665
1666 // nest the TypeLib elements
1667 if (null != typeLibTable)
1668 {
1669 foreach (Row row in typeLibTable.Rows)
1670 {
1671 Wix.Component component = (Wix.Component)this.core.GetIndexedElement("Component", Convert.ToString(row[2]));
1672 Wix.TypeLib typeLib = (Wix.TypeLib)this.core.GetIndexedElement(row);
1673
1674 foreach (Wix.ISchemaElement element in component.Children)
1675 {
1676 Wix.File file = element as Wix.File;
1677
1678 if (null != file && Wix.YesNoType.yes == file.KeyPath)
1679 {
1680 file.AddChild(typeLib);
1681 }
1682 }
1683 }
1684 }
1685 }
1686
1687 /// <summary>
1688 /// Finalize the MIME table.
1689 /// </summary>
1690 /// <param name="tables">The collection of all tables.</param>
1691 /// <remarks>
1692 /// There is a foreign key shared between the MIME and Extension
1693 /// tables so either one would be valid to be decompiled first, so
1694 /// the only safe way to nest the MIME elements is to do it during finalize.
1695 /// </remarks>
1696 private void FinalizeMIMETable(TableIndexedCollection tables)
1697 {
1698 Table extensionTable = tables["Extension"];
1699 Table mimeTable = tables["MIME"];
1700
1701 Hashtable comExtensions = new Hashtable();
1702
1703 if (null != extensionTable)
1704 {
1705 foreach (Row row in extensionTable.Rows)
1706 {
1707 Wix.Extension extension = (Wix.Extension)this.core.GetIndexedElement(row);
1708
1709 // index the extension
1710 if (!comExtensions.Contains(row[0]))
1711 {
1712 comExtensions.Add(row[0], new ArrayList());
1713 }
1714 ((ArrayList)comExtensions[row[0]]).Add(extension);
1715
1716 // set the default MIME element for this extension
1717 if (null != row[3])
1718 {
1719 Wix.MIME mime = (Wix.MIME)this.core.GetIndexedElement("MIME", Convert.ToString(row[3]));
1720
1721 if (null != mime)
1722 {
1723 mime.Default = Wix.YesNoType.yes;
1724 }
1725 else
1726 {
1727 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, "Extension", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "MIME_", Convert.ToString(row[3]), "MIME"));
1728 }
1729 }
1730 }
1731 }
1732
1733 if (null != mimeTable)
1734 {
1735 foreach (Row row in mimeTable.Rows)
1736 {
1737 Wix.MIME mime = (Wix.MIME)this.core.GetIndexedElement(row);
1738
1739 if (comExtensions.Contains(row[1]))
1740 {
1741 ArrayList extensionElements = (ArrayList)comExtensions[row[1]];
1742
1743 foreach (Wix.Extension extension in extensionElements)
1744 {
1745 extension.AddChild(mime);
1746 }
1747 }
1748 else
1749 {
1750 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, "MIME", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Extension_", Convert.ToString(row[1]), "Extension"));
1751 }
1752 }
1753 }
1754 }
1755
1756 /// <summary>
1757 /// Finalize the ProgId table.
1758 /// </summary>
1759 /// <param name="tables">The collection of all tables.</param>
1760 /// <remarks>
1761 /// Enumerates through all the Class rows, looking for child ProgIds (these are the
1762 /// default ProgIds for a given Class). Then go through the ProgId table and add any
1763 /// remaining ProgIds for each Class. This happens during finalize because there is
1764 /// a circular dependency between the Class and ProgId tables.
1765 /// </remarks>
1766 private void FinalizeProgIdTable(TableIndexedCollection tables)
1767 {
1768 Table classTable = tables["Class"];
1769 Table progIdTable = tables["ProgId"];
1770 Table extensionTable = tables["Extension"];
1771 Table componentTable = tables["Component"];
1772
1773 Hashtable addedProgIds = new Hashtable();
1774 Hashtable classes = new Hashtable();
1775 Hashtable components = new Hashtable();
1776
1777 // add the default ProgIds for each class (and index the class table)
1778 if (null != classTable)
1779 {
1780 foreach (Row row in classTable.Rows)
1781 {
1782 Wix.Class wixClass = (Wix.Class)this.core.GetIndexedElement(row);
1783
1784 if (null != row[3])
1785 {
1786 Wix.ProgId progId = (Wix.ProgId)this.core.GetIndexedElement("ProgId", Convert.ToString(row[3]));
1787
1788 if (null != progId)
1789 {
1790 if (addedProgIds.Contains(progId))
1791 {
1792 this.core.OnMessage(WixWarnings.TooManyProgIds(row.SourceLineNumbers, Convert.ToString(row[0]), Convert.ToString(row[3]), Convert.ToString(addedProgIds[progId])));
1793 }
1794 else
1795 {
1796 wixClass.AddChild(progId);
1797 addedProgIds.Add(progId, wixClass.Id);
1798 }
1799 }
1800 else
1801 {
1802 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, "Class", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "ProgId_Default", Convert.ToString(row[3]), "ProgId"));
1803 }
1804 }
1805
1806 // index the Class elements for nesting of ProgId elements (which don't use the full Class primary key)
1807 if (!classes.Contains(wixClass.Id))
1808 {
1809 classes.Add(wixClass.Id, new ArrayList());
1810 }
1811 ((ArrayList)classes[wixClass.Id]).Add(wixClass);
1812 }
1813 }
1814
1815 // add the remaining non-default ProgId entries for each class
1816 if (null != progIdTable)
1817 {
1818 foreach (Row row in progIdTable.Rows)
1819 {
1820 Wix.ProgId progId = (Wix.ProgId)this.core.GetIndexedElement(row);
1821
1822 if (!addedProgIds.Contains(progId) && null != row[2] && null == progId.ParentElement)
1823 {
1824 ArrayList classElements = (ArrayList)classes[row[2]];
1825
1826 if (null != classElements)
1827 {
1828 foreach (Wix.Class wixClass in classElements)
1829 {
1830 wixClass.AddChild(progId);
1831 addedProgIds.Add(progId, wixClass.Id);
1832 }
1833 }
1834 else
1835 {
1836 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, "ProgId", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Class_", Convert.ToString(row[2]), "Class"));
1837 }
1838 }
1839 }
1840 }
1841
1842 if (null != componentTable)
1843 {
1844 foreach (Row row in componentTable.Rows)
1845 {
1846 Wix.Component wixComponent = (Wix.Component)this.core.GetIndexedElement(row);
1847
1848 // index the Class elements for nesting of ProgId elements (which don't use the full Class primary key)
1849 if (!components.Contains(wixComponent.Id))
1850 {
1851 components.Add(wixComponent.Id, new ArrayList());
1852 }
1853 ((ArrayList)components[wixComponent.Id]).Add(wixComponent);
1854 }
1855 }
1856
1857 // Check for any progIds that are not hooked up to a class and hook them up to the component specified by the extension
1858 if (null != extensionTable)
1859 {
1860 foreach (Row row in extensionTable.Rows)
1861 {
1862 // ignore the extension if it isn't associated with a progId
1863 if (null == row[2])
1864 {
1865 continue;
1866 }
1867
1868 Wix.ProgId progId = (Wix.ProgId)this.core.GetIndexedElement("ProgId", Convert.ToString(row[2]));
1869
1870 // Haven't added the progId yet and it doesn't have a parent progId
1871 if (!addedProgIds.Contains(progId) && null == progId.ParentElement)
1872 {
1873 ArrayList componentElements = (ArrayList)components[row[1]];
1874
1875 if (null != componentElements)
1876 {
1877 foreach (Wix.Component wixComponent in componentElements)
1878 {
1879 wixComponent.AddChild(progId);
1880 }
1881 }
1882 else
1883 {
1884 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, "Extension", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", Convert.ToString(row[1]), "Component"));
1885 }
1886 }
1887 }
1888 }
1889 }
1890
1891 /// <summary>
1892 /// Finalize the Property table.
1893 /// </summary>
1894 /// <param name="tables">The collection of all tables.</param>
1895 /// <remarks>
1896 /// Removes properties that are generated from other entries.
1897 /// </remarks>
1898 private void FinalizePropertyTable(TableIndexedCollection tables)
1899 {
1900 Table propertyTable = tables["Property"];
1901 Table customActionTable = tables["CustomAction"];
1902
1903 if (null != propertyTable && null != customActionTable)
1904 {
1905 foreach (Row row in customActionTable.Rows)
1906 {
1907 int bits = Convert.ToInt32(row[1]);
1908 if (MsiInterop.MsidbCustomActionTypeHideTarget == (bits & MsiInterop.MsidbCustomActionTypeHideTarget) &&
1909 MsiInterop.MsidbCustomActionTypeInScript == (bits & MsiInterop.MsidbCustomActionTypeInScript))
1910 {
1911 Wix.Property property = (Wix.Property)this.core.GetIndexedElement("Property", Convert.ToString(row[0]));
1912
1913 // If no other fields on the property are set we must have created it during link
1914 if (null != property && null == property.Value && Wix.YesNoType.yes != property.Secure && Wix.YesNoType.yes != property.SuppressModularization)
1915 {
1916 this.core.RootElement.RemoveChild(property);
1917 }
1918 }
1919 }
1920 }
1921 }
1922
1923 /// <summary>
1924 /// Finalize the RemoveFile table.
1925 /// </summary>
1926 /// <param name="tables">The collection of all tables.</param>
1927 /// <remarks>
1928 /// Sets the directory/property for each RemoveFile row.
1929 /// </remarks>
1930 private void FinalizeRemoveFileTable(TableIndexedCollection tables)
1931 {
1932 Table removeFileTable = tables["RemoveFile"];
1933
1934 if (null != removeFileTable)
1935 {
1936 foreach (Row row in removeFileTable.Rows)
1937 {
1938 bool isDirectory = false;
1939 string property = Convert.ToString(row[3]);
1940
1941 // determine if the property is actually authored as a directory
1942 if (null != this.core.GetIndexedElement("Directory", property))
1943 {
1944 isDirectory = true;
1945 }
1946
1947 Wix.ISchemaElement element = this.core.GetIndexedElement(row);
1948
1949 Wix.RemoveFile removeFile = element as Wix.RemoveFile;
1950 if (null != removeFile)
1951 {
1952 if (isDirectory)
1953 {
1954 removeFile.Directory = property;
1955 }
1956 else
1957 {
1958 removeFile.Property = property;
1959 }
1960 }
1961 else
1962 {
1963 Wix.RemoveFolder removeFolder = (Wix.RemoveFolder)element;
1964
1965 if (isDirectory)
1966 {
1967 removeFolder.Directory = property;
1968 }
1969 else
1970 {
1971 removeFolder.Property = property;
1972 }
1973 }
1974 }
1975 }
1976 }
1977
1978 /// <summary>
1979 /// Finalize the LockPermissions table.
1980 /// </summary>
1981 /// <param name="tables">The collection of all tables.</param>
1982 /// <remarks>
1983 /// Nests the Permission elements below their parent elements. There are no declared foreign
1984 /// keys for the parents of the LockPermissions table.
1985 /// </remarks>
1986 private void FinalizeLockPermissionsTable(TableIndexedCollection tables)
1987 {
1988 Table createFolderTable = tables["CreateFolder"];
1989 Table lockPermissionsTable = tables["LockPermissions"];
1990
1991 Hashtable createFolders = new Hashtable();
1992
1993 // index the CreateFolder table because the foreign key to this table from the
1994 // LockPermissions table is only part of the primary key of this table
1995 if (null != createFolderTable)
1996 {
1997 foreach (Row row in createFolderTable.Rows)
1998 {
1999 Wix.CreateFolder createFolder = (Wix.CreateFolder)this.core.GetIndexedElement(row);
2000 string directoryId = Convert.ToString(row[0]);
2001
2002 if (!createFolders.Contains(directoryId))
2003 {
2004 createFolders.Add(directoryId, new ArrayList());
2005 }
2006 ((ArrayList)createFolders[directoryId]).Add(createFolder);
2007 }
2008 }
2009
2010 if (null != lockPermissionsTable)
2011 {
2012 foreach (Row row in lockPermissionsTable.Rows)
2013 {
2014 string id = Convert.ToString(row[0]);
2015 string table = Convert.ToString(row[1]);
2016
2017 Wix.Permission permission = (Wix.Permission)this.core.GetIndexedElement(row);
2018
2019 if ("CreateFolder" == table)
2020 {
2021 ArrayList createFolderElements = (ArrayList)createFolders[id];
2022
2023 if (null != createFolderElements)
2024 {
2025 foreach (Wix.CreateFolder createFolder in createFolderElements)
2026 {
2027 createFolder.AddChild(permission);
2028 }
2029 }
2030 else
2031 {
2032 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, "LockPermissions", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "LockObject", id, table));
2033 }
2034 }
2035 else
2036 {
2037 Wix.IParentElement parentElement = (Wix.IParentElement)this.core.GetIndexedElement(table, id);
2038
2039 if (null != parentElement)
2040 {
2041 parentElement.AddChild(permission);
2042 }
2043 else
2044 {
2045 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, "LockPermissions", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "LockObject", id, table));
2046 }
2047 }
2048 }
2049 }
2050 }
2051
2052 /// <summary>
2053 /// Finalize the MsiLockPermissionsEx table.
2054 /// </summary>
2055 /// <param name="tables">The collection of all tables.</param>
2056 /// <remarks>
2057 /// Nests the PermissionEx elements below their parent elements. There are no declared foreign
2058 /// keys for the parents of the MsiLockPermissionsEx table.
2059 /// </remarks>
2060 private void FinalizeMsiLockPermissionsExTable(TableIndexedCollection tables)
2061 {
2062 Table createFolderTable = tables["CreateFolder"];
2063 Table msiLockPermissionsExTable = tables["MsiLockPermissionsEx"];
2064
2065 Hashtable createFolders = new Hashtable();
2066
2067 // index the CreateFolder table because the foreign key to this table from the
2068 // MsiLockPermissionsEx table is only part of the primary key of this table
2069 if (null != createFolderTable)
2070 {
2071 foreach (Row row in createFolderTable.Rows)
2072 {
2073 Wix.CreateFolder createFolder = (Wix.CreateFolder)this.core.GetIndexedElement(row);
2074 string directoryId = Convert.ToString(row[0]);
2075
2076 if (!createFolders.Contains(directoryId))
2077 {
2078 createFolders.Add(directoryId, new ArrayList());
2079 }
2080 ((ArrayList)createFolders[directoryId]).Add(createFolder);
2081 }
2082 }
2083
2084 if (null != msiLockPermissionsExTable)
2085 {
2086 foreach (Row row in msiLockPermissionsExTable.Rows)
2087 {
2088 string id = Convert.ToString(row[1]);
2089 string table = Convert.ToString(row[2]);
2090
2091 Wix.PermissionEx permissionEx = (Wix.PermissionEx)this.core.GetIndexedElement(row);
2092
2093 if ("CreateFolder" == table)
2094 {
2095 ArrayList createFolderElements = (ArrayList)createFolders[id];
2096
2097 if (null != createFolderElements)
2098 {
2099 foreach (Wix.CreateFolder createFolder in createFolderElements)
2100 {
2101 createFolder.AddChild(permissionEx);
2102 }
2103 }
2104 else
2105 {
2106 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, "MsiLockPermissionsEx", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "LockObject", id, table));
2107 }
2108 }
2109 else
2110 {
2111 Wix.IParentElement parentElement = (Wix.IParentElement)this.core.GetIndexedElement(table, id);
2112
2113 if (null != parentElement)
2114 {
2115 parentElement.AddChild(permissionEx);
2116 }
2117 else
2118 {
2119 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, "MsiLockPermissionsEx", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "LockObject", id, table));
2120 }
2121 }
2122 }
2123 }
2124 }
2125
2126 /// <summary>
2127 /// Finalize the search tables.
2128 /// </summary>
2129 /// <param name="tables">The collection of all tables.</param>
2130 /// <remarks>Does all the complex linking required for the search tables.</remarks>
2131 private void FinalizeSearchTables(TableIndexedCollection tables)
2132 {
2133 Table appSearchTable = tables["AppSearch"];
2134 Table ccpSearchTable = tables["CCPSearch"];
2135 Table drLocatorTable = tables["DrLocator"];
2136
2137 Hashtable appSearches = new Hashtable();
2138 Hashtable ccpSearches = new Hashtable();
2139 Hashtable drLocators = new Hashtable();
2140 Hashtable locators = new Hashtable();
2141 Hashtable usedSearchElements = new Hashtable();
2142 ArrayList unusedSearchElements = new ArrayList();
2143
2144 Wix.ComplianceCheck complianceCheck = null;
2145
2146 // index the AppSearch table by signatures
2147 if (null != appSearchTable)
2148 {
2149 foreach (Row row in appSearchTable.Rows)
2150 {
2151 string property = Convert.ToString(row[0]);
2152 string signature = Convert.ToString(row[1]);
2153
2154 if (!appSearches.Contains(signature))
2155 {
2156 appSearches.Add(signature, new StringCollection());
2157 }
2158
2159 ((StringCollection)appSearches[signature]).Add(property);
2160 }
2161 }
2162
2163 // index the CCPSearch table by signatures
2164 if (null != ccpSearchTable)
2165 {
2166 foreach (Row row in ccpSearchTable.Rows)
2167 {
2168 string signature = Convert.ToString(row[0]);
2169
2170 if (!ccpSearches.Contains(signature))
2171 {
2172 ccpSearches.Add(signature, new StringCollection());
2173 }
2174
2175 ((StringCollection)ccpSearches[signature]).Add(null);
2176
2177 if (null == complianceCheck && !appSearches.Contains(signature))
2178 {
2179 complianceCheck = new Wix.ComplianceCheck();
2180 this.core.RootElement.AddChild(complianceCheck);
2181 }
2182 }
2183 }
2184
2185 // index the directory searches by their search elements (to get back the original row)
2186 if (null != drLocatorTable)
2187 {
2188 foreach (Row row in drLocatorTable.Rows)
2189 {
2190 drLocators.Add(this.core.GetIndexedElement(row), row);
2191 }
2192 }
2193
2194 // index the locator tables by their signatures
2195 string[] locatorTableNames = new string[] { "CompLocator", "RegLocator", "IniLocator", "DrLocator", "Signature" };
2196 foreach (string locatorTableName in locatorTableNames)
2197 {
2198 Table locatorTable = tables[locatorTableName];
2199
2200 if (null != locatorTable)
2201 {
2202 foreach (Row row in locatorTable.Rows)
2203 {
2204 string signature = Convert.ToString(row[0]);
2205
2206 if (!locators.Contains(signature))
2207 {
2208 locators.Add(signature, new ArrayList());
2209 }
2210
2211 ((ArrayList)locators[signature]).Add(row);
2212 }
2213 }
2214 }
2215
2216 // move the DrLocator rows with a parent of CCP_DRIVE first to ensure they get FileSearch children (not FileSearchRef)
2217 foreach (ArrayList locatorRows in locators.Values)
2218 {
2219 int firstDrLocator = -1;
2220
2221 for (int i = 0; i < locatorRows.Count; i++)
2222 {
2223 Row locatorRow = (Row)locatorRows[i];
2224
2225 if ("DrLocator" == locatorRow.TableDefinition.Name)
2226 {
2227 if (-1 == firstDrLocator)
2228 {
2229 firstDrLocator = i;
2230 }
2231
2232 if ("CCP_DRIVE" == Convert.ToString(locatorRow[1]))
2233 {
2234 locatorRows.RemoveAt(i);
2235 locatorRows.Insert(firstDrLocator, locatorRow);
2236 break;
2237 }
2238 }
2239 }
2240 }
2241
2242 foreach (string signature in locators.Keys)
2243 {
2244 ArrayList locatorRows = (ArrayList)locators[signature];
2245 ArrayList signatureSearchElements = new ArrayList();
2246
2247 foreach (Row locatorRow in locatorRows)
2248 {
2249 bool used = true;
2250 Wix.ISchemaElement searchElement = this.core.GetIndexedElement(locatorRow);
2251
2252 if ("Signature" == locatorRow.TableDefinition.Name && 0 < signatureSearchElements.Count)
2253 {
2254 foreach (Wix.IParentElement searchParentElement in signatureSearchElements)
2255 {
2256 if (!usedSearchElements.Contains(searchElement))
2257 {
2258 searchParentElement.AddChild(searchElement);
2259 usedSearchElements[searchElement] = null;
2260 }
2261 else
2262 {
2263 Wix.FileSearchRef fileSearchRef = new Wix.FileSearchRef();
2264
2265 fileSearchRef.Id = signature;
2266
2267 searchParentElement.AddChild(fileSearchRef);
2268 }
2269 }
2270 }
2271 else if ("DrLocator" == locatorRow.TableDefinition.Name && null != locatorRow[1])
2272 {
2273 string parentSignature = Convert.ToString(locatorRow[1]);
2274
2275 if ("CCP_DRIVE" == parentSignature)
2276 {
2277 if (appSearches.Contains(signature))
2278 {
2279 StringCollection appSearchPropertyIds = (StringCollection)appSearches[signature];
2280
2281 foreach (string propertyId in appSearchPropertyIds)
2282 {
2283 Wix.Property property = this.EnsureProperty(propertyId);
2284 Wix.ComplianceDrive complianceDrive = null;
2285
2286 if (ccpSearches.Contains(signature))
2287 {
2288 property.ComplianceCheck = Wix.YesNoType.yes;
2289 }
2290
2291 foreach (Wix.ISchemaElement element in property.Children)
2292 {
2293 complianceDrive = element as Wix.ComplianceDrive;
2294 if (null != complianceDrive)
2295 {
2296 break;
2297 }
2298 }
2299
2300 if (null == complianceDrive)
2301 {
2302 complianceDrive = new Wix.ComplianceDrive();
2303 property.AddChild(complianceDrive);
2304 }
2305
2306 if (!usedSearchElements.Contains(searchElement))
2307 {
2308 complianceDrive.AddChild(searchElement);
2309 usedSearchElements[searchElement] = null;
2310 }
2311 else
2312 {
2313 Wix.DirectorySearchRef directorySearchRef = new Wix.DirectorySearchRef();
2314
2315 directorySearchRef.Id = signature;
2316
2317 if (null != locatorRow[1])
2318 {
2319 directorySearchRef.Parent = Convert.ToString(locatorRow[1]);
2320 }
2321
2322 if (null != locatorRow[2])
2323 {
2324 directorySearchRef.Path = Convert.ToString(locatorRow[2]);
2325 }
2326
2327 complianceDrive.AddChild(directorySearchRef);
2328 signatureSearchElements.Add(directorySearchRef);
2329 }
2330 }
2331 }
2332 else if (ccpSearches.Contains(signature))
2333 {
2334 Wix.ComplianceDrive complianceDrive = null;
2335
2336 foreach (Wix.ISchemaElement element in complianceCheck.Children)
2337 {
2338 complianceDrive = element as Wix.ComplianceDrive;
2339 if (null != complianceDrive)
2340 {
2341 break;
2342 }
2343 }
2344
2345 if (null == complianceDrive)
2346 {
2347 complianceDrive = new Wix.ComplianceDrive();
2348 complianceCheck.AddChild(complianceDrive);
2349 }
2350
2351 if (!usedSearchElements.Contains(searchElement))
2352 {
2353 complianceDrive.AddChild(searchElement);
2354 usedSearchElements[searchElement] = null;
2355 }
2356 else
2357 {
2358 Wix.DirectorySearchRef directorySearchRef = new Wix.DirectorySearchRef();
2359
2360 directorySearchRef.Id = signature;
2361
2362 if (null != locatorRow[1])
2363 {
2364 directorySearchRef.Parent = Convert.ToString(locatorRow[1]);
2365 }
2366
2367 if (null != locatorRow[2])
2368 {
2369 directorySearchRef.Path = Convert.ToString(locatorRow[2]);
2370 }
2371
2372 complianceDrive.AddChild(directorySearchRef);
2373 signatureSearchElements.Add(directorySearchRef);
2374 }
2375 }
2376 }
2377 else
2378 {
2379 bool usedDrLocator = false;
2380 ArrayList parentLocatorRows = (ArrayList)locators[parentSignature];
2381
2382 if (null != parentLocatorRows)
2383 {
2384 foreach (Row parentLocatorRow in parentLocatorRows)
2385 {
2386 if ("DrLocator" == parentLocatorRow.TableDefinition.Name)
2387 {
2388 Wix.IParentElement parentSearchElement = (Wix.IParentElement)this.core.GetIndexedElement(parentLocatorRow);
2389
2390 if (parentSearchElement.Children.GetEnumerator().MoveNext())
2391 {
2392 Row parentDrLocatorRow = (Row)drLocators[parentSearchElement];
2393 Wix.DirectorySearchRef directorySeachRef = new Wix.DirectorySearchRef();
2394
2395 directorySeachRef.Id = parentSignature;
2396
2397 if (null != parentDrLocatorRow[1])
2398 {
2399 directorySeachRef.Parent = Convert.ToString(parentDrLocatorRow[1]);
2400 }
2401
2402 if (null != parentDrLocatorRow[2])
2403 {
2404 directorySeachRef.Path = Convert.ToString(parentDrLocatorRow[2]);
2405 }
2406
2407 parentSearchElement = directorySeachRef;
2408 unusedSearchElements.Add(directorySeachRef);
2409 }
2410
2411 if (!usedSearchElements.Contains(searchElement))
2412 {
2413 parentSearchElement.AddChild(searchElement);
2414 usedSearchElements[searchElement] = null;
2415 usedDrLocator = true;
2416 }
2417 else
2418 {
2419 Wix.DirectorySearchRef directorySearchRef = new Wix.DirectorySearchRef();
2420
2421 directorySearchRef.Id = signature;
2422
2423 directorySearchRef.Parent = parentSignature;
2424
2425 if (null != locatorRow[2])
2426 {
2427 directorySearchRef.Path = Convert.ToString(locatorRow[2]);
2428 }
2429
2430 parentSearchElement.AddChild(searchElement);
2431 usedDrLocator = true;
2432 }
2433 }
2434 }
2435
2436 // keep track of unused DrLocator rows
2437 if (!usedDrLocator)
2438 {
2439 unusedSearchElements.Add(searchElement);
2440 }
2441 }
2442 else
2443 {
2444 // TODO: warn
2445 }
2446 }
2447 }
2448 else if (appSearches.Contains(signature))
2449 {
2450 StringCollection appSearchPropertyIds = (StringCollection)appSearches[signature];
2451
2452 foreach (string propertyId in appSearchPropertyIds)
2453 {
2454 Wix.Property property = this.EnsureProperty(propertyId);
2455
2456 if (ccpSearches.Contains(signature))
2457 {
2458 property.ComplianceCheck = Wix.YesNoType.yes;
2459 }
2460
2461 if (!usedSearchElements.Contains(searchElement))
2462 {
2463 property.AddChild(searchElement);
2464 usedSearchElements[searchElement] = null;
2465 }
2466 else if ("RegLocator" == locatorRow.TableDefinition.Name)
2467 {
2468 Wix.RegistrySearchRef registrySearchRef = new Wix.RegistrySearchRef();
2469
2470 registrySearchRef.Id = signature;
2471
2472 property.AddChild(registrySearchRef);
2473 signatureSearchElements.Add(registrySearchRef);
2474 }
2475 else
2476 {
2477 // TODO: warn about unavailable Ref element
2478 }
2479 }
2480 }
2481 else if (ccpSearches.Contains(signature))
2482 {
2483 if (!usedSearchElements.Contains(searchElement))
2484 {
2485 complianceCheck.AddChild(searchElement);
2486 usedSearchElements[searchElement] = null;
2487 }
2488 else if ("RegLocator" == locatorRow.TableDefinition.Name)
2489 {
2490 Wix.RegistrySearchRef registrySearchRef = new Wix.RegistrySearchRef();
2491
2492 registrySearchRef.Id = signature;
2493
2494 complianceCheck.AddChild(registrySearchRef);
2495 signatureSearchElements.Add(registrySearchRef);
2496 }
2497 else
2498 {
2499 // TODO: warn about unavailable Ref element
2500 }
2501 }
2502 else
2503 {
2504 if ("DrLocator" == locatorRow.TableDefinition.Name)
2505 {
2506 unusedSearchElements.Add(searchElement);
2507 }
2508 else
2509 {
2510 // TODO: warn
2511 used = false;
2512 }
2513 }
2514
2515 // keep track of the search elements for this signature so that nested searches go in the proper parents
2516 if (used)
2517 {
2518 signatureSearchElements.Add(searchElement);
2519 }
2520 }
2521 }
2522
2523 foreach (Wix.IParentElement unusedSearchElement in unusedSearchElements)
2524 {
2525 bool used = false;
2526
2527 foreach (Wix.ISchemaElement schemaElement in unusedSearchElement.Children)
2528 {
2529 Wix.DirectorySearch directorySearch = schemaElement as Wix.DirectorySearch;
2530 if (null != directorySearch)
2531 {
2532 StringCollection appSearchProperties = (StringCollection)appSearches[directorySearch.Id];
2533
2534 Wix.ISchemaElement unusedSearchSchemaElement = unusedSearchElement as Wix.ISchemaElement;
2535 if (null != appSearchProperties)
2536 {
2537 Wix.Property property = this.EnsureProperty(appSearchProperties[0]);
2538
2539 property.AddChild(unusedSearchSchemaElement);
2540 used = true;
2541 break;
2542 }
2543 else if (ccpSearches.Contains(directorySearch.Id))
2544 {
2545 complianceCheck.AddChild(unusedSearchSchemaElement);
2546 used = true;
2547 break;
2548 }
2549 else
2550 {
2551 // TODO: warn
2552 }
2553 }
2554 }
2555
2556 if (!used)
2557 {
2558 // TODO: warn
2559 }
2560 }
2561 }
2562
2563 /// <summary>
2564 /// Finalize the sequence tables.
2565 /// </summary>
2566 /// <param name="tables">The collection of all tables.</param>
2567 /// <remarks>
2568 /// Creates the sequence elements. Occurs during finalization because its
2569 /// not known if sequences refer to custom actions or dialogs during decompilation.
2570 /// </remarks>
2571 private void FinalizeSequenceTables(TableIndexedCollection tables)
2572 {
2573 // finalize the normal sequence tables
2574 if (OutputType.Product == this.outputType && !this.treatProductAsModule)
2575 {
2576 foreach (SequenceTable sequenceTable in Enum.GetValues(typeof(SequenceTable)))
2577 {
2578 // if suppressing UI elements, skip UI-related sequence tables
2579 if (this.suppressUI && ("AdminUISequence" == sequenceTable.ToString() || "InstallUISequence" == sequenceTable.ToString()))
2580 {
2581 continue;
2582 }
2583
2584 Table actionsTable = new Table(null, this.tableDefinitions["WixAction"]);
2585 Table table = tables[sequenceTable.ToString()];
2586
2587 if (null != table)
2588 {
2589 ArrayList actionRows = new ArrayList();
2590 bool needAbsoluteScheduling = this.suppressRelativeActionSequencing;
2591 WixActionRowCollection nonSequencedActionRows = new WixActionRowCollection();
2592 WixActionRowCollection suppressedRelativeActionRows = new WixActionRowCollection();
2593
2594 // create a sorted array of actions in this table
2595 foreach (Row row in table.Rows)
2596 {
2597 WixActionRow actionRow = (WixActionRow)actionsTable.CreateRow(null);
2598
2599 actionRow.Action = Convert.ToString(row[0]);
2600
2601 if (null != row[1])
2602 {
2603 actionRow.Condition = Convert.ToString(row[1]);
2604 }
2605
2606 actionRow.Sequence = Convert.ToInt32(row[2]);
2607
2608 actionRow.SequenceTable = sequenceTable;
2609
2610 actionRows.Add(actionRow);
2611 }
2612 actionRows.Sort();
2613
2614 for (int i = 0; i < actionRows.Count && !needAbsoluteScheduling; i++)
2615 {
2616 WixActionRow actionRow = (WixActionRow)actionRows[i];
2617 WixActionRow standardActionRow = this.standardActions[actionRow.SequenceTable, actionRow.Action];
2618
2619 // create actions for custom actions, dialogs, AppSearch when its moved, and standard actions with non-standard conditions
2620 if ("AppSearch" == actionRow.Action || null == standardActionRow || actionRow.Condition != standardActionRow.Condition)
2621 {
2622 WixActionRow previousActionRow = null;
2623 WixActionRow nextActionRow = null;
2624
2625 // find the previous action row if there is one
2626 if (0 <= i - 1)
2627 {
2628 previousActionRow = (WixActionRow)actionRows[i - 1];
2629 }
2630
2631 // find the next action row if there is one
2632 if (actionRows.Count > i + 1)
2633 {
2634 nextActionRow = (WixActionRow)actionRows[i + 1];
2635 }
2636
2637 // the logic for setting the before or after attribute for an action:
2638 // 1. If more than one action shares the same sequence number, everything must be absolutely sequenced.
2639 // 2. If the next action is a standard action and is 1 sequence number higher, this action occurs before it.
2640 // 3. If the previous action is a standard action and is 1 sequence number lower, this action occurs after it.
2641 // 4. If this action is not standard and the previous action is 1 sequence number lower and does not occur before this action, this action occurs after it.
2642 // 5. If this action is not standard and the previous action does not have the same sequence number and the next action is 1 sequence number higher, this action occurs before it.
2643 // 6. If this action is AppSearch and has all standard information, ignore it.
2644 // 7. If this action is standard and has a non-standard condition, create the action without any scheduling information.
2645 // 8. Everything must be absolutely sequenced.
2646 if ((null != previousActionRow && actionRow.Sequence == previousActionRow.Sequence) || (null != nextActionRow && actionRow.Sequence == nextActionRow.Sequence))
2647 {
2648 needAbsoluteScheduling = true;
2649 }
2650 else if (null != nextActionRow && null != this.standardActions[sequenceTable, nextActionRow.Action] && actionRow.Sequence + 1 == nextActionRow.Sequence)
2651 {
2652 actionRow.Before = nextActionRow.Action;
2653 }
2654 else if (null != previousActionRow && null != this.standardActions[sequenceTable, previousActionRow.Action] && actionRow.Sequence - 1 == previousActionRow.Sequence)
2655 {
2656 actionRow.After = previousActionRow.Action;
2657 }
2658 else if (null == standardActionRow && null != previousActionRow && actionRow.Sequence - 1 == previousActionRow.Sequence && previousActionRow.Before != actionRow.Action)
2659 {
2660 actionRow.After = previousActionRow.Action;
2661 }
2662 else if (null == standardActionRow && null != previousActionRow && actionRow.Sequence != previousActionRow.Sequence && null != nextActionRow && actionRow.Sequence + 1 == nextActionRow.Sequence)
2663 {
2664 actionRow.Before = nextActionRow.Action;
2665 }
2666 else if ("AppSearch" == actionRow.Action && null != standardActionRow && actionRow.Sequence == standardActionRow.Sequence && actionRow.Condition == standardActionRow.Condition)
2667 {
2668 // ignore an AppSearch row which has the WiX standard sequence and a standard condition
2669 }
2670 else if (null != standardActionRow && actionRow.Condition != standardActionRow.Condition) // standard actions get their standard sequence numbers
2671 {
2672 nonSequencedActionRows.Add(actionRow);
2673 }
2674 else if (0 < actionRow.Sequence)
2675 {
2676 needAbsoluteScheduling = true;
2677 }
2678 }
2679 else
2680 {
2681 suppressedRelativeActionRows.Add(actionRow);
2682 }
2683 }
2684
2685 // create the actions now that we know if they must be absolutely or relatively scheduled
2686 foreach (WixActionRow actionRow in actionRows)
2687 {
2688 if (needAbsoluteScheduling)
2689 {
2690 // remove any before/after information to ensure this is absolutely sequenced
2691 actionRow.Before = null;
2692 actionRow.After = null;
2693 }
2694 else if (nonSequencedActionRows.Contains(actionRow.SequenceTable, actionRow.Action))
2695 {
2696 // clear the sequence attribute to ensure this action is scheduled without a sequence number (or before/after)
2697 actionRow.Sequence = 0;
2698 }
2699 else if (suppressedRelativeActionRows.Contains(actionRow.SequenceTable, actionRow.Action))
2700 {
2701 // skip the suppressed relatively scheduled action rows
2702 continue;
2703 }
2704
2705 // create the action element
2706 this.CreateActionElement(actionRow);
2707 }
2708 }
2709 }
2710 }
2711 else if (OutputType.Module == this.outputType || this.treatProductAsModule) // finalize the Module sequence tables
2712 {
2713 foreach (SequenceTable sequenceTable in Enum.GetValues(typeof(SequenceTable)))
2714 {
2715 // if suppressing UI elements, skip UI-related sequence tables
2716 if (this.suppressUI && ("AdminUISequence" == sequenceTable.ToString() || "InstallUISequence" == sequenceTable.ToString()))
2717 {
2718 continue;
2719 }
2720
2721 Table actionsTable = new Table(null, this.tableDefinitions["WixAction"]);
2722 Table table = tables[String.Concat("Module", sequenceTable.ToString())];
2723
2724 if (null != table)
2725 {
2726 foreach (Row row in table.Rows)
2727 {
2728 WixActionRow actionRow = (WixActionRow)actionsTable.CreateRow(null);
2729
2730 actionRow.Action = Convert.ToString(row[0]);
2731
2732 if (null != row[1])
2733 {
2734 actionRow.Sequence = Convert.ToInt32(row[1]);
2735 }
2736
2737 if (null != row[2] && null != row[3])
2738 {
2739 switch (Convert.ToInt32(row[3]))
2740 {
2741 case 0:
2742 actionRow.Before = Convert.ToString(row[2]);
2743 break;
2744 case 1:
2745 actionRow.After = Convert.ToString(row[2]);
2746 break;
2747 default:
2748 this.core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[3].Column.Name, row[3]));
2749 break;
2750 }
2751 }
2752
2753 if (null != row[4])
2754 {
2755 actionRow.Condition = Convert.ToString(row[4]);
2756 }
2757
2758 actionRow.SequenceTable = sequenceTable;
2759
2760 // create action elements for non-standard actions
2761 if (null == this.standardActions[actionRow.SequenceTable, actionRow.Action] || null != actionRow.After || null != actionRow.Before)
2762 {
2763 this.CreateActionElement(actionRow);
2764 }
2765 }
2766 }
2767 }
2768 }
2769 }
2770
2771 /// <summary>
2772 /// Finalize the Upgrade table.
2773 /// </summary>
2774 /// <param name="tables">The collection of all tables.</param>
2775 /// <remarks>
2776 /// Decompile the rows from the Upgrade and LaunchCondition tables
2777 /// created by the MajorUpgrade element.
2778 /// </remarks>
2779 private void FinalizeUpgradeTable(TableIndexedCollection tables)
2780 {
2781 Table launchConditionTable = tables["LaunchCondition"];
2782 Table upgradeTable = tables["Upgrade"];
2783 string downgradeErrorMessage = null;
2784 string disallowUpgradeErrorMessage = null;
2785 Wix.MajorUpgrade majorUpgrade = new Wix.MajorUpgrade();
2786
2787 // find the DowngradePreventedCondition launch condition message
2788 if (null != launchConditionTable && 0 < launchConditionTable.Rows.Count)
2789 {
2790 foreach (Row launchRow in launchConditionTable.Rows)
2791 {
2792 if (Compiler.DowngradePreventedCondition == Convert.ToString(launchRow[0]))
2793 {
2794 downgradeErrorMessage = Convert.ToString(launchRow[1]);
2795 }
2796 else if (Compiler.UpgradePreventedCondition == Convert.ToString(launchRow[0]))
2797 {
2798 disallowUpgradeErrorMessage = Convert.ToString(launchRow[1]);
2799 }
2800 }
2801 }
2802
2803 if (null != upgradeTable && 0 < upgradeTable.Rows.Count)
2804 {
2805 bool hasMajorUpgrade = false;
2806
2807 foreach (Row row in upgradeTable.Rows)
2808 {
2809 UpgradeRow upgradeRow = (UpgradeRow)row;
2810
2811 if (Compiler.UpgradeDetectedProperty == upgradeRow.ActionProperty)
2812 {
2813 hasMajorUpgrade = true;
2814 int attr = upgradeRow.Attributes;
2815 string removeFeatures = upgradeRow.Remove;
2816
2817 if (MsiInterop.MsidbUpgradeAttributesVersionMaxInclusive == (attr & MsiInterop.MsidbUpgradeAttributesVersionMaxInclusive))
2818 {
2819 majorUpgrade.AllowSameVersionUpgrades = Wix.YesNoType.yes;
2820 }
2821
2822 if (MsiInterop.MsidbUpgradeAttributesMigrateFeatures != (attr & MsiInterop.MsidbUpgradeAttributesMigrateFeatures))
2823 {
2824 majorUpgrade.MigrateFeatures = Wix.YesNoType.no;
2825 }
2826
2827 if (MsiInterop.MsidbUpgradeAttributesIgnoreRemoveFailure == (attr & MsiInterop.MsidbUpgradeAttributesIgnoreRemoveFailure))
2828 {
2829 majorUpgrade.IgnoreRemoveFailure = Wix.YesNoType.yes;
2830 }
2831
2832 if (!String.IsNullOrEmpty(removeFeatures))
2833 {
2834 majorUpgrade.RemoveFeatures = removeFeatures;
2835 }
2836 }
2837 else if (Compiler.DowngradeDetectedProperty == upgradeRow.ActionProperty)
2838 {
2839 hasMajorUpgrade = true;
2840 majorUpgrade.DowngradeErrorMessage = downgradeErrorMessage;
2841 }
2842 }
2843
2844 if (hasMajorUpgrade)
2845 {
2846 if (String.IsNullOrEmpty(downgradeErrorMessage))
2847 {
2848 majorUpgrade.AllowDowngrades = Wix.YesNoType.yes;
2849 }
2850
2851 if (!String.IsNullOrEmpty(disallowUpgradeErrorMessage))
2852 {
2853 majorUpgrade.Disallow = Wix.YesNoType.yes;
2854 majorUpgrade.DisallowUpgradeErrorMessage = disallowUpgradeErrorMessage;
2855 }
2856
2857 majorUpgrade.Schedule = DetermineMajorUpgradeScheduling(tables);
2858 this.core.RootElement.AddChild(majorUpgrade);
2859 }
2860 }
2861 }
2862
2863 /// <summary>
2864 /// Finalize the Verb table.
2865 /// </summary>
2866 /// <param name="tables">The collection of all tables.</param>
2867 /// <remarks>
2868 /// The Extension table is a foreign table for the Verb table, but the
2869 /// foreign key is only part of the primary key of the Extension table,
2870 /// so it needs special logic to be nested properly.
2871 /// </remarks>
2872 private void FinalizeVerbTable(TableIndexedCollection tables)
2873 {
2874 Table extensionTable = tables["Extension"];
2875 Table verbTable = tables["Verb"];
2876
2877 Hashtable extensionElements = new Hashtable();
2878
2879 if (null != extensionTable)
2880 {
2881 foreach (Row row in extensionTable.Rows)
2882 {
2883 Wix.Extension extension = (Wix.Extension)this.core.GetIndexedElement(row);
2884
2885 if (!extensionElements.Contains(row[0]))
2886 {
2887 extensionElements.Add(row[0], new ArrayList());
2888 }
2889
2890 ((ArrayList)extensionElements[row[0]]).Add(extension);
2891 }
2892 }
2893
2894 if (null != verbTable)
2895 {
2896 foreach (Row row in verbTable.Rows)
2897 {
2898 Wix.Verb verb = (Wix.Verb)this.core.GetIndexedElement(row);
2899
2900 ArrayList extensionsArray = (ArrayList)extensionElements[row[0]];
2901 if (null != extensionsArray)
2902 {
2903 foreach (Wix.Extension extension in extensionsArray)
2904 {
2905 extension.AddChild(verb);
2906 }
2907 }
2908 else
2909 {
2910 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, verbTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Extension_", Convert.ToString(row[0]), "Extension"));
2911 }
2912 }
2913 }
2914 }
2915
2916 /// <summary>
2917 /// Get the path to a file in the source image.
2918 /// </summary>
2919 /// <param name="file">The file.</param>
2920 /// <returns>The path to the file in the source image.</returns>
2921 private string GetSourcePath(Wix.File file)
2922 {
2923 StringBuilder sourcePath = new StringBuilder();
2924
2925 Wix.Component component = (Wix.Component)file.ParentElement;
2926
2927 for (Wix.Directory directory = (Wix.Directory)component.ParentElement; null != directory; directory = directory.ParentElement as Wix.Directory)
2928 {
2929 string name;
2930
2931 if (!this.shortNames && null != directory.SourceName)
2932 {
2933 name = directory.SourceName;
2934 }
2935 else if (null != directory.ShortSourceName)
2936 {
2937 name = directory.ShortSourceName;
2938 }
2939 else if (!this.shortNames || null == directory.ShortName)
2940 {
2941 name = directory.Name;
2942 }
2943 else
2944 {
2945 name = directory.ShortName;
2946 }
2947
2948 if (0 == sourcePath.Length)
2949 {
2950 sourcePath.Append(name);
2951 }
2952 else
2953 {
2954 sourcePath.Insert(0, Path.DirectorySeparatorChar);
2955 sourcePath.Insert(0, name);
2956 }
2957 }
2958
2959 return sourcePath.ToString();
2960 }
2961
2962 /// <summary>
2963 /// Resolve the dependencies for a table (this is a helper method for GetSortedTableNames).
2964 /// </summary>
2965 /// <param name="tableName">The name of the table to resolve.</param>
2966 /// <param name="unsortedTableNames">The unsorted table names.</param>
2967 /// <param name="sortedTableNames">The sorted table names.</param>
2968 private void ResolveTableDependencies(string tableName, SortedList unsortedTableNames, StringCollection sortedTableNames)
2969 {
2970 unsortedTableNames.Remove(tableName);
2971
2972 foreach (ColumnDefinition columnDefinition in this.tableDefinitions[tableName].Columns)
2973 {
2974 // no dependency to resolve because this column doesn't reference another table
2975 if (null == columnDefinition.KeyTable)
2976 {
2977 continue;
2978 }
2979
2980 foreach (string keyTable in columnDefinition.KeyTable.Split(';'))
2981 {
2982 if (tableName == keyTable)
2983 {
2984 continue; // self-referencing dependency
2985 }
2986 else if (sortedTableNames.Contains(keyTable))
2987 {
2988 continue; // dependent table has already been sorted
2989 }
2990 else if (!this.tableDefinitions.Contains(keyTable))
2991 {
2992 this.core.OnMessage(WixErrors.MissingTableDefinition(keyTable));
2993 }
2994 else if (unsortedTableNames.Contains(keyTable))
2995 {
2996 this.ResolveTableDependencies(keyTable, unsortedTableNames, sortedTableNames);
2997 }
2998 else
2999 {
3000 // found a circular dependency, so ignore it (this assumes that the tables will
3001 // use a finalize method to nest their elements since the ordering will not be
3002 // deterministic
3003 }
3004 }
3005 }
3006
3007 sortedTableNames.Add(tableName);
3008 }
3009
3010 /// <summary>
3011 /// Get the names of the tables to process in the order they should be processed, according to their dependencies.
3012 /// </summary>
3013 /// <returns>A StringCollection containing the ordered table names.</returns>
3014 private StringCollection GetSortedTableNames()
3015 {
3016 StringCollection sortedTableNames = new StringCollection();
3017 SortedList unsortedTableNames = new SortedList();
3018
3019 // index the table names
3020 foreach (TableDefinition tableDefinition in this.tableDefinitions)
3021 {
3022 unsortedTableNames.Add(tableDefinition.Name, tableDefinition.Name);
3023 }
3024
3025 // resolve the dependencies for each table
3026 while (0 < unsortedTableNames.Count)
3027 {
3028 this.ResolveTableDependencies(Convert.ToString(unsortedTableNames.GetByIndex(0)), unsortedTableNames, sortedTableNames);
3029 }
3030
3031 return sortedTableNames;
3032 }
3033
3034 /// <summary>
3035 /// Initialize decompilation.
3036 /// </summary>
3037 /// <param name="tables">The collection of all tables.</param>
3038 private void InitializeDecompile(TableIndexedCollection tables)
3039 {
3040 // reset all the state information
3041 this.compressed = false;
3042 this.patchTargetFiles.Clear();
3043 this.sequenceElements.Clear();
3044 this.shortNames = false;
3045
3046 // set the codepage if its not neutral (0)
3047 if (0 != this.codepage)
3048 {
3049 switch (this.outputType)
3050 {
3051 case OutputType.Module:
3052 ((Wix.Module)this.core.RootElement).Codepage = this.codepage.ToString(CultureInfo.InvariantCulture);
3053 break;
3054 case OutputType.PatchCreation:
3055 ((Wix.PatchCreation)this.core.RootElement).Codepage = this.codepage.ToString(CultureInfo.InvariantCulture);
3056 break;
3057 case OutputType.Product:
3058 ((Wix.Product)this.core.RootElement).Codepage = this.codepage.ToString(CultureInfo.InvariantCulture);
3059 break;
3060 }
3061 }
3062
3063 // index the rows from the extension libraries
3064 Dictionary<string, HashSet<string>> indexedExtensionTables = new Dictionary<string, HashSet<string>>();
3065 foreach (IDecompilerExtension extension in this.extensions)
3066 {
3067 // Get the optional library from the extension with the rows to be removed.
3068 Library library = extension.GetLibraryToRemove(this.tableDefinitions);
3069 if (null != library)
3070 {
3071 foreach (Section section in library.Sections)
3072 {
3073 foreach (Table table in section.Tables)
3074 {
3075 foreach (Row row in table.Rows)
3076 {
3077 string primaryKey;
3078 string tableName;
3079
3080 // the Actions table needs to be handled specially
3081 if ("WixAction" == table.Name)
3082 {
3083 primaryKey = Convert.ToString(row[1]);
3084
3085 if (OutputType.Module == this.outputType)
3086 {
3087 tableName = String.Concat("Module", Convert.ToString(row[0]));
3088 }
3089 else
3090 {
3091 tableName = Convert.ToString(row[0]);
3092 }
3093 }
3094 else
3095 {
3096 primaryKey = row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter);
3097 tableName = table.Name;
3098 }
3099
3100 if (null != primaryKey)
3101 {
3102 HashSet<string> indexedExtensionRows;
3103 if (!indexedExtensionTables.TryGetValue(tableName, out indexedExtensionRows))
3104 {
3105 indexedExtensionRows = new HashSet<string>();
3106 indexedExtensionTables.Add(tableName, indexedExtensionRows);
3107 }
3108
3109 indexedExtensionRows.Add(primaryKey);
3110 }
3111 }
3112 }
3113 }
3114 }
3115 }
3116
3117 // remove the rows from the extension libraries (to allow full round-tripping)
3118 foreach (var kvp in indexedExtensionTables)
3119 {
3120 string tableName = kvp.Key;
3121 HashSet<string> indexedExtensionRows = kvp.Value;
3122
3123 Table table = tables[tableName];
3124 if (null != table)
3125 {
3126 RowDictionary<Row> originalRows = new RowDictionary<Row>(table);
3127
3128 // remove the original rows so that they can be added back if they should remain
3129 table.Rows.Clear();
3130
3131 foreach (Row row in originalRows.Values)
3132 {
3133 if (!indexedExtensionRows.Contains(row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter)))
3134 {
3135 table.Rows.Add(row);
3136 }
3137 }
3138 }
3139 }
3140 }
3141
3142 /// <summary>
3143 /// Decompile the tables.
3144 /// </summary>
3145 /// <param name="output">The output being decompiled.</param>
3146 private void DecompileTables(Output output)
3147 {
3148 StringCollection sortedTableNames = this.GetSortedTableNames();
3149
3150 foreach (string tableName in sortedTableNames)
3151 {
3152 Table table = output.Tables[tableName];
3153
3154 // table does not exist in this database or should not be decompiled
3155 if (null == table || !this.DecompilableTable(output, tableName))
3156 {
3157 continue;
3158 }
3159
3160 this.core.OnMessage(WixVerboses.DecompilingTable(table.Name));
3161
3162 // empty tables may be kept with EnsureTable if the user set the proper option
3163 if (0 == table.Rows.Count && this.suppressDroppingEmptyTables)
3164 {
3165 Wix.EnsureTable ensureTable = new Wix.EnsureTable();
3166 ensureTable.Id = table.Name;
3167 this.core.RootElement.AddChild(ensureTable);
3168 }
3169
3170 switch (table.Name)
3171 {
3172 case "_SummaryInformation":
3173 this.Decompile_SummaryInformationTable(table);
3174 break;
3175 case "AdminExecuteSequence":
3176 case "AdminUISequence":
3177 case "AdvtExecuteSequence":
3178 case "InstallExecuteSequence":
3179 case "InstallUISequence":
3180 case "ModuleAdminExecuteSequence":
3181 case "ModuleAdminUISequence":
3182 case "ModuleAdvtExecuteSequence":
3183 case "ModuleInstallExecuteSequence":
3184 case "ModuleInstallUISequence":
3185 // handled in FinalizeSequenceTables
3186 break;
3187 case "ActionText":
3188 this.DecompileActionTextTable(table);
3189 break;
3190 case "AdvtUISequence":
3191 this.core.OnMessage(WixWarnings.DeprecatedTable(table.Name));
3192 break;
3193 case "AppId":
3194 this.DecompileAppIdTable(table);
3195 break;
3196 case "AppSearch":
3197 // handled in FinalizeSearchTables
3198 break;
3199 case "BBControl":
3200 this.DecompileBBControlTable(table);
3201 break;
3202 case "Billboard":
3203 this.DecompileBillboardTable(table);
3204 break;
3205 case "Binary":
3206 this.DecompileBinaryTable(table);
3207 break;
3208 case "BindImage":
3209 this.DecompileBindImageTable(table);
3210 break;
3211 case "CCPSearch":
3212 // handled in FinalizeSearchTables
3213 break;
3214 case "CheckBox":
3215 // handled in FinalizeCheckBoxTable
3216 break;
3217 case "Class":
3218 this.DecompileClassTable(table);
3219 break;
3220 case "ComboBox":
3221 this.DecompileComboBoxTable(table);
3222 break;
3223 case "Control":
3224 this.DecompileControlTable(table);
3225 break;
3226 case "ControlCondition":
3227 this.DecompileControlConditionTable(table);
3228 break;
3229 case "ControlEvent":
3230 this.DecompileControlEventTable(table);
3231 break;
3232 case "CreateFolder":
3233 this.DecompileCreateFolderTable(table);
3234 break;
3235 case "CustomAction":
3236 this.DecompileCustomActionTable(table);
3237 break;
3238 case "CompLocator":
3239 this.DecompileCompLocatorTable(table);
3240 break;
3241 case "Complus":
3242 this.DecompileComplusTable(table);
3243 break;
3244 case "Component":
3245 this.DecompileComponentTable(table);
3246 break;
3247 case "Condition":
3248 this.DecompileConditionTable(table);
3249 break;
3250 case "Dialog":
3251 this.DecompileDialogTable(table);
3252 break;
3253 case "Directory":
3254 this.DecompileDirectoryTable(table);
3255 break;
3256 case "DrLocator":
3257 this.DecompileDrLocatorTable(table);
3258 break;
3259 case "DuplicateFile":
3260 this.DecompileDuplicateFileTable(table);
3261 break;
3262 case "Environment":
3263 this.DecompileEnvironmentTable(table);
3264 break;
3265 case "Error":
3266 this.DecompileErrorTable(table);
3267 break;
3268 case "EventMapping":
3269 this.DecompileEventMappingTable(table);
3270 break;
3271 case "Extension":
3272 this.DecompileExtensionTable(table);
3273 break;
3274 case "ExternalFiles":
3275 this.DecompileExternalFilesTable(table);
3276 break;
3277 case "FamilyFileRanges":
3278 // handled in FinalizeFamilyFileRangesTable
3279 break;
3280 case "Feature":
3281 this.DecompileFeatureTable(table);
3282 break;
3283 case "FeatureComponents":
3284 this.DecompileFeatureComponentsTable(table);
3285 break;
3286 case "File":
3287 this.DecompileFileTable(table);
3288 break;
3289 case "FileSFPCatalog":
3290 this.DecompileFileSFPCatalogTable(table);
3291 break;
3292 case "Font":
3293 this.DecompileFontTable(table);
3294 break;
3295 case "Icon":
3296 this.DecompileIconTable(table);
3297 break;
3298 case "ImageFamilies":
3299 this.DecompileImageFamiliesTable(table);
3300 break;
3301 case "IniFile":
3302 this.DecompileIniFileTable(table);
3303 break;
3304 case "IniLocator":
3305 this.DecompileIniLocatorTable(table);
3306 break;
3307 case "IsolatedComponent":
3308 this.DecompileIsolatedComponentTable(table);
3309 break;
3310 case "LaunchCondition":
3311 this.DecompileLaunchConditionTable(table);
3312 break;
3313 case "ListBox":
3314 this.DecompileListBoxTable(table);
3315 break;
3316 case "ListView":
3317 this.DecompileListViewTable(table);
3318 break;
3319 case "LockPermissions":
3320 this.DecompileLockPermissionsTable(table);
3321 break;
3322 case "Media":
3323 this.DecompileMediaTable(table);
3324 break;
3325 case "MIME":
3326 this.DecompileMIMETable(table);
3327 break;
3328 case "ModuleAdvtUISequence":
3329 this.core.OnMessage(WixWarnings.DeprecatedTable(table.Name));
3330 break;
3331 case "ModuleComponents":
3332 // handled by DecompileComponentTable (since the ModuleComponents table
3333 // rows are created by nesting components under the Module element)
3334 break;
3335 case "ModuleConfiguration":
3336 this.DecompileModuleConfigurationTable(table);
3337 break;
3338 case "ModuleDependency":
3339 this.DecompileModuleDependencyTable(table);
3340 break;
3341 case "ModuleExclusion":
3342 this.DecompileModuleExclusionTable(table);
3343 break;
3344 case "ModuleIgnoreTable":
3345 this.DecompileModuleIgnoreTableTable(table);
3346 break;
3347 case "ModuleSignature":
3348 this.DecompileModuleSignatureTable(table);
3349 break;
3350 case "ModuleSubstitution":
3351 this.DecompileModuleSubstitutionTable(table);
3352 break;
3353 case "MoveFile":
3354 this.DecompileMoveFileTable(table);
3355 break;
3356 case "MsiAssembly":
3357 // handled in FinalizeFileTable
3358 break;
3359 case "MsiDigitalCertificate":
3360 this.DecompileMsiDigitalCertificateTable(table);
3361 break;
3362 case "MsiDigitalSignature":
3363 this.DecompileMsiDigitalSignatureTable(table);
3364 break;
3365 case "MsiEmbeddedChainer":
3366 this.DecompileMsiEmbeddedChainerTable(table);
3367 break;
3368 case "MsiEmbeddedUI":
3369 this.DecompileMsiEmbeddedUITable(table);
3370 break;
3371 case "MsiLockPermissionsEx":
3372 this.DecompileMsiLockPermissionsExTable(table);
3373 break;
3374 case "MsiPackageCertificate":
3375 this.DecompileMsiPackageCertificateTable(table);
3376 break;
3377 case "MsiPatchCertificate":
3378 this.DecompileMsiPatchCertificateTable(table);
3379 break;
3380 case "MsiShortcutProperty":
3381 this.DecompileMsiShortcutPropertyTable(table);
3382 break;
3383 case "ODBCAttribute":
3384 this.DecompileODBCAttributeTable(table);
3385 break;
3386 case "ODBCDataSource":
3387 this.DecompileODBCDataSourceTable(table);
3388 break;
3389 case "ODBCDriver":
3390 this.DecompileODBCDriverTable(table);
3391 break;
3392 case "ODBCSourceAttribute":
3393 this.DecompileODBCSourceAttributeTable(table);
3394 break;
3395 case "ODBCTranslator":
3396 this.DecompileODBCTranslatorTable(table);
3397 break;
3398 case "PatchMetadata":
3399 this.DecompilePatchMetadataTable(table);
3400 break;
3401 case "PatchSequence":
3402 this.DecompilePatchSequenceTable(table);
3403 break;
3404 case "ProgId":
3405 this.DecompileProgIdTable(table);
3406 break;
3407 case "Properties":
3408 this.DecompilePropertiesTable(table);
3409 break;
3410 case "Property":
3411 this.DecompilePropertyTable(table);
3412 break;
3413 case "PublishComponent":
3414 this.DecompilePublishComponentTable(table);
3415 break;
3416 case "RadioButton":
3417 this.DecompileRadioButtonTable(table);
3418 break;
3419 case "Registry":
3420 this.DecompileRegistryTable(table);
3421 break;
3422 case "RegLocator":
3423 this.DecompileRegLocatorTable(table);
3424 break;
3425 case "RemoveFile":
3426 this.DecompileRemoveFileTable(table);
3427 break;
3428 case "RemoveIniFile":
3429 this.DecompileRemoveIniFileTable(table);
3430 break;
3431 case "RemoveRegistry":
3432 this.DecompileRemoveRegistryTable(table);
3433 break;
3434 case "ReserveCost":
3435 this.DecompileReserveCostTable(table);
3436 break;
3437 case "SelfReg":
3438 this.DecompileSelfRegTable(table);
3439 break;
3440 case "ServiceControl":
3441 this.DecompileServiceControlTable(table);
3442 break;
3443 case "ServiceInstall":
3444 this.DecompileServiceInstallTable(table);
3445 break;
3446 case "SFPCatalog":
3447 this.DecompileSFPCatalogTable(table);
3448 break;
3449 case "Shortcut":
3450 this.DecompileShortcutTable(table);
3451 break;
3452 case "Signature":
3453 this.DecompileSignatureTable(table);
3454 break;
3455 case "TargetFiles_OptionalData":
3456 this.DecompileTargetFiles_OptionalDataTable(table);
3457 break;
3458 case "TargetImages":
3459 this.DecompileTargetImagesTable(table);
3460 break;
3461 case "TextStyle":
3462 this.DecompileTextStyleTable(table);
3463 break;
3464 case "TypeLib":
3465 this.DecompileTypeLibTable(table);
3466 break;
3467 case "Upgrade":
3468 this.DecompileUpgradeTable(table);
3469 break;
3470 case "UpgradedFiles_OptionalData":
3471 this.DecompileUpgradedFiles_OptionalDataTable(table);
3472 break;
3473 case "UpgradedFilesToIgnore":
3474 this.DecompileUpgradedFilesToIgnoreTable(table);
3475 break;
3476 case "UpgradedImages":
3477 this.DecompileUpgradedImagesTable(table);
3478 break;
3479 case "UIText":
3480 this.DecompileUITextTable(table);
3481 break;
3482 case "Verb":
3483 this.DecompileVerbTable(table);
3484 break;
3485 default:
3486 DecompilerExtension extension = (DecompilerExtension)this.extensionsByTableName[table.Name];
3487
3488 if (null != extension)
3489 {
3490 extension.DecompileTable(table);
3491 }
3492 else if (!this.suppressCustomTables)
3493 {
3494 this.DecompileCustomTable(table);
3495 }
3496 break;
3497 }
3498 }
3499 }
3500
3501 /// <summary>
3502 /// Determine if a particular table should be decompiled with the current settings.
3503 /// </summary>
3504 /// <param name="output">The output being decompiled.</param>
3505 /// <param name="tableName">The name of a table.</param>
3506 /// <returns>true if the table should be decompiled; false otherwise.</returns>
3507 private bool DecompilableTable(Output output, string tableName)
3508 {
3509 switch (tableName)
3510 {
3511 case "ActionText":
3512 case "BBControl":
3513 case "Billboard":
3514 case "CheckBox":
3515 case "Control":
3516 case "ControlCondition":
3517 case "ControlEvent":
3518 case "Dialog":
3519 case "Error":
3520 case "EventMapping":
3521 case "RadioButton":
3522 case "TextStyle":
3523 case "UIText":
3524 return !this.suppressUI;
3525 case "ModuleAdminExecuteSequence":
3526 case "ModuleAdminUISequence":
3527 case "ModuleAdvtExecuteSequence":
3528 case "ModuleAdvtUISequence":
3529 case "ModuleComponents":
3530 case "ModuleConfiguration":
3531 case "ModuleDependency":
3532 case "ModuleIgnoreTable":
3533 case "ModuleInstallExecuteSequence":
3534 case "ModuleInstallUISequence":
3535 case "ModuleExclusion":
3536 case "ModuleSignature":
3537 case "ModuleSubstitution":
3538 if (OutputType.Module != output.Type)
3539 {
3540 this.core.OnMessage(WixWarnings.SkippingMergeModuleTable(output.SourceLineNumbers, tableName));
3541 return false;
3542 }
3543 else
3544 {
3545 return true;
3546 }
3547 case "ExternalFiles":
3548 case "FamilyFileRanges":
3549 case "ImageFamilies":
3550 case "PatchMetadata":
3551 case "PatchSequence":
3552 case "Properties":
3553 case "TargetFiles_OptionalData":
3554 case "TargetImages":
3555 case "UpgradedFiles_OptionalData":
3556 case "UpgradedFilesToIgnore":
3557 case "UpgradedImages":
3558 if (OutputType.PatchCreation != output.Type)
3559 {
3560 this.core.OnMessage(WixWarnings.SkippingPatchCreationTable(output.SourceLineNumbers, tableName));
3561 return false;
3562 }
3563 else
3564 {
3565 return true;
3566 }
3567 case "MsiPatchHeaders":
3568 case "MsiPatchMetadata":
3569 case "MsiPatchOldAssemblyName":
3570 case "MsiPatchOldAssemblyFile":
3571 case "MsiPatchSequence":
3572 case "Patch":
3573 case "PatchPackage":
3574 this.core.OnMessage(WixWarnings.PatchTable(output.SourceLineNumbers, tableName));
3575 return false;
3576 case "_SummaryInformation":
3577 return true;
3578 case "_Validation":
3579 case "MsiAssemblyName":
3580 case "MsiFileHash":
3581 return false;
3582 default: // all other tables are allowed in any output except for a patch creation package
3583 if (OutputType.PatchCreation == output.Type)
3584 {
3585 this.core.OnMessage(WixWarnings.IllegalPatchCreationTable(output.SourceLineNumbers, tableName));
3586 return false;
3587 }
3588 else
3589 {
3590 return true;
3591 }
3592 }
3593 }
3594
3595 /// <summary>
3596 /// Decompile the _SummaryInformation table.
3597 /// </summary>
3598 /// <param name="table">The table to decompile.</param>
3599 private void Decompile_SummaryInformationTable(Table table)
3600 {
3601 if (OutputType.Module == this.outputType || OutputType.Product == this.outputType)
3602 {
3603 Wix.Package package = new Wix.Package();
3604
3605 foreach (Row row in table.Rows)
3606 {
3607 string value = Convert.ToString(row[1]);
3608
3609 if (null != value && 0 < value.Length)
3610 {
3611 switch (Convert.ToInt32(row[0]))
3612 {
3613 case 1:
3614 if ("1252" != value)
3615 {
3616 package.SummaryCodepage = value;
3617 }
3618 break;
3619 case 3:
3620 package.Description = value;
3621 break;
3622 case 4:
3623 package.Manufacturer = value;
3624 break;
3625 case 5:
3626 if ("Installer" != value)
3627 {
3628 package.Keywords = value;
3629 }
3630 break;
3631 case 6:
3632 package.Comments = value;
3633 break;
3634 case 7:
3635 string[] template = value.Split(';');
3636 if (0 < template.Length && 0 < template[template.Length - 1].Length)
3637 {
3638 package.Languages = template[template.Length - 1];
3639 }
3640
3641 if (1 < template.Length && null != template[0] && 0 < template[0].Length)
3642 {
3643 switch (template[0])
3644 {
3645 case "Intel":
3646 package.Platform = WixToolset.Data.Serialize.Package.PlatformType.x86;
3647 break;
3648 case "Intel64":
3649 package.Platform = WixToolset.Data.Serialize.Package.PlatformType.ia64;
3650 break;
3651 case "x64":
3652 package.Platform = WixToolset.Data.Serialize.Package.PlatformType.x64;
3653 break;
3654 }
3655 }
3656 break;
3657 case 9:
3658 if (OutputType.Module == this.outputType)
3659 {
3660 this.modularizationGuid = value;
3661 package.Id = value;
3662 }
3663 break;
3664 case 14:
3665 package.InstallerVersion = Convert.ToInt32(row[1], CultureInfo.InvariantCulture);
3666 break;
3667 case 15:
3668 int wordCount = Convert.ToInt32(row[1], CultureInfo.InvariantCulture);
3669 if (0x1 == (wordCount & 0x1))
3670 {
3671 this.shortNames = true;
3672 package.ShortNames = Wix.YesNoType.yes;
3673 }
3674
3675 if (0x2 == (wordCount & 0x2))
3676 {
3677 this.compressed = true;
3678
3679 if (OutputType.Product == this.outputType)
3680 {
3681 package.Compressed = Wix.YesNoType.yes;
3682 }
3683 }
3684
3685 if (0x4 == (wordCount & 0x4))
3686 {
3687 package.AdminImage = Wix.YesNoType.yes;
3688 }
3689
3690 if (0x8 == (wordCount & 0x8))
3691 {
3692 package.InstallPrivileges = Wix.Package.InstallPrivilegesType.limited;
3693 }
3694
3695 break;
3696 case 19:
3697 int security = Convert.ToInt32(row[1], CultureInfo.InvariantCulture);
3698 switch (security)
3699 {
3700 case 0:
3701 package.ReadOnly = Wix.YesNoDefaultType.no;
3702 break;
3703 case 4:
3704 package.ReadOnly = Wix.YesNoDefaultType.yes;
3705 break;
3706 }
3707 break;
3708 }
3709 }
3710 }
3711
3712 this.core.RootElement.AddChild(package);
3713 }
3714 else
3715 {
3716 Wix.PatchInformation patchInformation = new Wix.PatchInformation();
3717
3718 foreach (Row row in table.Rows)
3719 {
3720 int propertyId = Convert.ToInt32(row[0]);
3721 string value = Convert.ToString(row[1]);
3722
3723 if (null != row[1] && 0 < value.Length)
3724 {
3725 switch (propertyId)
3726 {
3727 case 1:
3728 if ("1252" != value)
3729 {
3730 patchInformation.SummaryCodepage = value;
3731 }
3732 break;
3733 case 3:
3734 patchInformation.Description = value;
3735 break;
3736 case 4:
3737 patchInformation.Manufacturer = value;
3738 break;
3739 case 5:
3740 if ("Installer,Patching,PCP,Database" != value)
3741 {
3742 patchInformation.Keywords = value;
3743 }
3744 break;
3745 case 6:
3746 patchInformation.Comments = value;
3747 break;
3748 case 7:
3749 string[] template = value.Split(';');
3750 if (0 < template.Length && 0 < template[template.Length - 1].Length)
3751 {
3752 patchInformation.Languages = template[template.Length - 1];
3753 }
3754
3755 if (1 < template.Length && null != template[0] && 0 < template[0].Length)
3756 {
3757 patchInformation.Platforms = template[0];
3758 }
3759 break;
3760 case 15:
3761 int wordCount = Convert.ToInt32(value, CultureInfo.InvariantCulture);
3762 if (0x1 == (wordCount & 0x1))
3763 {
3764 patchInformation.ShortNames = Wix.YesNoType.yes;
3765 }
3766
3767 if (0x2 == (wordCount & 0x2))
3768 {
3769 patchInformation.Compressed = Wix.YesNoType.yes;
3770 }
3771
3772 if (0x4 == (wordCount & 0x4))
3773 {
3774 patchInformation.AdminImage = Wix.YesNoType.yes;
3775 }
3776 break;
3777 case 19:
3778 int security = Convert.ToInt32(value, CultureInfo.InvariantCulture);
3779 switch (security)
3780 {
3781 case 0:
3782 patchInformation.ReadOnly = Wix.YesNoDefaultType.no;
3783 break;
3784 case 4:
3785 patchInformation.ReadOnly = Wix.YesNoDefaultType.yes;
3786 break;
3787 }
3788 break;
3789 }
3790 }
3791 }
3792
3793 this.core.RootElement.AddChild(patchInformation);
3794 }
3795 }
3796
3797 /// <summary>
3798 /// Decompile the ActionText table.
3799 /// </summary>
3800 /// <param name="table">The table to decompile.</param>
3801 private void DecompileActionTextTable(Table table)
3802 {
3803 foreach (Row row in table.Rows)
3804 {
3805 Wix.ProgressText progressText = new Wix.ProgressText();
3806
3807 progressText.Action = Convert.ToString(row[0]);
3808
3809 if (null != row[1])
3810 {
3811 progressText.Content = Convert.ToString(row[1]);
3812 }
3813
3814 if (null != row[2])
3815 {
3816 progressText.Template = Convert.ToString(row[2]);
3817 }
3818
3819 this.core.UIElement.AddChild(progressText);
3820 }
3821 }
3822
3823 /// <summary>
3824 /// Decompile the AppId table.
3825 /// </summary>
3826 /// <param name="table">The table to decompile.</param>
3827 private void DecompileAppIdTable(Table table)
3828 {
3829 foreach (Row row in table.Rows)
3830 {
3831 Wix.AppId appId = new Wix.AppId();
3832
3833 appId.Advertise = Wix.YesNoType.yes;
3834
3835 appId.Id = Convert.ToString(row[0]);
3836
3837 if (null != row[1])
3838 {
3839 appId.RemoteServerName = Convert.ToString(row[1]);
3840 }
3841
3842 if (null != row[2])
3843 {
3844 appId.LocalService = Convert.ToString(row[2]);
3845 }
3846
3847 if (null != row[3])
3848 {
3849 appId.ServiceParameters = Convert.ToString(row[3]);
3850 }
3851
3852 if (null != row[4])
3853 {
3854 appId.DllSurrogate = Convert.ToString(row[4]);
3855 }
3856
3857 if (null != row[5] && Int32.Equals(row[5], 1))
3858 {
3859 appId.ActivateAtStorage = Wix.YesNoType.yes;
3860 }
3861
3862 if (null != row[6] && Int32.Equals(row[6], 1))
3863 {
3864 appId.RunAsInteractiveUser = Wix.YesNoType.yes;
3865 }
3866
3867 this.core.RootElement.AddChild(appId);
3868 this.core.IndexElement(row, appId);
3869 }
3870 }
3871
3872 /// <summary>
3873 /// Decompile the BBControl table.
3874 /// </summary>
3875 /// <param name="table">The table to decompile.</param>
3876 private void DecompileBBControlTable(Table table)
3877 {
3878 foreach (BBControlRow bbControlRow in table.Rows)
3879 {
3880 Wix.Control control = new Wix.Control();
3881
3882 control.Id = bbControlRow.BBControl;
3883
3884 control.Type = bbControlRow.Type;
3885
3886 control.X = bbControlRow.X;
3887
3888 control.Y = bbControlRow.Y;
3889
3890 control.Width = bbControlRow.Width;
3891
3892 control.Height = bbControlRow.Height;
3893
3894 if (null != bbControlRow[7])
3895 {
3896 SetControlAttributes(bbControlRow.Attributes, control);
3897 }
3898
3899 if (null != bbControlRow.Text)
3900 {
3901 control.Text = bbControlRow.Text;
3902 }
3903
3904 Wix.Billboard billboard = (Wix.Billboard)this.core.GetIndexedElement("Billboard", bbControlRow.Billboard);
3905 if (null != billboard)
3906 {
3907 billboard.AddChild(control);
3908 }
3909 else
3910 {
3911 this.core.OnMessage(WixWarnings.ExpectedForeignRow(bbControlRow.SourceLineNumbers, table.Name, bbControlRow.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Billboard_", bbControlRow.Billboard, "Billboard"));
3912 }
3913 }
3914 }
3915
3916 /// <summary>
3917 /// Decompile the Billboard table.
3918 /// </summary>
3919 /// <param name="table">The table to decompile.</param>
3920 private void DecompileBillboardTable(Table table)
3921 {
3922 Hashtable billboardActions = new Hashtable();
3923 SortedList billboards = new SortedList();
3924
3925 foreach (Row row in table.Rows)
3926 {
3927 Wix.Billboard billboard = new Wix.Billboard();
3928
3929 billboard.Id = Convert.ToString(row[0]);
3930
3931 billboard.Feature = Convert.ToString(row[1]);
3932
3933 this.core.IndexElement(row, billboard);
3934 billboards.Add(String.Format(CultureInfo.InvariantCulture, "{0}|{1:0000000000}", row[0], row[3]), row);
3935 }
3936
3937 foreach (Row row in billboards.Values)
3938 {
3939 Wix.Billboard billboard = (Wix.Billboard)this.core.GetIndexedElement(row);
3940 Wix.BillboardAction billboardAction = (Wix.BillboardAction)billboardActions[row[2]];
3941
3942 if (null == billboardAction)
3943 {
3944 billboardAction = new Wix.BillboardAction();
3945
3946 billboardAction.Id = Convert.ToString(row[2]);
3947
3948 this.core.UIElement.AddChild(billboardAction);
3949 billboardActions.Add(row[2], billboardAction);
3950 }
3951
3952 billboardAction.AddChild(billboard);
3953 }
3954 }
3955
3956 /// <summary>
3957 /// Decompile the Binary table.
3958 /// </summary>
3959 /// <param name="table">The table to decompile.</param>
3960 private void DecompileBinaryTable(Table table)
3961 {
3962 foreach (Row row in table.Rows)
3963 {
3964 Wix.Binary binary = new Wix.Binary();
3965
3966 binary.Id = Convert.ToString(row[0]);
3967
3968 binary.SourceFile = Convert.ToString(row[1]);
3969
3970 this.core.RootElement.AddChild(binary);
3971 }
3972 }
3973
3974 /// <summary>
3975 /// Decompile the BindImage table.
3976 /// </summary>
3977 /// <param name="table">The table to decompile.</param>
3978 private void DecompileBindImageTable(Table table)
3979 {
3980 foreach (Row row in table.Rows)
3981 {
3982 Wix.File file = (Wix.File)this.core.GetIndexedElement("File", Convert.ToString(row[0]));
3983
3984 if (null != file)
3985 {
3986 file.BindPath = Convert.ToString(row[1]);
3987 }
3988 else
3989 {
3990 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "File_", Convert.ToString(row[0]), "File"));
3991 }
3992 }
3993 }
3994
3995 /// <summary>
3996 /// Decompile the Class table.
3997 /// </summary>
3998 /// <param name="table">The table to decompile.</param>
3999 private void DecompileClassTable(Table table)
4000 {
4001 foreach (Row row in table.Rows)
4002 {
4003 Wix.Class wixClass = new Wix.Class();
4004
4005 wixClass.Advertise = Wix.YesNoType.yes;
4006
4007 wixClass.Id = Convert.ToString(row[0]);
4008
4009 switch (Convert.ToString(row[1]))
4010 {
4011 case "LocalServer":
4012 wixClass.Context = Wix.Class.ContextType.LocalServer;
4013 break;
4014 case "LocalServer32":
4015 wixClass.Context = Wix.Class.ContextType.LocalServer32;
4016 break;
4017 case "InprocServer":
4018 wixClass.Context = Wix.Class.ContextType.InprocServer;
4019 break;
4020 case "InprocServer32":
4021 wixClass.Context = Wix.Class.ContextType.InprocServer32;
4022 break;
4023 default:
4024 this.core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[1].Column.Name, row[1]));
4025 break;
4026 }
4027
4028 // ProgId children are handled in FinalizeProgIdTable
4029
4030 if (null != row[4])
4031 {
4032 wixClass.Description = Convert.ToString(row[4]);
4033 }
4034
4035 if (null != row[5])
4036 {
4037 wixClass.AppId = Convert.ToString(row[5]);
4038 }
4039
4040 if (null != row[6])
4041 {
4042 string[] fileTypeMaskStrings = (Convert.ToString(row[6])).Split(';');
4043
4044 try
4045 {
4046 foreach (string fileTypeMaskString in fileTypeMaskStrings)
4047 {
4048 string[] fileTypeMaskParts = fileTypeMaskString.Split(',');
4049
4050 if (4 == fileTypeMaskParts.Length)
4051 {
4052 Wix.FileTypeMask fileTypeMask = new Wix.FileTypeMask();
4053
4054 fileTypeMask.Offset = Convert.ToInt32(fileTypeMaskParts[0], CultureInfo.InvariantCulture);
4055
4056 fileTypeMask.Mask = fileTypeMaskParts[2];
4057
4058 fileTypeMask.Value = fileTypeMaskParts[3];
4059
4060 wixClass.AddChild(fileTypeMask);
4061 }
4062 else
4063 {
4064 // TODO: warn
4065 }
4066 }
4067 }
4068 catch (FormatException)
4069 {
4070 this.core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[6].Column.Name, row[6]));
4071 }
4072 catch (OverflowException)
4073 {
4074 this.core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[6].Column.Name, row[6]));
4075 }
4076 }
4077
4078 if (null != row[7])
4079 {
4080 wixClass.Icon = Convert.ToString(row[7]);
4081 }
4082
4083 if (null != row[8])
4084 {
4085 wixClass.IconIndex = Convert.ToInt32(row[8]);
4086 }
4087
4088 if (null != row[9])
4089 {
4090 wixClass.Handler = Convert.ToString(row[9]);
4091 }
4092
4093 if (null != row[10])
4094 {
4095 wixClass.Argument = Convert.ToString(row[10]);
4096 }
4097
4098 if (null != row[12])
4099 {
4100 if (1 == Convert.ToInt32(row[12]))
4101 {
4102 wixClass.RelativePath = Wix.YesNoType.yes;
4103 }
4104 else
4105 {
4106 this.core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[12].Column.Name, row[12]));
4107 }
4108 }
4109
4110 Wix.Component component = (Wix.Component)this.core.GetIndexedElement("Component", Convert.ToString(row[2]));
4111 if (null != component)
4112 {
4113 component.AddChild(wixClass);
4114 }
4115 else
4116 {
4117 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", Convert.ToString(row[2]), "Component"));
4118 }
4119
4120 this.core.IndexElement(row, wixClass);
4121 }
4122 }
4123
4124 /// <summary>
4125 /// Decompile the ComboBox table.
4126 /// </summary>
4127 /// <param name="table">The table to decompile.</param>
4128 private void DecompileComboBoxTable(Table table)
4129 {
4130 Wix.ComboBox comboBox = null;
4131 SortedList comboBoxRows = new SortedList();
4132
4133 // sort the combo boxes by their property and order
4134 foreach (Row row in table.Rows)
4135 {
4136 comboBoxRows.Add(String.Concat("{0}|{1:0000000000}", row[0], row[1]), row);
4137 }
4138
4139 foreach (Row row in comboBoxRows.Values)
4140 {
4141 if (null == comboBox || Convert.ToString(row[0]) != comboBox.Property)
4142 {
4143 comboBox = new Wix.ComboBox();
4144
4145 comboBox.Property = Convert.ToString(row[0]);
4146
4147 this.core.UIElement.AddChild(comboBox);
4148 }
4149
4150 Wix.ListItem listItem = new Wix.ListItem();
4151
4152 listItem.Value = Convert.ToString(row[2]);
4153
4154 if (null != row[3])
4155 {
4156 listItem.Text = Convert.ToString(row[3]);
4157 }
4158
4159 comboBox.AddChild(listItem);
4160 }
4161 }
4162
4163 /// <summary>
4164 /// Decompile the Control table.
4165 /// </summary>
4166 /// <param name="table">The table to decompile.</param>
4167 private void DecompileControlTable(Table table)
4168 {
4169 foreach (ControlRow controlRow in table.Rows)
4170 {
4171 Wix.Control control = new Wix.Control();
4172
4173 control.Id = controlRow.Control;
4174
4175 control.Type = controlRow.Type;
4176
4177 control.X = controlRow.X;
4178
4179 control.Y = controlRow.Y;
4180
4181 control.Width = controlRow.Width;
4182
4183 control.Height = controlRow.Height;
4184
4185 if (null != controlRow[7])
4186 {
4187 string[] specialAttributes;
4188
4189 // sets various common attributes like Disabled, Indirect, Integer, ...
4190 SetControlAttributes(controlRow.Attributes, control);
4191
4192 switch (control.Type)
4193 {
4194 case "Bitmap":
4195 specialAttributes = MsiInterop.BitmapControlAttributes;
4196 break;
4197 case "CheckBox":
4198 specialAttributes = MsiInterop.CheckboxControlAttributes;
4199 break;
4200 case "ComboBox":
4201 specialAttributes = MsiInterop.ComboboxControlAttributes;
4202 break;
4203 case "DirectoryCombo":
4204 specialAttributes = MsiInterop.VolumeControlAttributes;
4205 break;
4206 case "Edit":
4207 specialAttributes = MsiInterop.EditControlAttributes;
4208 break;
4209 case "Icon":
4210 specialAttributes = MsiInterop.IconControlAttributes;
4211 break;
4212 case "ListBox":
4213 specialAttributes = MsiInterop.ListboxControlAttributes;
4214 break;
4215 case "ListView":
4216 specialAttributes = MsiInterop.ListviewControlAttributes;
4217 break;
4218 case "MaskedEdit":
4219 specialAttributes = MsiInterop.EditControlAttributes;
4220 break;
4221 case "PathEdit":
4222 specialAttributes = MsiInterop.EditControlAttributes;
4223 break;
4224 case "ProgressBar":
4225 specialAttributes = MsiInterop.ProgressControlAttributes;
4226 break;
4227 case "PushButton":
4228 specialAttributes = MsiInterop.ButtonControlAttributes;
4229 break;
4230 case "RadioButtonGroup":
4231 specialAttributes = MsiInterop.RadioControlAttributes;
4232 break;
4233 case "Text":
4234 specialAttributes = MsiInterop.TextControlAttributes;
4235 break;
4236 case "VolumeCostList":
4237 specialAttributes = MsiInterop.VolumeControlAttributes;
4238 break;
4239 case "VolumeSelectCombo":
4240 specialAttributes = MsiInterop.VolumeControlAttributes;
4241 break;
4242 default:
4243 specialAttributes = null;
4244 break;
4245 }
4246
4247 if (null != specialAttributes)
4248 {
4249 bool iconSizeSet = false;
4250
4251 for (int i = 16; 32 > i; i++)
4252 {
4253 if (1 == ((controlRow.Attributes >> i) & 1))
4254 {
4255 string attribute = null;
4256
4257 if (specialAttributes.Length > (i - 16))
4258 {
4259 attribute = specialAttributes[i - 16];
4260 }
4261
4262 // unknown attribute
4263 if (null == attribute)
4264 {
4265 this.core.OnMessage(WixWarnings.IllegalColumnValue(controlRow.SourceLineNumbers, table.Name, controlRow.Fields[7].Column.Name, controlRow.Attributes));
4266 continue;
4267 }
4268
4269 switch (attribute)
4270 {
4271 case "Bitmap":
4272 control.Bitmap = Wix.YesNoType.yes;
4273 break;
4274 case "CDROM":
4275 control.CDROM = Wix.YesNoType.yes;
4276 break;
4277 case "ComboList":
4278 control.ComboList = Wix.YesNoType.yes;
4279 break;
4280 case "ElevationShield":
4281 control.ElevationShield = Wix.YesNoType.yes;
4282 break;
4283 case "Fixed":
4284 control.Fixed = Wix.YesNoType.yes;
4285 break;
4286 case "FixedSize":
4287 control.FixedSize = Wix.YesNoType.yes;
4288 break;
4289 case "Floppy":
4290 control.Floppy = Wix.YesNoType.yes;
4291 break;
4292 case "FormatSize":
4293 control.FormatSize = Wix.YesNoType.yes;
4294 break;
4295 case "HasBorder":
4296 control.HasBorder = Wix.YesNoType.yes;
4297 break;
4298 case "Icon":
4299 control.Icon = Wix.YesNoType.yes;
4300 break;
4301 case "Icon16":
4302 if (iconSizeSet)
4303 {
4304 control.IconSize = Wix.Control.IconSizeType.Item48;
4305 }
4306 else
4307 {
4308 iconSizeSet = true;
4309 control.IconSize = Wix.Control.IconSizeType.Item16;
4310 }
4311 break;
4312 case "Icon32":
4313 if (iconSizeSet)
4314 {
4315 control.IconSize = Wix.Control.IconSizeType.Item48;
4316 }
4317 else
4318 {
4319 iconSizeSet = true;
4320 control.IconSize = Wix.Control.IconSizeType.Item32;
4321 }
4322 break;
4323 case "Image":
4324 control.Image = Wix.YesNoType.yes;
4325 break;
4326 case "Multiline":
4327 control.Multiline = Wix.YesNoType.yes;
4328 break;
4329 case "NoPrefix":
4330 control.NoPrefix = Wix.YesNoType.yes;
4331 break;
4332 case "NoWrap":
4333 control.NoWrap = Wix.YesNoType.yes;
4334 break;
4335 case "Password":
4336 control.Password = Wix.YesNoType.yes;
4337 break;
4338 case "ProgressBlocks":
4339 control.ProgressBlocks = Wix.YesNoType.yes;
4340 break;
4341 case "PushLike":
4342 control.PushLike = Wix.YesNoType.yes;
4343 break;
4344 case "RAMDisk":
4345 control.RAMDisk = Wix.YesNoType.yes;
4346 break;
4347 case "Remote":
4348 control.Remote = Wix.YesNoType.yes;
4349 break;
4350 case "Removable":
4351 control.Removable = Wix.YesNoType.yes;
4352 break;
4353 case "ShowRollbackCost":
4354 control.ShowRollbackCost = Wix.YesNoType.yes;
4355 break;
4356 case "Sorted":
4357 control.Sorted = Wix.YesNoType.yes;
4358 break;
4359 case "Transparent":
4360 control.Transparent = Wix.YesNoType.yes;
4361 break;
4362 case "UserLanguage":
4363 control.UserLanguage = Wix.YesNoType.yes;
4364 break;
4365 default:
4366 throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnknowControlAttribute, attribute));
4367 }
4368 }
4369 }
4370 }
4371 else if (0 < (controlRow.Attributes & 0xFFFF0000))
4372 {
4373 this.core.OnMessage(WixWarnings.IllegalColumnValue(controlRow.SourceLineNumbers, table.Name, controlRow.Fields[7].Column.Name, controlRow.Attributes));
4374 }
4375 }
4376
4377 // FinalizeCheckBoxTable adds Control/@Property|@CheckBoxPropertyRef
4378 if (null != controlRow.Property && 0 != String.CompareOrdinal("CheckBox", control.Type))
4379 {
4380 control.Property = controlRow.Property;
4381 }
4382
4383 if (null != controlRow.Text)
4384 {
4385 control.Text = controlRow.Text;
4386 }
4387
4388 if (null != controlRow.Help)
4389 {
4390 string[] help = controlRow.Help.Split('|');
4391
4392 if (2 == help.Length)
4393 {
4394 if (0 < help[0].Length)
4395 {
4396 control.ToolTip = help[0];
4397 }
4398
4399 if (0 < help[1].Length)
4400 {
4401 control.Help = help[1];
4402 }
4403 }
4404 }
4405
4406 this.core.IndexElement(controlRow, control);
4407 }
4408 }
4409
4410 /// <summary>
4411 /// Decompile the ControlCondition table.
4412 /// </summary>
4413 /// <param name="table">The table to decompile.</param>
4414 private void DecompileControlConditionTable(Table table)
4415 {
4416 foreach (Row row in table.Rows)
4417 {
4418 Wix.Condition condition = new Wix.Condition();
4419
4420 switch (Convert.ToString(row[2]))
4421 {
4422 case "Default":
4423 condition.Action = Wix.Condition.ActionType.@default;
4424 break;
4425 case "Disable":
4426 condition.Action = Wix.Condition.ActionType.disable;
4427 break;
4428 case "Enable":
4429 condition.Action = Wix.Condition.ActionType.enable;
4430 break;
4431 case "Hide":
4432 condition.Action = Wix.Condition.ActionType.hide;
4433 break;
4434 case "Show":
4435 condition.Action = Wix.Condition.ActionType.show;
4436 break;
4437 default:
4438 this.core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[2].Column.Name, row[2]));
4439 break;
4440 }
4441
4442 condition.Content = Convert.ToString(row[3]);
4443
4444 Wix.Control control = (Wix.Control)this.core.GetIndexedElement("Control", Convert.ToString(row[0]), Convert.ToString(row[1]));
4445 if (null != control)
4446 {
4447 control.AddChild(condition);
4448 }
4449 else
4450 {
4451 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Dialog_", Convert.ToString(row[0]), "Control_", Convert.ToString(row[1]), "Control"));
4452 }
4453 }
4454 }
4455
4456 /// <summary>
4457 /// Decompile the ControlEvent table.
4458 /// </summary>
4459 /// <param name="table">The table to decompile.</param>
4460 private void DecompileControlEventTable(Table table)
4461 {
4462 SortedList controlEvents = new SortedList();
4463
4464 foreach (Row row in table.Rows)
4465 {
4466 Wix.Publish publish = new Wix.Publish();
4467
4468 string publishEvent = Convert.ToString(row[2]);
4469 if (publishEvent.StartsWith("[", StringComparison.Ordinal) && publishEvent.EndsWith("]", StringComparison.Ordinal))
4470 {
4471 publish.Property = publishEvent.Substring(1, publishEvent.Length - 2);
4472
4473 if ("{}" != Convert.ToString(row[3]))
4474 {
4475 publish.Value = Convert.ToString(row[3]);
4476 }
4477 }
4478 else
4479 {
4480 publish.Event = publishEvent;
4481 publish.Value = Convert.ToString(row[3]);
4482 }
4483
4484 if (null != row[4])
4485 {
4486 publish.Content = Convert.ToString(row[4]);
4487 }
4488
4489 controlEvents.Add(String.Format(CultureInfo.InvariantCulture, "{0}|{1}|{2:0000000000}|{3}|{4}|{5}", row[0], row[1], (null == row[5] ? 0 : Convert.ToInt32(row[5])), row[2], row[3], row[4]), row);
4490
4491 this.core.IndexElement(row, publish);
4492 }
4493
4494 foreach (Row row in controlEvents.Values)
4495 {
4496 Wix.Control control = (Wix.Control)this.core.GetIndexedElement("Control", Convert.ToString(row[0]), Convert.ToString(row[1]));
4497 Wix.Publish publish = (Wix.Publish)this.core.GetIndexedElement(row);
4498
4499 if (null != control)
4500 {
4501 control.AddChild(publish);
4502 }
4503 else
4504 {
4505 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Dialog_", Convert.ToString(row[0]), "Control_", Convert.ToString(row[1]), "Control"));
4506 }
4507 }
4508 }
4509
4510 /// <summary>
4511 /// Decompile a custom table.
4512 /// </summary>
4513 /// <param name="table">The table to decompile.</param>
4514 private void DecompileCustomTable(Table table)
4515 {
4516 if (0 < table.Rows.Count || this.suppressDroppingEmptyTables)
4517 {
4518 Wix.CustomTable customTable = new Wix.CustomTable();
4519
4520 this.core.OnMessage(WixWarnings.DecompilingAsCustomTable(table.Rows[0].SourceLineNumbers, table.Name));
4521
4522 customTable.Id = table.Name;
4523
4524 foreach (ColumnDefinition columnDefinition in table.Definition.Columns)
4525 {
4526 Wix.Column column = new Wix.Column();
4527
4528 column.Id = columnDefinition.Name;
4529
4530 if (ColumnCategory.Unknown != columnDefinition.Category)
4531 {
4532 switch (columnDefinition.Category)
4533 {
4534 case ColumnCategory.Text:
4535 column.Category = Wix.Column.CategoryType.Text;
4536 break;
4537 case ColumnCategory.UpperCase:
4538 column.Category = Wix.Column.CategoryType.UpperCase;
4539 break;
4540 case ColumnCategory.LowerCase:
4541 column.Category = Wix.Column.CategoryType.LowerCase;
4542 break;
4543 case ColumnCategory.Integer:
4544 column.Category = Wix.Column.CategoryType.Integer;
4545 break;
4546 case ColumnCategory.DoubleInteger:
4547 column.Category = Wix.Column.CategoryType.DoubleInteger;
4548 break;
4549 case ColumnCategory.TimeDate:
4550 column.Category = Wix.Column.CategoryType.TimeDate;
4551 break;
4552 case ColumnCategory.Identifier:
4553 column.Category = Wix.Column.CategoryType.Identifier;
4554 break;
4555 case ColumnCategory.Property:
4556 column.Category = Wix.Column.CategoryType.Property;
4557 break;
4558 case ColumnCategory.Filename:
4559 column.Category = Wix.Column.CategoryType.Filename;
4560 break;
4561 case ColumnCategory.WildCardFilename:
4562 column.Category = Wix.Column.CategoryType.WildCardFilename;
4563 break;
4564 case ColumnCategory.Path:
4565 column.Category = Wix.Column.CategoryType.Path;
4566 break;
4567 case ColumnCategory.Paths:
4568 column.Category = Wix.Column.CategoryType.Paths;
4569 break;
4570 case ColumnCategory.AnyPath:
4571 column.Category = Wix.Column.CategoryType.AnyPath;
4572 break;
4573 case ColumnCategory.DefaultDir:
4574 column.Category = Wix.Column.CategoryType.DefaultDir;
4575 break;
4576 case ColumnCategory.RegPath:
4577 column.Category = Wix.Column.CategoryType.RegPath;
4578 break;
4579 case ColumnCategory.Formatted:
4580 column.Category = Wix.Column.CategoryType.Formatted;
4581 break;
4582 case ColumnCategory.FormattedSDDLText:
4583 column.Category = Wix.Column.CategoryType.FormattedSddl;
4584 break;
4585 case ColumnCategory.Template:
4586 column.Category = Wix.Column.CategoryType.Template;
4587 break;
4588 case ColumnCategory.Condition:
4589 column.Category = Wix.Column.CategoryType.Condition;
4590 break;
4591 case ColumnCategory.Guid:
4592 column.Category = Wix.Column.CategoryType.Guid;
4593 break;
4594 case ColumnCategory.Version:
4595 column.Category = Wix.Column.CategoryType.Version;
4596 break;
4597 case ColumnCategory.Language:
4598 column.Category = Wix.Column.CategoryType.Language;
4599 break;
4600 case ColumnCategory.Binary:
4601 column.Category = Wix.Column.CategoryType.Binary;
4602 break;
4603 case ColumnCategory.CustomSource:
4604 column.Category = Wix.Column.CategoryType.CustomSource;
4605 break;
4606 case ColumnCategory.Cabinet:
4607 column.Category = Wix.Column.CategoryType.Cabinet;
4608 break;
4609 case ColumnCategory.Shortcut:
4610 column.Category = Wix.Column.CategoryType.Shortcut;
4611 break;
4612 default:
4613 throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnknownCustomColumnCategory, columnDefinition.Category.ToString()));
4614 }
4615 }
4616
4617 if (null != columnDefinition.Description)
4618 {
4619 column.Description = columnDefinition.Description;
4620 }
4621
4622 if (columnDefinition.IsKeyColumnSet)
4623 {
4624 column.KeyColumn = columnDefinition.KeyColumn;
4625 }
4626
4627 if (null != columnDefinition.KeyTable)
4628 {
4629 column.KeyTable = columnDefinition.KeyTable;
4630 }
4631
4632 if (columnDefinition.IsLocalizable)
4633 {
4634 column.Localizable = Wix.YesNoType.yes;
4635 }
4636
4637 if (columnDefinition.IsMaxValueSet)
4638 {
4639 column.MaxValue = columnDefinition.MaxValue;
4640 }
4641
4642 if (columnDefinition.IsMinValueSet)
4643 {
4644 column.MinValue = columnDefinition.MinValue;
4645 }
4646
4647 if (ColumnModularizeType.None != columnDefinition.ModularizeType)
4648 {
4649 switch (columnDefinition.ModularizeType)
4650 {
4651 case ColumnModularizeType.Column:
4652 column.Modularize = Wix.Column.ModularizeType.Column;
4653 break;
4654 case ColumnModularizeType.Condition:
4655 column.Modularize = Wix.Column.ModularizeType.Condition;
4656 break;
4657 case ColumnModularizeType.Icon:
4658 column.Modularize = Wix.Column.ModularizeType.Icon;
4659 break;
4660 case ColumnModularizeType.Property:
4661 column.Modularize = Wix.Column.ModularizeType.Property;
4662 break;
4663 case ColumnModularizeType.SemicolonDelimited:
4664 column.Modularize = Wix.Column.ModularizeType.SemicolonDelimited;
4665 break;
4666 default:
4667 throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnknownCustomColumnModularizationType, columnDefinition.ModularizeType.ToString()));
4668 }
4669 }
4670
4671 if (columnDefinition.Nullable)
4672 {
4673 column.Nullable = Wix.YesNoType.yes;
4674 }
4675
4676 if (columnDefinition.PrimaryKey)
4677 {
4678 column.PrimaryKey = Wix.YesNoType.yes;
4679 }
4680
4681 if (null != columnDefinition.Possibilities)
4682 {
4683 column.Set = columnDefinition.Possibilities;
4684 }
4685
4686 if (ColumnType.Unknown != columnDefinition.Type)
4687 {
4688 switch (columnDefinition.Type)
4689 {
4690 case ColumnType.Localized:
4691 column.Localizable = Wix.YesNoType.yes;
4692 column.Type = Wix.Column.TypeType.@string;
4693 break;
4694 case ColumnType.Number:
4695 column.Type = Wix.Column.TypeType.@int;
4696 break;
4697 case ColumnType.Object:
4698 column.Type = Wix.Column.TypeType.binary;
4699 break;
4700 case ColumnType.Preserved:
4701 case ColumnType.String:
4702 column.Type = Wix.Column.TypeType.@string;
4703 break;
4704 default:
4705 throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnknownCustomColumnType, columnDefinition.Type.ToString()));
4706 }
4707 }
4708
4709 column.Width = columnDefinition.Length;
4710
4711 customTable.AddChild(column);
4712 }
4713
4714 foreach (Row row in table.Rows)
4715 {
4716 Wix.Row wixRow = new Wix.Row();
4717
4718 foreach (Field field in row.Fields)
4719 {
4720 Wix.Data data = new Wix.Data();
4721
4722 data.Column = field.Column.Name;
4723
4724 data.Content = Convert.ToString(field.Data, CultureInfo.InvariantCulture);
4725
4726 wixRow.AddChild(data);
4727 }
4728
4729 customTable.AddChild(wixRow);
4730 }
4731
4732 this.core.RootElement.AddChild(customTable);
4733 }
4734 }
4735
4736 /// <summary>
4737 /// Decompile the CreateFolder table.
4738 /// </summary>
4739 /// <param name="table">The table to decompile.</param>
4740 private void DecompileCreateFolderTable(Table table)
4741 {
4742 foreach (Row row in table.Rows)
4743 {
4744 Wix.CreateFolder createFolder = new Wix.CreateFolder();
4745
4746 createFolder.Directory = Convert.ToString(row[0]);
4747
4748 Wix.Component component = (Wix.Component)this.core.GetIndexedElement("Component", Convert.ToString(row[1]));
4749 if (null != component)
4750 {
4751 component.AddChild(createFolder);
4752 }
4753 else
4754 {
4755 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", Convert.ToString(row[1]), "Component"));
4756 }
4757 this.core.IndexElement(row, createFolder);
4758 }
4759 }
4760
4761 /// <summary>
4762 /// Decompile the CustomAction table.
4763 /// </summary>
4764 /// <param name="table">The table to decompile.</param>
4765 private void DecompileCustomActionTable(Table table)
4766 {
4767 foreach (Row row in table.Rows)
4768 {
4769 Wix.CustomAction customAction = new Wix.CustomAction();
4770
4771 customAction.Id = Convert.ToString(row[0]);
4772
4773 int type = Convert.ToInt32(row[1]);
4774
4775 if (MsiInterop.MsidbCustomActionTypeHideTarget == (type & MsiInterop.MsidbCustomActionTypeHideTarget))
4776 {
4777 customAction.HideTarget = Wix.YesNoType.yes;
4778 }
4779
4780 if (MsiInterop.MsidbCustomActionTypeNoImpersonate == (type & MsiInterop.MsidbCustomActionTypeNoImpersonate))
4781 {
4782 customAction.Impersonate = Wix.YesNoType.no;
4783 }
4784
4785 if (MsiInterop.MsidbCustomActionTypeTSAware == (type & MsiInterop.MsidbCustomActionTypeTSAware))
4786 {
4787 customAction.TerminalServerAware = Wix.YesNoType.yes;
4788 }
4789
4790 if (MsiInterop.MsidbCustomActionType64BitScript == (type & MsiInterop.MsidbCustomActionType64BitScript))
4791 {
4792 customAction.Win64 = Wix.YesNoType.yes;
4793 }
4794
4795 switch (type & MsiInterop.MsidbCustomActionTypeExecuteBits)
4796 {
4797 case 0:
4798 // this is the default value
4799 break;
4800 case MsiInterop.MsidbCustomActionTypeFirstSequence:
4801 customAction.Execute = Wix.CustomAction.ExecuteType.firstSequence;
4802 break;
4803 case MsiInterop.MsidbCustomActionTypeOncePerProcess:
4804 customAction.Execute = Wix.CustomAction.ExecuteType.oncePerProcess;
4805 break;
4806 case MsiInterop.MsidbCustomActionTypeClientRepeat:
4807 customAction.Execute = Wix.CustomAction.ExecuteType.secondSequence;
4808 break;
4809 case MsiInterop.MsidbCustomActionTypeInScript:
4810 customAction.Execute = Wix.CustomAction.ExecuteType.deferred;
4811 break;
4812 case MsiInterop.MsidbCustomActionTypeInScript + MsiInterop.MsidbCustomActionTypeRollback:
4813 customAction.Execute = Wix.CustomAction.ExecuteType.rollback;
4814 break;
4815 case MsiInterop.MsidbCustomActionTypeInScript + MsiInterop.MsidbCustomActionTypeCommit:
4816 customAction.Execute = Wix.CustomAction.ExecuteType.commit;
4817 break;
4818 default:
4819 this.core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[1].Column.Name, row[1]));
4820 break;
4821 }
4822
4823 switch (type & MsiInterop.MsidbCustomActionTypeReturnBits)
4824 {
4825 case 0:
4826 // this is the default value
4827 break;
4828 case MsiInterop.MsidbCustomActionTypeContinue:
4829 customAction.Return = Wix.CustomAction.ReturnType.ignore;
4830 break;
4831 case MsiInterop.MsidbCustomActionTypeAsync:
4832 customAction.Return = Wix.CustomAction.ReturnType.asyncWait;
4833 break;
4834 case MsiInterop.MsidbCustomActionTypeAsync + MsiInterop.MsidbCustomActionTypeContinue:
4835 customAction.Return = Wix.CustomAction.ReturnType.asyncNoWait;
4836 break;
4837 default:
4838 this.core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[1].Column.Name, row[1]));
4839 break;
4840 }
4841
4842 int source = type & MsiInterop.MsidbCustomActionTypeSourceBits;
4843 switch (source)
4844 {
4845 case MsiInterop.MsidbCustomActionTypeBinaryData:
4846 customAction.BinaryKey = Convert.ToString(row[2]);
4847 break;
4848 case MsiInterop.MsidbCustomActionTypeSourceFile:
4849 if (null != row[2])
4850 {
4851 customAction.FileKey = Convert.ToString(row[2]);
4852 }
4853 break;
4854 case MsiInterop.MsidbCustomActionTypeDirectory:
4855 if (null != row[2])
4856 {
4857 customAction.Directory = Convert.ToString(row[2]);
4858 }
4859 break;
4860 case MsiInterop.MsidbCustomActionTypeProperty:
4861 customAction.Property = Convert.ToString(row[2]);
4862 break;
4863 default:
4864 this.core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[1].Column.Name, row[1]));
4865 break;
4866 }
4867
4868 switch (type & MsiInterop.MsidbCustomActionTypeTargetBits)
4869 {
4870 case MsiInterop.MsidbCustomActionTypeDll:
4871 customAction.DllEntry = Convert.ToString(row[3]);
4872 break;
4873 case MsiInterop.MsidbCustomActionTypeExe:
4874 customAction.ExeCommand = Convert.ToString(row[3]);
4875 break;
4876 case MsiInterop.MsidbCustomActionTypeTextData:
4877 if (MsiInterop.MsidbCustomActionTypeSourceFile == source)
4878 {
4879 customAction.Error = Convert.ToString(row[3]);
4880 }
4881 else
4882 {
4883 customAction.Value = Convert.ToString(row[3]);
4884 }
4885 break;
4886 case MsiInterop.MsidbCustomActionTypeJScript:
4887 if (MsiInterop.MsidbCustomActionTypeDirectory == source)
4888 {
4889 customAction.Script = Wix.CustomAction.ScriptType.jscript;
4890 customAction.Content = Convert.ToString(row[3]);
4891 }
4892 else
4893 {
4894 customAction.JScriptCall = Convert.ToString(row[3]);
4895 }
4896 break;
4897 case MsiInterop.MsidbCustomActionTypeVBScript:
4898 if (MsiInterop.MsidbCustomActionTypeDirectory == source)
4899 {
4900 customAction.Script = Wix.CustomAction.ScriptType.vbscript;
4901 customAction.Content = Convert.ToString(row[3]);
4902 }
4903 else
4904 {
4905 customAction.VBScriptCall = Convert.ToString(row[3]);
4906 }
4907 break;
4908 case MsiInterop.MsidbCustomActionTypeInstall:
4909 this.core.OnMessage(WixWarnings.NestedInstall(row.SourceLineNumbers, table.Name, row.Fields[1].Column.Name, row[1]));
4910 continue;
4911 default:
4912 this.core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[1].Column.Name, row[1]));
4913 break;
4914 }
4915
4916 int extype = 4 < row.Fields.Length && null != row[4] ? Convert.ToInt32(row[4]) : 0;
4917 if (MsiInterop.MsidbCustomActionTypePatchUninstall == (extype & MsiInterop.MsidbCustomActionTypePatchUninstall))
4918 {
4919 customAction.PatchUninstall = Wix.YesNoType.yes;
4920 }
4921
4922 this.core.RootElement.AddChild(customAction);
4923 this.core.IndexElement(row, customAction);
4924 }
4925 }
4926
4927 /// <summary>
4928 /// Decompile the CompLocator table.
4929 /// </summary>
4930 /// <param name="table">The table to decompile.</param>
4931 private void DecompileCompLocatorTable(Table table)
4932 {
4933 foreach (Row row in table.Rows)
4934 {
4935 Wix.ComponentSearch componentSearch = new Wix.ComponentSearch();
4936
4937 componentSearch.Id = Convert.ToString(row[0]);
4938
4939 componentSearch.Guid = Convert.ToString(row[1]);
4940
4941 if (null != row[2])
4942 {
4943 switch (Convert.ToInt32(row[2]))
4944 {
4945 case MsiInterop.MsidbLocatorTypeDirectory:
4946 componentSearch.Type = Wix.ComponentSearch.TypeType.directory;
4947 break;
4948 case MsiInterop.MsidbLocatorTypeFileName:
4949 // this is the default value
4950 break;
4951 default:
4952 this.core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[2].Column.Name, row[2]));
4953 break;
4954 }
4955 }
4956
4957 this.core.IndexElement(row, componentSearch);
4958 }
4959 }
4960
4961 /// <summary>
4962 /// Decompile the Complus table.
4963 /// </summary>
4964 /// <param name="table">The table to decompile.</param>
4965 private void DecompileComplusTable(Table table)
4966 {
4967 foreach (Row row in table.Rows)
4968 {
4969 if (null != row[1])
4970 {
4971 Wix.Component component = (Wix.Component)this.core.GetIndexedElement("Component", Convert.ToString(row[0]));
4972
4973 if (null != component)
4974 {
4975 component.ComPlusFlags = Convert.ToInt32(row[1]);
4976 }
4977 else
4978 {
4979 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", Convert.ToString(row[0]), "Component"));
4980 }
4981 }
4982 }
4983 }
4984
4985 /// <summary>
4986 /// Decompile the Component table.
4987 /// </summary>
4988 /// <param name="table">The table to decompile.</param>
4989 private void DecompileComponentTable(Table table)
4990 {
4991 foreach (Row row in table.Rows)
4992 {
4993 Wix.Component component = new Wix.Component();
4994
4995 component.Id = Convert.ToString(row[0]);
4996
4997 component.Guid = Convert.ToString(row[1]);
4998
4999 int attributes = Convert.ToInt32(row[3]);
5000
5001 if (MsiInterop.MsidbComponentAttributesSourceOnly == (attributes & MsiInterop.MsidbComponentAttributesSourceOnly))
5002 {
5003 component.Location = Wix.Component.LocationType.source;
5004 }
5005 else if (MsiInterop.MsidbComponentAttributesOptional == (attributes & MsiInterop.MsidbComponentAttributesOptional))
5006 {
5007 component.Location = Wix.Component.LocationType.either;
5008 }
5009
5010 if (MsiInterop.MsidbComponentAttributesSharedDllRefCount == (attributes & MsiInterop.MsidbComponentAttributesSharedDllRefCount))
5011 {
5012 component.SharedDllRefCount = Wix.YesNoType.yes;
5013 }
5014
5015 if (MsiInterop.MsidbComponentAttributesPermanent == (attributes & MsiInterop.MsidbComponentAttributesPermanent))
5016 {
5017 component.Permanent = Wix.YesNoType.yes;
5018 }
5019
5020 if (MsiInterop.MsidbComponentAttributesTransitive == (attributes & MsiInterop.MsidbComponentAttributesTransitive))
5021 {
5022 component.Transitive = Wix.YesNoType.yes;
5023 }
5024
5025 if (MsiInterop.MsidbComponentAttributesNeverOverwrite == (attributes & MsiInterop.MsidbComponentAttributesNeverOverwrite))
5026 {
5027 component.NeverOverwrite = Wix.YesNoType.yes;
5028 }
5029
5030 if (MsiInterop.MsidbComponentAttributes64bit == (attributes & MsiInterop.MsidbComponentAttributes64bit))
5031 {
5032 component.Win64 = Wix.YesNoType.yes;
5033 }
5034
5035 if (MsiInterop.MsidbComponentAttributesDisableRegistryReflection == (attributes & MsiInterop.MsidbComponentAttributesDisableRegistryReflection))
5036 {
5037 component.DisableRegistryReflection = Wix.YesNoType.yes;
5038 }
5039
5040 if (MsiInterop.MsidbComponentAttributesUninstallOnSupersedence == (attributes & MsiInterop.MsidbComponentAttributesUninstallOnSupersedence))
5041 {
5042 component.UninstallWhenSuperseded = Wix.YesNoType.yes;
5043 }
5044
5045 if (MsiInterop.MsidbComponentAttributesShared == (attributes & MsiInterop.MsidbComponentAttributesShared))
5046 {
5047 component.Shared = Wix.YesNoType.yes;
5048 }
5049
5050 if (null != row[4])
5051 {
5052 Wix.Condition condition = new Wix.Condition();
5053
5054 condition.Content = Convert.ToString(row[4]);
5055
5056 component.AddChild(condition);
5057 }
5058
5059 Wix.Directory directory = (Wix.Directory)this.core.GetIndexedElement("Directory", Convert.ToString(row[2]));
5060 if (null != directory)
5061 {
5062 directory.AddChild(component);
5063 }
5064 else
5065 {
5066 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Directory_", Convert.ToString(row[2]), "Directory"));
5067 }
5068 this.core.IndexElement(row, component);
5069 }
5070 }
5071
5072 /// <summary>
5073 /// Decompile the Condition table.
5074 /// </summary>
5075 /// <param name="table">The table to decompile.</param>
5076 private void DecompileConditionTable(Table table)
5077 {
5078 foreach (Row row in table.Rows)
5079 {
5080 Wix.Condition condition = new Wix.Condition();
5081
5082 condition.Level = Convert.ToInt32(row[1]);
5083
5084 if (null != row[2])
5085 {
5086 condition.Content = Convert.ToString(row[2]);
5087 }
5088
5089 Wix.Feature feature = (Wix.Feature)this.core.GetIndexedElement("Feature", Convert.ToString(row[0]));
5090 if (null != feature)
5091 {
5092 feature.AddChild(condition);
5093 }
5094 else
5095 {
5096 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Feature_", Convert.ToString(row[0]), "Feature"));
5097 }
5098 }
5099 }
5100
5101 /// <summary>
5102 /// Decompile the Dialog table.
5103 /// </summary>
5104 /// <param name="table">The table to decompile.</param>
5105 private void DecompileDialogTable(Table table)
5106 {
5107 foreach (Row row in table.Rows)
5108 {
5109 Wix.Dialog dialog = new Wix.Dialog();
5110
5111 dialog.Id = Convert.ToString(row[0]);
5112
5113 dialog.X = Convert.ToInt32(row[1]);
5114
5115 dialog.Y = Convert.ToInt32(row[2]);
5116
5117 dialog.Width = Convert.ToInt32(row[3]);
5118
5119 dialog.Height = Convert.ToInt32(row[4]);
5120
5121 if (null != row[5])
5122 {
5123 int attributes = Convert.ToInt32(row[5]);
5124
5125 if (0 == (attributes & MsiInterop.MsidbDialogAttributesVisible))
5126 {
5127 dialog.Hidden = Wix.YesNoType.yes;
5128 }
5129
5130 if (0 == (attributes & MsiInterop.MsidbDialogAttributesModal))
5131 {
5132 dialog.Modeless = Wix.YesNoType.yes;
5133 }
5134
5135 if (0 == (attributes & MsiInterop.MsidbDialogAttributesMinimize))
5136 {
5137 dialog.NoMinimize = Wix.YesNoType.yes;
5138 }
5139
5140 if (MsiInterop.MsidbDialogAttributesSysModal == (attributes & MsiInterop.MsidbDialogAttributesSysModal))
5141 {
5142 dialog.SystemModal = Wix.YesNoType.yes;
5143 }
5144
5145 if (MsiInterop.MsidbDialogAttributesKeepModeless == (attributes & MsiInterop.MsidbDialogAttributesKeepModeless))
5146 {
5147 dialog.KeepModeless = Wix.YesNoType.yes;
5148 }
5149
5150 if (MsiInterop.MsidbDialogAttributesTrackDiskSpace == (attributes & MsiInterop.MsidbDialogAttributesTrackDiskSpace))
5151 {
5152 dialog.TrackDiskSpace = Wix.YesNoType.yes;
5153 }
5154
5155 if (MsiInterop.MsidbDialogAttributesUseCustomPalette == (attributes & MsiInterop.MsidbDialogAttributesUseCustomPalette))
5156 {
5157 dialog.CustomPalette = Wix.YesNoType.yes;
5158 }
5159
5160 if (MsiInterop.MsidbDialogAttributesRTLRO == (attributes & MsiInterop.MsidbDialogAttributesRTLRO))
5161 {
5162 dialog.RightToLeft = Wix.YesNoType.yes;
5163 }
5164
5165 if (MsiInterop.MsidbDialogAttributesRightAligned == (attributes & MsiInterop.MsidbDialogAttributesRightAligned))
5166 {
5167 dialog.RightAligned = Wix.YesNoType.yes;
5168 }
5169
5170 if (MsiInterop.MsidbDialogAttributesLeftScroll == (attributes & MsiInterop.MsidbDialogAttributesLeftScroll))
5171 {
5172 dialog.LeftScroll = Wix.YesNoType.yes;
5173 }
5174
5175 if (MsiInterop.MsidbDialogAttributesError == (attributes & MsiInterop.MsidbDialogAttributesError))
5176 {
5177 dialog.ErrorDialog = Wix.YesNoType.yes;
5178 }
5179 }
5180
5181 if (null != row[6])
5182 {
5183 dialog.Title = Convert.ToString(row[6]);
5184 }
5185
5186 this.core.UIElement.AddChild(dialog);
5187 this.core.IndexElement(row, dialog);
5188 }
5189 }
5190
5191 /// <summary>
5192 /// Decompile the Directory table.
5193 /// </summary>
5194 /// <param name="table">The table to decompile.</param>
5195 private void DecompileDirectoryTable(Table table)
5196 {
5197 foreach (Row row in table.Rows)
5198 {
5199 Wix.Directory directory = new Wix.Directory();
5200
5201 directory.Id = Convert.ToString(row[0]);
5202
5203 string[] names = Common.GetNames(Convert.ToString(row[2]));
5204
5205 if (String.Equals(directory.Id, "TARGETDIR", StringComparison.Ordinal) && !String.Equals(names[0], "SourceDir", StringComparison.Ordinal))
5206 {
5207 this.core.OnMessage(WixWarnings.TargetDirCorrectedDefaultDir());
5208 directory.Name = "SourceDir";
5209 }
5210 else
5211 {
5212 if (null != names[0] && "." != names[0])
5213 {
5214 if (null != names[1])
5215 {
5216 directory.ShortName = names[0];
5217 }
5218 else
5219 {
5220 directory.Name = names[0];
5221 }
5222 }
5223
5224 if (null != names[1])
5225 {
5226 directory.Name = names[1];
5227 }
5228 }
5229
5230 if (null != names[2])
5231 {
5232 if (null != names[3])
5233 {
5234 directory.ShortSourceName = names[2];
5235 }
5236 else
5237 {
5238 directory.SourceName = names[2];
5239 }
5240 }
5241
5242 if (null != names[3])
5243 {
5244 directory.SourceName = names[3];
5245 }
5246
5247 this.core.IndexElement(row, directory);
5248 }
5249
5250 // nest the directories
5251 foreach (Row row in table.Rows)
5252 {
5253 Wix.Directory directory = (Wix.Directory)this.core.GetIndexedElement(row);
5254
5255 if (null == row[1])
5256 {
5257 this.core.RootElement.AddChild(directory);
5258 }
5259 else
5260 {
5261 Wix.Directory parentDirectory = (Wix.Directory)this.core.GetIndexedElement("Directory", Convert.ToString(row[1]));
5262
5263 if (null == parentDirectory)
5264 {
5265 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Directory_Parent", Convert.ToString(row[1]), "Directory"));
5266 }
5267 else if (parentDirectory == directory) // another way to specify a root directory
5268 {
5269 this.core.RootElement.AddChild(directory);
5270 }
5271 else
5272 {
5273 parentDirectory.AddChild(directory);
5274 }
5275 }
5276 }
5277 }
5278
5279 /// <summary>
5280 /// Decompile the DrLocator table.
5281 /// </summary>
5282 /// <param name="table">The table to decompile.</param>
5283 private void DecompileDrLocatorTable(Table table)
5284 {
5285 foreach (Row row in table.Rows)
5286 {
5287 Wix.DirectorySearch directorySearch = new Wix.DirectorySearch();
5288
5289 directorySearch.Id = Convert.ToString(row[0]);
5290
5291 if (null != row[2])
5292 {
5293 directorySearch.Path = Convert.ToString(row[2]);
5294 }
5295
5296 if (null != row[3])
5297 {
5298 directorySearch.Depth = Convert.ToInt32(row[3]);
5299 }
5300
5301 this.core.IndexElement(row, directorySearch);
5302 }
5303 }
5304
5305 /// <summary>
5306 /// Decompile the DuplicateFile table.
5307 /// </summary>
5308 /// <param name="table">The table to decompile.</param>
5309 private void DecompileDuplicateFileTable(Table table)
5310 {
5311 foreach (Row row in table.Rows)
5312 {
5313 Wix.CopyFile copyFile = new Wix.CopyFile();
5314
5315 copyFile.Id = Convert.ToString(row[0]);
5316
5317 copyFile.FileId = Convert.ToString(row[2]);
5318
5319 if (null != row[3])
5320 {
5321 string[] names = Common.GetNames(Convert.ToString(row[3]));
5322 if (null != names[0] && null != names[1])
5323 {
5324 copyFile.DestinationShortName = names[0];
5325 copyFile.DestinationName = names[1];
5326 }
5327 else if (null != names[0])
5328 {
5329 copyFile.DestinationName = names[0];
5330 }
5331 }
5332
5333 // destination directory/property is set in FinalizeDuplicateMoveFileTables
5334
5335 Wix.Component component = (Wix.Component)this.core.GetIndexedElement("Component", Convert.ToString(row[1]));
5336 if (null != component)
5337 {
5338 component.AddChild(copyFile);
5339 }
5340 else
5341 {
5342 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", Convert.ToString(row[1]), "Component"));
5343 }
5344 this.core.IndexElement(row, copyFile);
5345 }
5346 }
5347
5348 /// <summary>
5349 /// Decompile the Environment table.
5350 /// </summary>
5351 /// <param name="table">The table to decompile.</param>
5352 private void DecompileEnvironmentTable(Table table)
5353 {
5354 foreach (Row row in table.Rows)
5355 {
5356 Wix.Environment environment = new Wix.Environment();
5357
5358 environment.Id = Convert.ToString(row[0]);
5359
5360 bool done = false;
5361 bool permanent = true;
5362 string name = Convert.ToString(row[1]);
5363 for (int i = 0; i < name.Length && !done; i++)
5364 {
5365 switch (name[i])
5366 {
5367 case '=':
5368 environment.Action = Wix.Environment.ActionType.set;
5369 break;
5370 case '+':
5371 environment.Action = Wix.Environment.ActionType.create;
5372 break;
5373 case '-':
5374 permanent = false;
5375 break;
5376 case '!':
5377 environment.Action = Wix.Environment.ActionType.remove;
5378 break;
5379 case '*':
5380 environment.System = Wix.YesNoType.yes;
5381 break;
5382 default:
5383 environment.Name = name.Substring(i);
5384 done = true;
5385 break;
5386 }
5387 }
5388
5389 if (permanent)
5390 {
5391 environment.Permanent = Wix.YesNoType.yes;
5392 }
5393
5394 if (null != row[2])
5395 {
5396 string value = Convert.ToString(row[2]);
5397
5398 if (value.StartsWith("[~]", StringComparison.Ordinal))
5399 {
5400 environment.Part = Wix.Environment.PartType.last;
5401
5402 if (3 < value.Length)
5403 {
5404 environment.Separator = value.Substring(3, 1);
5405 environment.Value = value.Substring(4);
5406 }
5407 }
5408 else if (value.EndsWith("[~]", StringComparison.Ordinal))
5409 {
5410 environment.Part = Wix.Environment.PartType.first;
5411
5412 if (3 < value.Length)
5413 {
5414 environment.Separator = value.Substring(value.Length - 4, 1);
5415 environment.Value = value.Substring(0, value.Length - 4);
5416 }
5417 }
5418 else
5419 {
5420 environment.Value = value;
5421 }
5422 }
5423
5424 Wix.Component component = (Wix.Component)this.core.GetIndexedElement("Component", Convert.ToString(row[3]));
5425 if (null != component)
5426 {
5427 component.AddChild(environment);
5428 }
5429 else
5430 {
5431 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", Convert.ToString(row[3]), "Component"));
5432 }
5433 }
5434 }
5435
5436 /// <summary>
5437 /// Decompile the Error table.
5438 /// </summary>
5439 /// <param name="table">The table to decompile.</param>
5440 private void DecompileErrorTable(Table table)
5441 {
5442 foreach (Row row in table.Rows)
5443 {
5444 Wix.Error error = new Wix.Error();
5445
5446 error.Id = Convert.ToInt32(row[0]);
5447
5448 error.Content = Convert.ToString(row[1]);
5449
5450 this.core.UIElement.AddChild(error);
5451 }
5452 }
5453
5454 /// <summary>
5455 /// Decompile the EventMapping table.
5456 /// </summary>
5457 /// <param name="table">The table to decompile.</param>
5458 private void DecompileEventMappingTable(Table table)
5459 {
5460 foreach (Row row in table.Rows)
5461 {
5462 Wix.Subscribe subscribe = new Wix.Subscribe();
5463
5464 subscribe.Event = Convert.ToString(row[2]);
5465
5466 subscribe.Attribute = Convert.ToString(row[3]);
5467
5468 Wix.Control control = (Wix.Control)this.core.GetIndexedElement("Control", Convert.ToString(row[0]), Convert.ToString(row[1]));
5469 if (null != control)
5470 {
5471 control.AddChild(subscribe);
5472 }
5473 else
5474 {
5475 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Dialog_", Convert.ToString(row[0]), "Control_", Convert.ToString(row[1]), "Control"));
5476 }
5477 }
5478 }
5479
5480 /// <summary>
5481 /// Decompile the Extension table.
5482 /// </summary>
5483 /// <param name="table">The table to decompile.</param>
5484 private void DecompileExtensionTable(Table table)
5485 {
5486 foreach (Row row in table.Rows)
5487 {
5488 Wix.Extension extension = new Wix.Extension();
5489
5490 extension.Advertise = Wix.YesNoType.yes;
5491
5492 extension.Id = Convert.ToString(row[0]);
5493
5494 if (null != row[3])
5495 {
5496 Wix.MIME mime = (Wix.MIME)this.core.GetIndexedElement("MIME", Convert.ToString(row[3]));
5497
5498 if (null != mime)
5499 {
5500 mime.Default = Wix.YesNoType.yes;
5501 }
5502 else
5503 {
5504 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "MIME_", Convert.ToString(row[3]), "MIME"));
5505 }
5506 }
5507
5508 if (null != row[2])
5509 {
5510 Wix.ProgId progId = (Wix.ProgId)this.core.GetIndexedElement("ProgId", Convert.ToString(row[2]));
5511
5512 if (null != progId)
5513 {
5514 progId.AddChild(extension);
5515 }
5516 else
5517 {
5518 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "ProgId_", Convert.ToString(row[2]), "ProgId"));
5519 }
5520 }
5521 else
5522 {
5523 Wix.Component component = (Wix.Component)this.core.GetIndexedElement("Component", Convert.ToString(row[1]));
5524
5525 if (null != component)
5526 {
5527 component.AddChild(extension);
5528 }
5529 else
5530 {
5531 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", Convert.ToString(row[1]), "Component"));
5532 }
5533 }
5534
5535 this.core.IndexElement(row, extension);
5536 }
5537 }
5538
5539 /// <summary>
5540 /// Decompile the ExternalFiles table.
5541 /// </summary>
5542 /// <param name="table">The table to decompile.</param>
5543 private void DecompileExternalFilesTable(Table table)
5544 {
5545 foreach (Row row in table.Rows)
5546 {
5547 Wix.ExternalFile externalFile = new Wix.ExternalFile();
5548
5549 externalFile.File = Convert.ToString(row[1]);
5550
5551 externalFile.Source = Convert.ToString(row[2]);
5552
5553 if (null != row[3])
5554 {
5555 string[] symbolPaths = (Convert.ToString(row[3])).Split(';');
5556
5557 foreach (string symbolPathString in symbolPaths)
5558 {
5559 Wix.SymbolPath symbolPath = new Wix.SymbolPath();
5560
5561 symbolPath.Path = symbolPathString;
5562
5563 externalFile.AddChild(symbolPath);
5564 }
5565 }
5566
5567 if (null != row[4] && null != row[5])
5568 {
5569 string[] ignoreOffsets = (Convert.ToString(row[4])).Split(',');
5570 string[] ignoreLengths = (Convert.ToString(row[5])).Split(',');
5571
5572 if (ignoreOffsets.Length == ignoreLengths.Length)
5573 {
5574 for (int i = 0; i < ignoreOffsets.Length; i++)
5575 {
5576 Wix.IgnoreRange ignoreRange = new Wix.IgnoreRange();
5577
5578 if (ignoreOffsets[i].StartsWith("0x", StringComparison.Ordinal))
5579 {
5580 ignoreRange.Offset = Convert.ToInt32(ignoreOffsets[i].Substring(2), 16);
5581 }
5582 else
5583 {
5584 ignoreRange.Offset = Convert.ToInt32(ignoreOffsets[i], CultureInfo.InvariantCulture);
5585 }
5586
5587 if (ignoreLengths[i].StartsWith("0x", StringComparison.Ordinal))
5588 {
5589 ignoreRange.Length = Convert.ToInt32(ignoreLengths[i].Substring(2), 16);
5590 }
5591 else
5592 {
5593 ignoreRange.Length = Convert.ToInt32(ignoreLengths[i], CultureInfo.InvariantCulture);
5594 }
5595
5596 externalFile.AddChild(ignoreRange);
5597 }
5598 }
5599 else
5600 {
5601 // TODO: warn
5602 }
5603 }
5604 else if (null != row[4] || null != row[5])
5605 {
5606 // TODO: warn about mismatch between columns
5607 }
5608
5609 // the RetainOffsets column is handled in FinalizeFamilyFileRangesTable
5610
5611 if (null != row[7])
5612 {
5613 externalFile.Order = Convert.ToInt32(row[7]);
5614 }
5615
5616 Wix.Family family = (Wix.Family)this.core.GetIndexedElement("ImageFamilies", Convert.ToString(row[0]));
5617 if (null != family)
5618 {
5619 family.AddChild(externalFile);
5620 }
5621 else
5622 {
5623 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Family", Convert.ToString(row[0]), "ImageFamilies"));
5624 }
5625 this.core.IndexElement(row, externalFile);
5626 }
5627 }
5628
5629 /// <summary>
5630 /// Decompile the Feature table.
5631 /// </summary>
5632 /// <param name="table">The table to decompile.</param>
5633 private void DecompileFeatureTable(Table table)
5634 {
5635 SortedList sortedFeatures = new SortedList();
5636
5637 foreach (Row row in table.Rows)
5638 {
5639 Wix.Feature feature = new Wix.Feature();
5640
5641 feature.Id = Convert.ToString(row[0]);
5642
5643 if (null != row[2])
5644 {
5645 feature.Title = Convert.ToString(row[2]);
5646 }
5647
5648 if (null != row[3])
5649 {
5650 feature.Description = Convert.ToString(row[3]);
5651 }
5652
5653 if (null == row[4])
5654 {
5655 feature.Display = "hidden";
5656 }
5657 else
5658 {
5659 int display = Convert.ToInt32(row[4]);
5660
5661 if (0 == display)
5662 {
5663 feature.Display = "hidden";
5664 }
5665 else if (1 == display % 2)
5666 {
5667 feature.Display = "expand";
5668 }
5669 }
5670
5671 feature.Level = Convert.ToInt32(row[5]);
5672
5673 if (null != row[6])
5674 {
5675 feature.ConfigurableDirectory = Convert.ToString(row[6]);
5676 }
5677
5678 int attributes = Convert.ToInt32(row[7]);
5679
5680 if (MsiInterop.MsidbFeatureAttributesFavorSource == (attributes & MsiInterop.MsidbFeatureAttributesFavorSource) && MsiInterop.MsidbFeatureAttributesFollowParent == (attributes & MsiInterop.MsidbFeatureAttributesFollowParent))
5681 {
5682 // TODO: display a warning for setting favor local and follow parent together
5683 }
5684 else if (MsiInterop.MsidbFeatureAttributesFavorSource == (attributes & MsiInterop.MsidbFeatureAttributesFavorSource))
5685 {
5686 feature.InstallDefault = Wix.Feature.InstallDefaultType.source;
5687 }
5688 else if (MsiInterop.MsidbFeatureAttributesFollowParent == (attributes & MsiInterop.MsidbFeatureAttributesFollowParent))
5689 {
5690 feature.InstallDefault = Wix.Feature.InstallDefaultType.followParent;
5691 }
5692
5693 if (MsiInterop.MsidbFeatureAttributesFavorAdvertise == (attributes & MsiInterop.MsidbFeatureAttributesFavorAdvertise))
5694 {
5695 feature.TypicalDefault = Wix.Feature.TypicalDefaultType.advertise;
5696 }
5697
5698 if (MsiInterop.MsidbFeatureAttributesDisallowAdvertise == (attributes & MsiInterop.MsidbFeatureAttributesDisallowAdvertise) &&
5699 MsiInterop.MsidbFeatureAttributesNoUnsupportedAdvertise == (attributes & MsiInterop.MsidbFeatureAttributesNoUnsupportedAdvertise))
5700 {
5701 this.core.OnMessage(WixWarnings.InvalidAttributeCombination(row.SourceLineNumbers, "msidbFeatureAttributesDisallowAdvertise", "msidbFeatureAttributesNoUnsupportedAdvertise", "Feature.AllowAdvertiseType", "no"));
5702 feature.AllowAdvertise = Wix.Feature.AllowAdvertiseType.no;
5703 }
5704 else if (MsiInterop.MsidbFeatureAttributesDisallowAdvertise == (attributes & MsiInterop.MsidbFeatureAttributesDisallowAdvertise))
5705 {
5706 feature.AllowAdvertise = Wix.Feature.AllowAdvertiseType.no;
5707 }
5708 else if (MsiInterop.MsidbFeatureAttributesNoUnsupportedAdvertise == (attributes & MsiInterop.MsidbFeatureAttributesNoUnsupportedAdvertise))
5709 {
5710 feature.AllowAdvertise = Wix.Feature.AllowAdvertiseType.system;
5711 }
5712
5713 if (MsiInterop.MsidbFeatureAttributesUIDisallowAbsent == (attributes & MsiInterop.MsidbFeatureAttributesUIDisallowAbsent))
5714 {
5715 feature.Absent = Wix.Feature.AbsentType.disallow;
5716 }
5717
5718 this.core.IndexElement(row, feature);
5719
5720 // sort the features by their display column (and append the identifier to ensure unique keys)
5721 sortedFeatures.Add(String.Format(CultureInfo.InvariantCulture, "{0:00000}|{1}", Convert.ToInt32(row[4], CultureInfo.InvariantCulture), row[0]), row);
5722 }
5723
5724 // nest the features
5725 foreach (Row row in sortedFeatures.Values)
5726 {
5727 Wix.Feature feature = (Wix.Feature)this.core.GetIndexedElement("Feature", Convert.ToString(row[0]));
5728
5729 if (null == row[1])
5730 {
5731 this.core.RootElement.AddChild(feature);
5732 }
5733 else
5734 {
5735 Wix.Feature parentFeature = (Wix.Feature)this.core.GetIndexedElement("Feature", Convert.ToString(row[1]));
5736
5737 if (null == parentFeature)
5738 {
5739 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Feature_Parent", Convert.ToString(row[1]), "Feature"));
5740 }
5741 else if (parentFeature == feature)
5742 {
5743 // TODO: display a warning about self-nesting
5744 }
5745 else
5746 {
5747 parentFeature.AddChild(feature);
5748 }
5749 }
5750 }
5751 }
5752
5753 /// <summary>
5754 /// Decompile the FeatureComponents table.
5755 /// </summary>
5756 /// <param name="table">The table to decompile.</param>
5757 private void DecompileFeatureComponentsTable(Table table)
5758 {
5759 foreach (Row row in table.Rows)
5760 {
5761 Wix.ComponentRef componentRef = new Wix.ComponentRef();
5762
5763 componentRef.Id = Convert.ToString(row[1]);
5764
5765 Wix.Feature parentFeature = (Wix.Feature)this.core.GetIndexedElement("Feature", Convert.ToString(row[0]));
5766 if (null != parentFeature)
5767 {
5768 parentFeature.AddChild(componentRef);
5769 }
5770 else
5771 {
5772 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Feature_", Convert.ToString(row[0]), "Feature"));
5773 }
5774 this.core.IndexElement(row, componentRef);
5775 }
5776 }
5777
5778 /// <summary>
5779 /// Decompile the File table.
5780 /// </summary>
5781 /// <param name="table">The table to decompile.</param>
5782 private void DecompileFileTable(Table table)
5783 {
5784 foreach (FileRow fileRow in table.Rows)
5785 {
5786 Wix.File file = new Wix.File();
5787
5788 file.Id = fileRow.File;
5789
5790 string[] names = Common.GetNames(fileRow.FileName);
5791 if (null != names[0] && null != names[1])
5792 {
5793 file.ShortName = names[0];
5794 file.Name = names[1];
5795 }
5796 else if (null != names[0])
5797 {
5798 file.Name = names[0];
5799 }
5800
5801 if (null != fileRow.Version && 0 < fileRow.Version.Length)
5802 {
5803 if (!Char.IsDigit(fileRow.Version[0]))
5804 {
5805 file.CompanionFile = fileRow.Version;
5806 }
5807 }
5808
5809 if (MsiInterop.MsidbFileAttributesReadOnly == (fileRow.Attributes & MsiInterop.MsidbFileAttributesReadOnly))
5810 {
5811 file.ReadOnly = Wix.YesNoType.yes;
5812 }
5813
5814 if (MsiInterop.MsidbFileAttributesHidden == (fileRow.Attributes & MsiInterop.MsidbFileAttributesHidden))
5815 {
5816 file.Hidden = Wix.YesNoType.yes;
5817 }
5818
5819 if (MsiInterop.MsidbFileAttributesSystem == (fileRow.Attributes & MsiInterop.MsidbFileAttributesSystem))
5820 {
5821 file.System = Wix.YesNoType.yes;
5822 }
5823
5824 if (MsiInterop.MsidbFileAttributesVital != (fileRow.Attributes & MsiInterop.MsidbFileAttributesVital))
5825 {
5826 file.Vital = Wix.YesNoType.no;
5827 }
5828
5829 if (MsiInterop.MsidbFileAttributesChecksum == (fileRow.Attributes & MsiInterop.MsidbFileAttributesChecksum))
5830 {
5831 file.Checksum = Wix.YesNoType.yes;
5832 }
5833
5834 if (MsiInterop.MsidbFileAttributesNoncompressed == (fileRow.Attributes & MsiInterop.MsidbFileAttributesNoncompressed) &&
5835 MsiInterop.MsidbFileAttributesCompressed == (fileRow.Attributes & MsiInterop.MsidbFileAttributesCompressed))
5836 {
5837 // TODO: error
5838 }
5839 else if (MsiInterop.MsidbFileAttributesNoncompressed == (fileRow.Attributes & MsiInterop.MsidbFileAttributesNoncompressed))
5840 {
5841 file.Compressed = Wix.YesNoDefaultType.no;
5842 }
5843 else if (MsiInterop.MsidbFileAttributesCompressed == (fileRow.Attributes & MsiInterop.MsidbFileAttributesCompressed))
5844 {
5845 file.Compressed = Wix.YesNoDefaultType.yes;
5846 }
5847
5848 this.core.IndexElement(fileRow, file);
5849 }
5850 }
5851
5852 /// <summary>
5853 /// Decompile the FileSFPCatalog table.
5854 /// </summary>
5855 /// <param name="table">The table to decompile.</param>
5856 private void DecompileFileSFPCatalogTable(Table table)
5857 {
5858 foreach (Row row in table.Rows)
5859 {
5860 Wix.SFPFile sfpFile = new Wix.SFPFile();
5861
5862 sfpFile.Id = Convert.ToString(row[0]);
5863
5864 Wix.SFPCatalog sfpCatalog = (Wix.SFPCatalog)this.core.GetIndexedElement("SFPCatalog", Convert.ToString(row[1]));
5865 if (null != sfpCatalog)
5866 {
5867 sfpCatalog.AddChild(sfpFile);
5868 }
5869 else
5870 {
5871 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "SFPCatalog_", Convert.ToString(row[1]), "SFPCatalog"));
5872 }
5873 }
5874 }
5875
5876 /// <summary>
5877 /// Decompile the Font table.
5878 /// </summary>
5879 /// <param name="table">The table to decompile.</param>
5880 private void DecompileFontTable(Table table)
5881 {
5882 foreach (Row row in table.Rows)
5883 {
5884 Wix.File file = (Wix.File)this.core.GetIndexedElement("File", Convert.ToString(row[0]));
5885
5886 if (null != file)
5887 {
5888 if (null != row[1])
5889 {
5890 file.FontTitle = Convert.ToString(row[1]);
5891 }
5892 else
5893 {
5894 file.TrueType = Wix.YesNoType.yes;
5895 }
5896 }
5897 else
5898 {
5899 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "File_", Convert.ToString(row[0]), "File"));
5900 }
5901 }
5902 }
5903
5904 /// <summary>
5905 /// Decompile the Icon table.
5906 /// </summary>
5907 /// <param name="table">The table to decompile.</param>
5908 private void DecompileIconTable(Table table)
5909 {
5910 foreach (Row row in table.Rows)
5911 {
5912 Wix.Icon icon = new Wix.Icon();
5913
5914 icon.Id = Convert.ToString(row[0]);
5915
5916 icon.SourceFile = Convert.ToString(row[1]);
5917
5918 this.core.RootElement.AddChild(icon);
5919 }
5920 }
5921
5922 /// <summary>
5923 /// Decompile the ImageFamilies table.
5924 /// </summary>
5925 /// <param name="table">The table to decompile.</param>
5926 private void DecompileImageFamiliesTable(Table table)
5927 {
5928 foreach (Row row in table.Rows)
5929 {
5930 Wix.Family family = new Wix.Family();
5931
5932 family.Name = Convert.ToString(row[0]);
5933
5934 if (null != row[1])
5935 {
5936 family.MediaSrcProp = Convert.ToString(row[1]);
5937 }
5938
5939 if (null != row[2])
5940 {
5941 family.DiskId = Convert.ToString(Convert.ToInt32(row[2]));
5942 }
5943
5944 if (null != row[3])
5945 {
5946 family.SequenceStart = Convert.ToInt32(row[3]);
5947 }
5948
5949 if (null != row[4])
5950 {
5951 family.DiskPrompt = Convert.ToString(row[4]);
5952 }
5953
5954 if (null != row[5])
5955 {
5956 family.VolumeLabel = Convert.ToString(row[5]);
5957 }
5958
5959 this.core.RootElement.AddChild(family);
5960 this.core.IndexElement(row, family);
5961 }
5962 }
5963
5964 /// <summary>
5965 /// Decompile the IniFile table.
5966 /// </summary>
5967 /// <param name="table">The table to decompile.</param>
5968 private void DecompileIniFileTable(Table table)
5969 {
5970 foreach (Row row in table.Rows)
5971 {
5972 Wix.IniFile iniFile = new Wix.IniFile();
5973
5974 iniFile.Id = Convert.ToString(row[0]);
5975
5976 string[] names = Common.GetNames(Convert.ToString(row[1]));
5977
5978 if (null != names[0])
5979 {
5980 if (null == names[1])
5981 {
5982 iniFile.Name = names[0];
5983 }
5984 else
5985 {
5986 iniFile.ShortName = names[0];
5987 }
5988 }
5989
5990 if (null != names[1])
5991 {
5992 iniFile.Name = names[1];
5993 }
5994
5995 if (null != row[2])
5996 {
5997 iniFile.Directory = Convert.ToString(row[2]);
5998 }
5999
6000 iniFile.Section = Convert.ToString(row[3]);
6001
6002 iniFile.Key = Convert.ToString(row[4]);
6003
6004 iniFile.Value = Convert.ToString(row[5]);
6005
6006 switch (Convert.ToInt32(row[6]))
6007 {
6008 case MsiInterop.MsidbIniFileActionAddLine:
6009 iniFile.Action = Wix.IniFile.ActionType.addLine;
6010 break;
6011 case MsiInterop.MsidbIniFileActionCreateLine:
6012 iniFile.Action = Wix.IniFile.ActionType.createLine;
6013 break;
6014 case MsiInterop.MsidbIniFileActionAddTag:
6015 iniFile.Action = Wix.IniFile.ActionType.addTag;
6016 break;
6017 default:
6018 this.core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[6].Column.Name, row[6]));
6019 break;
6020 }
6021
6022 Wix.Component component = (Wix.Component)this.core.GetIndexedElement("Component", Convert.ToString(row[7]));
6023 if (null != component)
6024 {
6025 component.AddChild(iniFile);
6026 }
6027 else
6028 {
6029 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", Convert.ToString(row[7]), "Component"));
6030 }
6031 }
6032 }
6033
6034 /// <summary>
6035 /// Decompile the IniLocator table.
6036 /// </summary>
6037 /// <param name="table">The table to decompile.</param>
6038 private void DecompileIniLocatorTable(Table table)
6039 {
6040 foreach (Row row in table.Rows)
6041 {
6042 Wix.IniFileSearch iniFileSearch = new Wix.IniFileSearch();
6043
6044 iniFileSearch.Id = Convert.ToString(row[0]);
6045
6046 string[] names = Common.GetNames(Convert.ToString(row[1]));
6047 if (null != names[0] && null != names[1])
6048 {
6049 iniFileSearch.ShortName = names[0];
6050 iniFileSearch.Name = names[1];
6051 }
6052 else if (null != names[0])
6053 {
6054 iniFileSearch.Name = names[0];
6055 }
6056
6057 iniFileSearch.Section = Convert.ToString(row[2]);
6058
6059 iniFileSearch.Key = Convert.ToString(row[3]);
6060
6061 if (null != row[4])
6062 {
6063 int field = Convert.ToInt32(row[4]);
6064
6065 if (0 != field)
6066 {
6067 iniFileSearch.Field = field;
6068 }
6069 }
6070
6071 if (null != row[5])
6072 {
6073 switch (Convert.ToInt32(row[5]))
6074 {
6075 case MsiInterop.MsidbLocatorTypeDirectory:
6076 iniFileSearch.Type = Wix.IniFileSearch.TypeType.directory;
6077 break;
6078 case MsiInterop.MsidbLocatorTypeFileName:
6079 // this is the default value
6080 break;
6081 case MsiInterop.MsidbLocatorTypeRawValue:
6082 iniFileSearch.Type = Wix.IniFileSearch.TypeType.raw;
6083 break;
6084 default:
6085 this.core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[5].Column.Name, row[5]));
6086 break;
6087 }
6088 }
6089
6090 this.core.IndexElement(row, iniFileSearch);
6091 }
6092 }
6093
6094 /// <summary>
6095 /// Decompile the IsolatedComponent table.
6096 /// </summary>
6097 /// <param name="table">The table to decompile.</param>
6098 private void DecompileIsolatedComponentTable(Table table)
6099 {
6100 foreach (Row row in table.Rows)
6101 {
6102 Wix.IsolateComponent isolateComponent = new Wix.IsolateComponent();
6103
6104 isolateComponent.Shared = Convert.ToString(row[0]);
6105
6106 Wix.Component component = (Wix.Component)this.core.GetIndexedElement("Component", Convert.ToString(row[1]));
6107 if (null != component)
6108 {
6109 component.AddChild(isolateComponent);
6110 }
6111 else
6112 {
6113 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", Convert.ToString(row[1]), "Component"));
6114 }
6115 }
6116 }
6117
6118 /// <summary>
6119 /// Decompile the LaunchCondition table.
6120 /// </summary>
6121 /// <param name="table">The table to decompile.</param>
6122 private void DecompileLaunchConditionTable(Table table)
6123 {
6124 foreach (Row row in table.Rows)
6125 {
6126 if (Compiler.DowngradePreventedCondition == Convert.ToString(row[0]) || Compiler.UpgradePreventedCondition == Convert.ToString(row[0]))
6127 {
6128 continue; // MajorUpgrade rows processed in FinalizeUpgradeTable
6129 }
6130
6131 Wix.Condition condition = new Wix.Condition();
6132
6133 condition.Content = Convert.ToString(row[0]);
6134
6135 condition.Message = Convert.ToString(row[1]);
6136
6137 this.core.RootElement.AddChild(condition);
6138 }
6139 }
6140
6141 /// <summary>
6142 /// Decompile the ListBox table.
6143 /// </summary>
6144 /// <param name="table">The table to decompile.</param>
6145 private void DecompileListBoxTable(Table table)
6146 {
6147 Wix.ListBox listBox = null;
6148 SortedList listBoxRows = new SortedList();
6149
6150 // sort the list boxes by their property and order
6151 foreach (Row row in table.Rows)
6152 {
6153 listBoxRows.Add(String.Concat("{0}|{1:0000000000}", row[0], row[1]), row);
6154 }
6155
6156 foreach (Row row in listBoxRows.Values)
6157 {
6158 if (null == listBox || Convert.ToString(row[0]) != listBox.Property)
6159 {
6160 listBox = new Wix.ListBox();
6161
6162 listBox.Property = Convert.ToString(row[0]);
6163
6164 this.core.UIElement.AddChild(listBox);
6165 }
6166
6167 Wix.ListItem listItem = new Wix.ListItem();
6168
6169 listItem.Value = Convert.ToString(row[2]);
6170
6171 if (null != row[3])
6172 {
6173 listItem.Text = Convert.ToString(row[3]);
6174 }
6175
6176 listBox.AddChild(listItem);
6177 }
6178 }
6179
6180 /// <summary>
6181 /// Decompile the ListView table.
6182 /// </summary>
6183 /// <param name="table">The table to decompile.</param>
6184 private void DecompileListViewTable(Table table)
6185 {
6186 Wix.ListView listView = null;
6187 SortedList listViewRows = new SortedList();
6188
6189 // sort the list views by their property and order
6190 foreach (Row row in table.Rows)
6191 {
6192 listViewRows.Add(String.Concat("{0}|{1:0000000000}", row[0], row[1]), row);
6193 }
6194
6195 foreach (Row row in listViewRows.Values)
6196 {
6197 if (null == listView || Convert.ToString(row[0]) != listView.Property)
6198 {
6199 listView = new Wix.ListView();
6200
6201 listView.Property = Convert.ToString(row[0]);
6202
6203 this.core.UIElement.AddChild(listView);
6204 }
6205
6206 Wix.ListItem listItem = new Wix.ListItem();
6207
6208 listItem.Value = Convert.ToString(row[2]);
6209
6210 if (null != row[3])
6211 {
6212 listItem.Text = Convert.ToString(row[3]);
6213 }
6214
6215 if (null != row[4])
6216 {
6217 listItem.Icon = Convert.ToString(row[4]);
6218 }
6219
6220 listView.AddChild(listItem);
6221 }
6222 }
6223
6224 /// <summary>
6225 /// Decompile the LockPermissions table.
6226 /// </summary>
6227 /// <param name="table">The table to decompile.</param>
6228 private void DecompileLockPermissionsTable(Table table)
6229 {
6230 foreach (Row row in table.Rows)
6231 {
6232 Wix.Permission permission = new Wix.Permission();
6233 string[] specialPermissions;
6234
6235 switch (Convert.ToString(row[1]))
6236 {
6237 case "CreateFolder":
6238 specialPermissions = Common.FolderPermissions;
6239 break;
6240 case "File":
6241 specialPermissions = Common.FilePermissions;
6242 break;
6243 case "Registry":
6244 specialPermissions = Common.RegistryPermissions;
6245 break;
6246 default:
6247 this.core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, row.Table.Name, row.Fields[1].Column.Name, row[1]));
6248 return;
6249 }
6250
6251 int permissionBits = Convert.ToInt32(row[4]);
6252 for (int i = 0; i < 32; i++)
6253 {
6254 if (0 != ((permissionBits >> i) & 1))
6255 {
6256 string name = null;
6257
6258 if (specialPermissions.Length > i)
6259 {
6260 name = specialPermissions[i];
6261 }
6262 else if (16 > i && specialPermissions.Length <= i)
6263 {
6264 name = "SpecificRightsAll";
6265 }
6266 else if (28 > i && Common.StandardPermissions.Length > (i - 16))
6267 {
6268 name = Common.StandardPermissions[i - 16];
6269 }
6270 else if (0 <= (i - 28) && Common.GenericPermissions.Length > (i - 28))
6271 {
6272 name = Common.GenericPermissions[i - 28];
6273 }
6274
6275 if (null == name)
6276 {
6277 this.core.OnMessage(WixWarnings.UnknownPermission(row.SourceLineNumbers, row.Table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), i));
6278 }
6279 else
6280 {
6281 switch (name)
6282 {
6283 case "Append":
6284 permission.Append = Wix.YesNoType.yes;
6285 break;
6286 case "ChangePermission":
6287 permission.ChangePermission = Wix.YesNoType.yes;
6288 break;
6289 case "CreateChild":
6290 permission.CreateChild = Wix.YesNoType.yes;
6291 break;
6292 case "CreateFile":
6293 permission.CreateFile = Wix.YesNoType.yes;
6294 break;
6295 case "CreateLink":
6296 permission.CreateLink = Wix.YesNoType.yes;
6297 break;
6298 case "CreateSubkeys":
6299 permission.CreateSubkeys = Wix.YesNoType.yes;
6300 break;
6301 case "Delete":
6302 permission.Delete = Wix.YesNoType.yes;
6303 break;
6304 case "DeleteChild":
6305 permission.DeleteChild = Wix.YesNoType.yes;
6306 break;
6307 case "EnumerateSubkeys":
6308 permission.EnumerateSubkeys = Wix.YesNoType.yes;
6309 break;
6310 case "Execute":
6311 permission.Execute = Wix.YesNoType.yes;
6312 break;
6313 case "FileAllRights":
6314 permission.FileAllRights = Wix.YesNoType.yes;
6315 break;
6316 case "GenericAll":
6317 permission.GenericAll = Wix.YesNoType.yes;
6318 break;
6319 case "GenericExecute":
6320 permission.GenericExecute = Wix.YesNoType.yes;
6321 break;
6322 case "GenericRead":
6323 permission.GenericRead = Wix.YesNoType.yes;
6324 break;
6325 case "GenericWrite":
6326 permission.GenericWrite = Wix.YesNoType.yes;
6327 break;
6328 case "Notify":
6329 permission.Notify = Wix.YesNoType.yes;
6330 break;
6331 case "Read":
6332 permission.Read = Wix.YesNoType.yes;
6333 break;
6334 case "ReadAttributes":
6335 permission.ReadAttributes = Wix.YesNoType.yes;
6336 break;
6337 case "ReadExtendedAttributes":
6338 permission.ReadExtendedAttributes = Wix.YesNoType.yes;
6339 break;
6340 case "ReadPermission":
6341 permission.ReadPermission = Wix.YesNoType.yes;
6342 break;
6343 case "SpecificRightsAll":
6344 permission.SpecificRightsAll = Wix.YesNoType.yes;
6345 break;
6346 case "Synchronize":
6347 permission.Synchronize = Wix.YesNoType.yes;
6348 break;
6349 case "TakeOwnership":
6350 permission.TakeOwnership = Wix.YesNoType.yes;
6351 break;
6352 case "Traverse":
6353 permission.Traverse = Wix.YesNoType.yes;
6354 break;
6355 case "Write":
6356 permission.Write = Wix.YesNoType.yes;
6357 break;
6358 case "WriteAttributes":
6359 permission.WriteAttributes = Wix.YesNoType.yes;
6360 break;
6361 case "WriteExtendedAttributes":
6362 permission.WriteExtendedAttributes = Wix.YesNoType.yes;
6363 break;
6364 default:
6365 throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnknownPermissionAttribute, name));
6366 }
6367 }
6368 }
6369 }
6370
6371 if (null != row[2])
6372 {
6373 permission.Domain = Convert.ToString(row[2]);
6374 }
6375
6376 permission.User = Convert.ToString(row[3]);
6377
6378 this.core.IndexElement(row, permission);
6379 }
6380 }
6381
6382 /// <summary>
6383 /// Decompile the Media table.
6384 /// </summary>
6385 /// <param name="table">The table to decompile.</param>
6386 private void DecompileMediaTable(Table table)
6387 {
6388 foreach (MediaRow mediaRow in table.Rows)
6389 {
6390 Wix.Media media = new Wix.Media();
6391
6392 media.Id = Convert.ToString(mediaRow.DiskId);
6393
6394 if (null != mediaRow.DiskPrompt)
6395 {
6396 media.DiskPrompt = mediaRow.DiskPrompt;
6397 }
6398
6399 if (null != mediaRow.Cabinet)
6400 {
6401 string cabinet = mediaRow.Cabinet;
6402
6403 if (cabinet.StartsWith("#", StringComparison.Ordinal))
6404 {
6405 media.EmbedCab = Wix.YesNoType.yes;
6406 cabinet = cabinet.Substring(1);
6407 }
6408
6409 media.Cabinet = cabinet;
6410 }
6411
6412 if (null != mediaRow.VolumeLabel)
6413 {
6414 media.VolumeLabel = mediaRow.VolumeLabel;
6415 }
6416
6417 this.core.RootElement.AddChild(media);
6418 this.core.IndexElement(mediaRow, media);
6419 }
6420 }
6421
6422 /// <summary>
6423 /// Decompile the MIME table.
6424 /// </summary>
6425 /// <param name="table">The table to decompile.</param>
6426 private void DecompileMIMETable(Table table)
6427 {
6428 foreach (Row row in table.Rows)
6429 {
6430 Wix.MIME mime = new Wix.MIME();
6431
6432 mime.ContentType = Convert.ToString(row[0]);
6433
6434 if (null != row[2])
6435 {
6436 mime.Class = Convert.ToString(row[2]);
6437 }
6438
6439 this.core.IndexElement(row, mime);
6440 }
6441 }
6442
6443 /// <summary>
6444 /// Decompile the ModuleConfiguration table.
6445 /// </summary>
6446 /// <param name="table">The table to decompile.</param>
6447 private void DecompileModuleConfigurationTable(Table table)
6448 {
6449 foreach (Row row in table.Rows)
6450 {
6451 Wix.Configuration configuration = new Wix.Configuration();
6452
6453 configuration.Name = Convert.ToString(row[0]);
6454
6455 switch (Convert.ToInt32(row[1]))
6456 {
6457 case 0:
6458 configuration.Format = Wix.Configuration.FormatType.Text;
6459 break;
6460 case 1:
6461 configuration.Format = Wix.Configuration.FormatType.Key;
6462 break;
6463 case 2:
6464 configuration.Format = Wix.Configuration.FormatType.Integer;
6465 break;
6466 case 3:
6467 configuration.Format = Wix.Configuration.FormatType.Bitfield;
6468 break;
6469 default:
6470 this.core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[1].Column.Name, row[1]));
6471 break;
6472 }
6473
6474 if (null != row[2])
6475 {
6476 configuration.Type = Convert.ToString(row[2]);
6477 }
6478
6479 if (null != row[3])
6480 {
6481 configuration.ContextData = Convert.ToString(row[3]);
6482 }
6483
6484 if (null != row[4])
6485 {
6486 configuration.DefaultValue = Convert.ToString(row[4]);
6487 }
6488
6489 if (null != row[5])
6490 {
6491 int attributes = Convert.ToInt32(row[5]);
6492
6493 if (MsiInterop.MsidbMsmConfigurableOptionKeyNoOrphan == (attributes & MsiInterop.MsidbMsmConfigurableOptionKeyNoOrphan))
6494 {
6495 configuration.KeyNoOrphan = Wix.YesNoType.yes;
6496 }
6497
6498 if (MsiInterop.MsidbMsmConfigurableOptionNonNullable == (attributes & MsiInterop.MsidbMsmConfigurableOptionNonNullable))
6499 {
6500 configuration.NonNullable = Wix.YesNoType.yes;
6501 }
6502
6503 if (3 < attributes)
6504 {
6505 this.core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[5].Column.Name, row[5]));
6506 }
6507 }
6508
6509 if (null != row[6])
6510 {
6511 configuration.DisplayName = Convert.ToString(row[6]);
6512 }
6513
6514 if (null != row[7])
6515 {
6516 configuration.Description = Convert.ToString(row[7]);
6517 }
6518
6519 if (null != row[8])
6520 {
6521 configuration.HelpLocation = Convert.ToString(row[8]);
6522 }
6523
6524 if (null != row[9])
6525 {
6526 configuration.HelpKeyword = Convert.ToString(row[9]);
6527 }
6528
6529 this.core.RootElement.AddChild(configuration);
6530 }
6531 }
6532
6533 /// <summary>
6534 /// Decompile the ModuleDependency table.
6535 /// </summary>
6536 /// <param name="table">The table to decompile.</param>
6537 private void DecompileModuleDependencyTable(Table table)
6538 {
6539 foreach (Row row in table.Rows)
6540 {
6541 Wix.Dependency dependency = new Wix.Dependency();
6542
6543 dependency.RequiredId = Convert.ToString(row[2]);
6544
6545 dependency.RequiredLanguage = Convert.ToInt32(row[3], CultureInfo.InvariantCulture);
6546
6547 if (null != row[4])
6548 {
6549 dependency.RequiredVersion = Convert.ToString(row[4]);
6550 }
6551
6552 this.core.RootElement.AddChild(dependency);
6553 }
6554 }
6555
6556 /// <summary>
6557 /// Decompile the ModuleExclusion table.
6558 /// </summary>
6559 /// <param name="table">The table to decompile.</param>
6560 private void DecompileModuleExclusionTable(Table table)
6561 {
6562 foreach (Row row in table.Rows)
6563 {
6564 Wix.Exclusion exclusion = new Wix.Exclusion();
6565
6566 exclusion.ExcludedId = Convert.ToString(row[2]);
6567
6568 int excludedLanguage = Convert.ToInt32(Convert.ToString(row[3]), CultureInfo.InvariantCulture);
6569 if (0 < excludedLanguage)
6570 {
6571 exclusion.ExcludeLanguage = excludedLanguage;
6572 }
6573 else if (0 > excludedLanguage)
6574 {
6575 exclusion.ExcludeExceptLanguage = -excludedLanguage;
6576 }
6577
6578 if (null != row[4])
6579 {
6580 exclusion.ExcludedMinVersion = Convert.ToString(row[4]);
6581 }
6582
6583 if (null != row[5])
6584 {
6585 exclusion.ExcludedMinVersion = Convert.ToString(row[5]);
6586 }
6587
6588 this.core.RootElement.AddChild(exclusion);
6589 }
6590 }
6591
6592 /// <summary>
6593 /// Decompile the ModuleIgnoreTable table.
6594 /// </summary>
6595 /// <param name="table">The table to decompile.</param>
6596 private void DecompileModuleIgnoreTableTable(Table table)
6597 {
6598 foreach (Row row in table.Rows)
6599 {
6600 string tableName = Convert.ToString(row[0]);
6601
6602 // the linker automatically adds a ModuleIgnoreTable row for some tables
6603 if ("ModuleConfiguration" != tableName && "ModuleSubstitution" != tableName)
6604 {
6605 Wix.IgnoreTable ignoreTable = new Wix.IgnoreTable();
6606
6607 ignoreTable.Id = tableName;
6608
6609 this.core.RootElement.AddChild(ignoreTable);
6610 }
6611 }
6612 }
6613
6614 /// <summary>
6615 /// Decompile the ModuleSignature table.
6616 /// </summary>
6617 /// <param name="table">The table to decompile.</param>
6618 private void DecompileModuleSignatureTable(Table table)
6619 {
6620 if (1 == table.Rows.Count)
6621 {
6622 Row row = table.Rows[0];
6623
6624 Wix.Module module = (Wix.Module)this.core.RootElement;
6625
6626 module.Id = Convert.ToString(row[0]);
6627
6628 // support Language columns that are treated as integers as well as strings (the WiX default, to support localizability)
6629 module.Language = Convert.ToString(row[1], CultureInfo.InvariantCulture);
6630
6631 module.Version = Convert.ToString(row[2]);
6632 }
6633 else
6634 {
6635 // TODO: warn
6636 }
6637 }
6638
6639 /// <summary>
6640 /// Decompile the ModuleSubstitution table.
6641 /// </summary>
6642 /// <param name="table">The table to decompile.</param>
6643 private void DecompileModuleSubstitutionTable(Table table)
6644 {
6645 foreach (Row row in table.Rows)
6646 {
6647 Wix.Substitution substitution = new Wix.Substitution();
6648
6649 substitution.Table = Convert.ToString(row[0]);
6650
6651 substitution.Row = Convert.ToString(row[1]);
6652
6653 substitution.Column = Convert.ToString(row[2]);
6654
6655 if (null != row[3])
6656 {
6657 substitution.Value = Convert.ToString(row[3]);
6658 }
6659
6660 this.core.RootElement.AddChild(substitution);
6661 }
6662 }
6663
6664 /// <summary>
6665 /// Decompile the MoveFile table.
6666 /// </summary>
6667 /// <param name="table">The table to decompile.</param>
6668 private void DecompileMoveFileTable(Table table)
6669 {
6670 foreach (Row row in table.Rows)
6671 {
6672 Wix.CopyFile copyFile = new Wix.CopyFile();
6673
6674 copyFile.Id = Convert.ToString(row[0]);
6675
6676 if (null != row[2])
6677 {
6678 copyFile.SourceName = Convert.ToString(row[2]);
6679 }
6680
6681 if (null != row[3])
6682 {
6683 string[] names = Common.GetNames(Convert.ToString(row[3]));
6684 if (null != names[0] && null != names[1])
6685 {
6686 copyFile.DestinationShortName = names[0];
6687 copyFile.DestinationName = names[1];
6688 }
6689 else if (null != names[0])
6690 {
6691 copyFile.DestinationName = names[0];
6692 }
6693 }
6694
6695 // source/destination directory/property is set in FinalizeDuplicateMoveFileTables
6696
6697 switch (Convert.ToInt32(row[6]))
6698 {
6699 case 0:
6700 break;
6701 case MsiInterop.MsidbMoveFileOptionsMove:
6702 copyFile.Delete = Wix.YesNoType.yes;
6703 break;
6704 default:
6705 this.core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[6].Column.Name, row[6]));
6706 break;
6707 }
6708
6709 Wix.Component component = (Wix.Component)this.core.GetIndexedElement("Component", Convert.ToString(row[1]));
6710 if (null != component)
6711 {
6712 component.AddChild(copyFile);
6713 }
6714 else
6715 {
6716 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", Convert.ToString(row[1]), "Component"));
6717 }
6718 this.core.IndexElement(row, copyFile);
6719 }
6720 }
6721
6722 /// <summary>
6723 /// Decompile the MsiDigitalCertificate table.
6724 /// </summary>
6725 /// <param name="table">The table to decompile.</param>
6726 private void DecompileMsiDigitalCertificateTable(Table table)
6727 {
6728 foreach (Row row in table.Rows)
6729 {
6730 Wix.DigitalCertificate digitalCertificate = new Wix.DigitalCertificate();
6731
6732 digitalCertificate.Id = Convert.ToString(row[0]);
6733
6734 digitalCertificate.SourceFile = Convert.ToString(row[1]);
6735
6736 this.core.IndexElement(row, digitalCertificate);
6737 }
6738 }
6739
6740 /// <summary>
6741 /// Decompile the MsiDigitalSignature table.
6742 /// </summary>
6743 /// <param name="table">The table to decompile.</param>
6744 private void DecompileMsiDigitalSignatureTable(Table table)
6745 {
6746 foreach (Row row in table.Rows)
6747 {
6748 Wix.DigitalSignature digitalSignature = new Wix.DigitalSignature();
6749
6750 if (null != row[3])
6751 {
6752 digitalSignature.SourceFile = Convert.ToString(row[3]);
6753 }
6754
6755 Wix.DigitalCertificate digitalCertificate = (Wix.DigitalCertificate)this.core.GetIndexedElement("MsiDigitalCertificate", Convert.ToString(row[2]));
6756 if (null != digitalCertificate)
6757 {
6758 digitalSignature.AddChild(digitalCertificate);
6759 }
6760 else
6761 {
6762 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "DigitalCertificate_", Convert.ToString(row[2]), "MsiDigitalCertificate"));
6763 }
6764
6765 Wix.IParentElement parentElement = (Wix.IParentElement)this.core.GetIndexedElement(Convert.ToString(row[0]), Convert.ToString(row[1]));
6766 if (null != parentElement)
6767 {
6768 parentElement.AddChild(digitalSignature);
6769 }
6770 else
6771 {
6772 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "SignObject", Convert.ToString(row[1]), Convert.ToString(row[0])));
6773 }
6774 }
6775 }
6776
6777 /// <summary>
6778 /// Decompile the MsiEmbeddedChainer table.
6779 /// </summary>
6780 /// <param name="table">The table to decompile.</param>
6781 private void DecompileMsiEmbeddedChainerTable(Table table)
6782 {
6783 foreach (Row row in table.Rows)
6784 {
6785 Wix.EmbeddedChainer embeddedChainer = new Wix.EmbeddedChainer();
6786
6787 embeddedChainer.Id = Convert.ToString(row[0]);
6788
6789 embeddedChainer.Content = Convert.ToString(row[1]);
6790
6791 if (null != row[2])
6792 {
6793 embeddedChainer.CommandLine = Convert.ToString(row[2]);
6794 }
6795
6796 switch (Convert.ToInt32(row[4]))
6797 {
6798 case MsiInterop.MsidbCustomActionTypeExe + MsiInterop.MsidbCustomActionTypeBinaryData:
6799 embeddedChainer.BinarySource = Convert.ToString(row[3]);
6800 break;
6801 case MsiInterop.MsidbCustomActionTypeExe + MsiInterop.MsidbCustomActionTypeSourceFile:
6802 embeddedChainer.FileSource = Convert.ToString(row[3]);
6803 break;
6804 case MsiInterop.MsidbCustomActionTypeExe + MsiInterop.MsidbCustomActionTypeProperty:
6805 embeddedChainer.PropertySource = Convert.ToString(row[3]);
6806 break;
6807 default:
6808 this.core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[4].Column.Name, row[4]));
6809 break;
6810 }
6811
6812 this.core.RootElement.AddChild(embeddedChainer);
6813 }
6814 }
6815
6816 /// <summary>
6817 /// Decompile the MsiEmbeddedUI table.
6818 /// </summary>
6819 /// <param name="table">The table to decompile.</param>
6820 private void DecompileMsiEmbeddedUITable(Table table)
6821 {
6822 Wix.EmbeddedUI embeddedUI = new Wix.EmbeddedUI();
6823 bool foundEmbeddedUI = false;
6824 bool foundEmbeddedResources = false;
6825
6826 foreach (Row row in table.Rows)
6827 {
6828 int attributes = Convert.ToInt32(row[2]);
6829
6830 if (MsiInterop.MsidbEmbeddedUI == (attributes & MsiInterop.MsidbEmbeddedUI))
6831 {
6832 if (foundEmbeddedUI)
6833 {
6834 this.core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[2].Column.Name, row[2]));
6835 }
6836 else
6837 {
6838 embeddedUI.Id = Convert.ToString(row[0]);
6839 embeddedUI.Name = Convert.ToString(row[1]);
6840
6841 int messageFilter = Convert.ToInt32(row[3]);
6842 if (0 == (messageFilter & MsiInterop.INSTALLLOGMODE_FATALEXIT))
6843 {
6844 embeddedUI.IgnoreFatalExit = Wix.YesNoType.yes;
6845 }
6846
6847 if (0 == (messageFilter & MsiInterop.INSTALLLOGMODE_ERROR))
6848 {
6849 embeddedUI.IgnoreError = Wix.YesNoType.yes;
6850 }
6851
6852 if (0 == (messageFilter & MsiInterop.INSTALLLOGMODE_WARNING))
6853 {
6854 embeddedUI.IgnoreWarning = Wix.YesNoType.yes;
6855 }
6856
6857 if (0 == (messageFilter & MsiInterop.INSTALLLOGMODE_USER))
6858 {
6859 embeddedUI.IgnoreUser = Wix.YesNoType.yes;
6860 }
6861
6862 if (0 == (messageFilter & MsiInterop.INSTALLLOGMODE_INFO))
6863 {
6864 embeddedUI.IgnoreInfo = Wix.YesNoType.yes;
6865 }
6866
6867 if (0 == (messageFilter & MsiInterop.INSTALLLOGMODE_FILESINUSE))
6868 {
6869 embeddedUI.IgnoreFilesInUse = Wix.YesNoType.yes;
6870 }
6871
6872 if (0 == (messageFilter & MsiInterop.INSTALLLOGMODE_RESOLVESOURCE))
6873 {
6874 embeddedUI.IgnoreResolveSource = Wix.YesNoType.yes;
6875 }
6876
6877 if (0 == (messageFilter & MsiInterop.INSTALLLOGMODE_OUTOFDISKSPACE))
6878 {
6879 embeddedUI.IgnoreOutOfDiskSpace = Wix.YesNoType.yes;
6880 }
6881
6882 if (0 == (messageFilter & MsiInterop.INSTALLLOGMODE_ACTIONSTART))
6883 {
6884 embeddedUI.IgnoreActionStart = Wix.YesNoType.yes;
6885 }
6886
6887 if (0 == (messageFilter & MsiInterop.INSTALLLOGMODE_ACTIONDATA))
6888 {
6889 embeddedUI.IgnoreActionData = Wix.YesNoType.yes;
6890 }
6891
6892 if (0 == (messageFilter & MsiInterop.INSTALLLOGMODE_PROGRESS))
6893 {
6894 embeddedUI.IgnoreProgress = Wix.YesNoType.yes;
6895 }
6896
6897 if (0 == (messageFilter & MsiInterop.INSTALLLOGMODE_COMMONDATA))
6898 {
6899 embeddedUI.IgnoreCommonData = Wix.YesNoType.yes;
6900 }
6901
6902 if (0 == (messageFilter & MsiInterop.INSTALLLOGMODE_INITIALIZE))
6903 {
6904 embeddedUI.IgnoreInitialize = Wix.YesNoType.yes;
6905 }
6906
6907 if (0 == (messageFilter & MsiInterop.INSTALLLOGMODE_TERMINATE))
6908 {
6909 embeddedUI.IgnoreTerminate = Wix.YesNoType.yes;
6910 }
6911
6912 if (0 == (messageFilter & MsiInterop.INSTALLLOGMODE_SHOWDIALOG))
6913 {
6914 embeddedUI.IgnoreShowDialog = Wix.YesNoType.yes;
6915 }
6916
6917 if (0 == (messageFilter & MsiInterop.INSTALLLOGMODE_RMFILESINUSE))
6918 {
6919 embeddedUI.IgnoreRMFilesInUse = Wix.YesNoType.yes;
6920 }
6921
6922 if (0 == (messageFilter & MsiInterop.INSTALLLOGMODE_INSTALLSTART))
6923 {
6924 embeddedUI.IgnoreInstallStart = Wix.YesNoType.yes;
6925 }
6926
6927 if (0 == (messageFilter & MsiInterop.INSTALLLOGMODE_INSTALLEND))
6928 {
6929 embeddedUI.IgnoreInstallEnd = Wix.YesNoType.yes;
6930 }
6931
6932 if (MsiInterop.MsidbEmbeddedHandlesBasic == (attributes & MsiInterop.MsidbEmbeddedHandlesBasic))
6933 {
6934 embeddedUI.SupportBasicUI = Wix.YesNoType.yes;
6935 }
6936
6937 embeddedUI.SourceFile = Convert.ToString(row[4]);
6938
6939 this.core.UIElement.AddChild(embeddedUI);
6940 foundEmbeddedUI = true;
6941 }
6942 }
6943 else
6944 {
6945 Wix.EmbeddedUIResource embeddedResource = new Wix.EmbeddedUIResource();
6946
6947 embeddedResource.Id = Convert.ToString(row[0]);
6948 embeddedResource.Name = Convert.ToString(row[1]);
6949 embeddedResource.SourceFile = Convert.ToString(row[4]);
6950
6951 embeddedUI.AddChild(embeddedResource);
6952 foundEmbeddedResources = true;
6953 }
6954 }
6955
6956 if (!foundEmbeddedUI && foundEmbeddedResources)
6957 {
6958 // TODO: warn
6959 }
6960 }
6961
6962 /// <summary>
6963 /// Decompile the MsiLockPermissionsEx table.
6964 /// </summary>
6965 /// <param name="table">The table to decompile.</param>
6966 private void DecompileMsiLockPermissionsExTable(Table table)
6967 {
6968 foreach (Row row in table.Rows)
6969 {
6970 Wix.PermissionEx permissionEx = new Wix.PermissionEx();
6971 permissionEx.Id = Convert.ToString(row[0]);
6972 permissionEx.Sddl = Convert.ToString(row[3]);
6973
6974 if (null != row[4])
6975 {
6976 Wix.Condition condition = new Wix.Condition();
6977 condition.Content = Convert.ToString(row[4]);
6978 permissionEx.AddChild(condition);
6979 }
6980
6981 switch (Convert.ToString(row[2]))
6982 {
6983 case "CreateFolder":
6984 case "File":
6985 case "Registry":
6986 case "ServiceInstall":
6987 break;
6988 default:
6989 this.core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, row.Table.Name, row.Fields[1].Column.Name, row[1]));
6990 return;
6991 }
6992
6993 this.core.IndexElement(row, permissionEx);
6994 }
6995 }
6996
6997 /// <summary>
6998 /// Decompile the MsiPackageCertificate table.
6999 /// </summary>
7000 /// <param name="table">The table to decompile.</param>
7001 private void DecompileMsiPackageCertificateTable(Table table)
7002 {
7003 if (0 < table.Rows.Count)
7004 {
7005 Wix.PackageCertificates packageCertificates = new Wix.PackageCertificates();
7006 this.core.RootElement.AddChild(packageCertificates);
7007 AddCertificates(table, packageCertificates);
7008 }
7009 }
7010
7011 /// <summary>
7012 /// Decompile the MsiPatchCertificate table.
7013 /// </summary>
7014 /// <param name="table">The table to decompile.</param>
7015 private void DecompileMsiPatchCertificateTable(Table table)
7016 {
7017 if (0 < table.Rows.Count)
7018 {
7019 Wix.PatchCertificates patchCertificates = new Wix.PatchCertificates();
7020 this.core.RootElement.AddChild(patchCertificates);
7021 AddCertificates(table, patchCertificates);
7022 }
7023 }
7024
7025 /// <summary>
7026 /// Insert DigitalCertificate records associated with passed msiPackageCertificate or msiPatchCertificate table.
7027 /// </summary>
7028 /// <param name="table">The table being decompiled.</param>
7029 /// <param name="parent">DigitalCertificate parent</param>
7030 private void AddCertificates(Table table, Wix.IParentElement parent)
7031 {
7032 foreach (Row row in table.Rows)
7033 {
7034 Wix.DigitalCertificate digitalCertificate = (Wix.DigitalCertificate)this.core.GetIndexedElement("MsiDigitalCertificate", Convert.ToString(row[1]));
7035
7036 if (null != digitalCertificate)
7037 {
7038 parent.AddChild(digitalCertificate);
7039 }
7040 else
7041 {
7042 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "DigitalCertificate_", Convert.ToString(row[1]), "MsiDigitalCertificate"));
7043 }
7044 }
7045 }
7046
7047 /// <summary>
7048 /// Decompile the MsiShortcutProperty table.
7049 /// </summary>
7050 /// <param name="table">The table to decompile.</param>
7051 private void DecompileMsiShortcutPropertyTable(Table table)
7052 {
7053 foreach (Row row in table.Rows)
7054 {
7055 Wix.ShortcutProperty property = new Wix.ShortcutProperty();
7056 property.Id = Convert.ToString(row[0]);
7057 property.Key = Convert.ToString(row[2]);
7058 property.Value = Convert.ToString(row[3]);
7059
7060 Wix.Shortcut shortcut = (Wix.Shortcut)this.core.GetIndexedElement("Shortcut", Convert.ToString(row[1]));
7061 if (null != shortcut)
7062 {
7063 shortcut.AddChild(property);
7064 }
7065 else
7066 {
7067 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Shortcut_", Convert.ToString(row[1]), "Shortcut"));
7068 }
7069 }
7070 }
7071
7072 /// <summary>
7073 /// Decompile the ODBCAttribute table.
7074 /// </summary>
7075 /// <param name="table">The table to decompile.</param>
7076 private void DecompileODBCAttributeTable(Table table)
7077 {
7078 foreach (Row row in table.Rows)
7079 {
7080 Wix.Property property = new Wix.Property();
7081
7082 property.Id = Convert.ToString(row[1]);
7083
7084 if (null != row[2])
7085 {
7086 property.Value = Convert.ToString(row[2]);
7087 }
7088
7089 Wix.ODBCDriver odbcDriver = (Wix.ODBCDriver)this.core.GetIndexedElement("ODBCDriver", Convert.ToString(row[0]));
7090 if (null != odbcDriver)
7091 {
7092 odbcDriver.AddChild(property);
7093 }
7094 else
7095 {
7096 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Driver_", Convert.ToString(row[0]), "ODBCDriver"));
7097 }
7098 }
7099 }
7100
7101 /// <summary>
7102 /// Decompile the ODBCDataSource table.
7103 /// </summary>
7104 /// <param name="table">The table to decompile.</param>
7105 private void DecompileODBCDataSourceTable(Table table)
7106 {
7107 foreach (Row row in table.Rows)
7108 {
7109 Wix.ODBCDataSource odbcDataSource = new Wix.ODBCDataSource();
7110
7111 odbcDataSource.Id = Convert.ToString(row[0]);
7112
7113 odbcDataSource.Name = Convert.ToString(row[2]);
7114
7115 odbcDataSource.DriverName = Convert.ToString(row[3]);
7116
7117 switch (Convert.ToInt32(row[4]))
7118 {
7119 case MsiInterop.MsidbODBCDataSourceRegistrationPerMachine:
7120 odbcDataSource.Registration = Wix.ODBCDataSource.RegistrationType.machine;
7121 break;
7122 case MsiInterop.MsidbODBCDataSourceRegistrationPerUser:
7123 odbcDataSource.Registration = Wix.ODBCDataSource.RegistrationType.user;
7124 break;
7125 default:
7126 this.core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[4].Column.Name, row[4]));
7127 break;
7128 }
7129
7130 this.core.IndexElement(row, odbcDataSource);
7131 }
7132 }
7133
7134 /// <summary>
7135 /// Decompile the ODBCDriver table.
7136 /// </summary>
7137 /// <param name="table">The table to decompile.</param>
7138 private void DecompileODBCDriverTable(Table table)
7139 {
7140 foreach (Row row in table.Rows)
7141 {
7142 Wix.ODBCDriver odbcDriver = new Wix.ODBCDriver();
7143
7144 odbcDriver.Id = Convert.ToString(row[0]);
7145
7146 odbcDriver.Name = Convert.ToString(row[2]);
7147
7148 odbcDriver.File = Convert.ToString(row[3]);
7149
7150 if (null != row[4])
7151 {
7152 odbcDriver.SetupFile = Convert.ToString(row[4]);
7153 }
7154
7155 Wix.Component component = (Wix.Component)this.core.GetIndexedElement("Component", Convert.ToString(row[1]));
7156 if (null != component)
7157 {
7158 component.AddChild(odbcDriver);
7159 }
7160 else
7161 {
7162 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", Convert.ToString(row[1]), "Component"));
7163 }
7164 this.core.IndexElement(row, odbcDriver);
7165 }
7166 }
7167
7168 /// <summary>
7169 /// Decompile the ODBCSourceAttribute table.
7170 /// </summary>
7171 /// <param name="table">The table to decompile.</param>
7172 private void DecompileODBCSourceAttributeTable(Table table)
7173 {
7174 foreach (Row row in table.Rows)
7175 {
7176 Wix.Property property = new Wix.Property();
7177
7178 property.Id = Convert.ToString(row[1]);
7179
7180 if (null != row[2])
7181 {
7182 property.Value = Convert.ToString(row[2]);
7183 }
7184
7185 Wix.ODBCDataSource odbcDataSource = (Wix.ODBCDataSource)this.core.GetIndexedElement("ODBCDataSource", Convert.ToString(row[0]));
7186 if (null != odbcDataSource)
7187 {
7188 odbcDataSource.AddChild(property);
7189 }
7190 else
7191 {
7192 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "DataSource_", Convert.ToString(row[0]), "ODBCDataSource"));
7193 }
7194 }
7195 }
7196
7197 /// <summary>
7198 /// Decompile the ODBCTranslator table.
7199 /// </summary>
7200 /// <param name="table">The table to decompile.</param>
7201 private void DecompileODBCTranslatorTable(Table table)
7202 {
7203 foreach (Row row in table.Rows)
7204 {
7205 Wix.ODBCTranslator odbcTranslator = new Wix.ODBCTranslator();
7206
7207 odbcTranslator.Id = Convert.ToString(row[0]);
7208
7209 odbcTranslator.Name = Convert.ToString(row[2]);
7210
7211 odbcTranslator.File = Convert.ToString(row[3]);
7212
7213 if (null != row[4])
7214 {
7215 odbcTranslator.SetupFile = Convert.ToString(row[4]);
7216 }
7217
7218 Wix.Component component = (Wix.Component)this.core.GetIndexedElement("Component", Convert.ToString(row[1]));
7219 if (null != component)
7220 {
7221 component.AddChild(odbcTranslator);
7222 }
7223 else
7224 {
7225 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", Convert.ToString(row[1]), "Component"));
7226 }
7227 }
7228 }
7229
7230 /// <summary>
7231 /// Decompile the PatchMetadata table.
7232 /// </summary>
7233 /// <param name="table">The table to decompile.</param>
7234 private void DecompilePatchMetadataTable(Table table)
7235 {
7236 if (0 < table.Rows.Count)
7237 {
7238 Wix.PatchMetadata patchMetadata = new Wix.PatchMetadata();
7239
7240 foreach (Row row in table.Rows)
7241 {
7242 string value = Convert.ToString(row[2]);
7243
7244 switch (Convert.ToString(row[1]))
7245 {
7246 case "AllowRemoval":
7247 if ("1" == value)
7248 {
7249 patchMetadata.AllowRemoval = Wix.YesNoType.yes;
7250 }
7251 break;
7252 case "Classification":
7253 if (null != value)
7254 {
7255 patchMetadata.Classification = value;
7256 }
7257 break;
7258 case "CreationTimeUTC":
7259 if (null != value)
7260 {
7261 patchMetadata.CreationTimeUTC = value;
7262 }
7263 break;
7264 case "Description":
7265 if (null != value)
7266 {
7267 patchMetadata.Description = value;
7268 }
7269 break;
7270 case "DisplayName":
7271 if (null != value)
7272 {
7273 patchMetadata.DisplayName = value;
7274 }
7275 break;
7276 case "ManufacturerName":
7277 if (null != value)
7278 {
7279 patchMetadata.ManufacturerName = value;
7280 }
7281 break;
7282 case "MinorUpdateTargetRTM":
7283 if (null != value)
7284 {
7285 patchMetadata.MinorUpdateTargetRTM = value;
7286 }
7287 break;
7288 case "MoreInfoURL":
7289 if (null != value)
7290 {
7291 patchMetadata.MoreInfoURL = value;
7292 }
7293 break;
7294 case "OptimizeCA":
7295 Wix.OptimizeCustomActions optimizeCustomActions = new Wix.OptimizeCustomActions();
7296 int optimizeCA = Int32.Parse(value, CultureInfo.InvariantCulture);
7297 if (0 != (Convert.ToInt32(OptimizeCA.SkipAssignment) & optimizeCA))
7298 {
7299 optimizeCustomActions.SkipAssignment = Wix.YesNoType.yes;
7300 }
7301
7302 if (0 != (Convert.ToInt32(OptimizeCA.SkipImmediate) & optimizeCA))
7303 {
7304 optimizeCustomActions.SkipImmediate = Wix.YesNoType.yes;
7305 }
7306
7307 if (0 != (Convert.ToInt32(OptimizeCA.SkipDeferred) & optimizeCA))
7308 {
7309 optimizeCustomActions.SkipDeferred = Wix.YesNoType.yes;
7310 }
7311
7312 patchMetadata.AddChild(optimizeCustomActions);
7313 break;
7314 case "OptimizedInstallMode":
7315 if ("1" == value)
7316 {
7317 patchMetadata.OptimizedInstallMode = Wix.YesNoType.yes;
7318 }
7319 break;
7320 case "TargetProductName":
7321 if (null != value)
7322 {
7323 patchMetadata.TargetProductName = value;
7324 }
7325 break;
7326 default:
7327 Wix.CustomProperty customProperty = new Wix.CustomProperty();
7328
7329 if (null != row[0])
7330 {
7331 customProperty.Company = Convert.ToString(row[0]);
7332 }
7333
7334 customProperty.Property = Convert.ToString(row[1]);
7335
7336 if (null != row[2])
7337 {
7338 customProperty.Value = Convert.ToString(row[2]);
7339 }
7340
7341 patchMetadata.AddChild(customProperty);
7342 break;
7343 }
7344 }
7345
7346 this.core.RootElement.AddChild(patchMetadata);
7347 }
7348 }
7349
7350 /// <summary>
7351 /// Decompile the PatchSequence table.
7352 /// </summary>
7353 /// <param name="table">The table to decompile.</param>
7354 private void DecompilePatchSequenceTable(Table table)
7355 {
7356 foreach (Row row in table.Rows)
7357 {
7358 Wix.PatchSequence patchSequence = new Wix.PatchSequence();
7359
7360 patchSequence.PatchFamily = Convert.ToString(row[0]);
7361
7362 if (null != row[1])
7363 {
7364 try
7365 {
7366 Guid guid = new Guid(Convert.ToString(row[1]));
7367
7368 patchSequence.ProductCode = Convert.ToString(row[1]);
7369 }
7370 catch // non-guid value
7371 {
7372 patchSequence.TargetImage = Convert.ToString(row[1]);
7373 }
7374 }
7375
7376 if (null != row[2])
7377 {
7378 patchSequence.Sequence = Convert.ToString(row[2]);
7379 }
7380
7381 if (null != row[3] && 0x1 == Convert.ToInt32(row[3]))
7382 {
7383 patchSequence.Supersede = Wix.YesNoType.yes;
7384 }
7385
7386 this.core.RootElement.AddChild(patchSequence);
7387 }
7388 }
7389
7390 /// <summary>
7391 /// Decompile the ProgId table.
7392 /// </summary>
7393 /// <param name="table">The table to decompile.</param>
7394 private void DecompileProgIdTable(Table table)
7395 {
7396 foreach (Row row in table.Rows)
7397 {
7398 Wix.ProgId progId = new Wix.ProgId();
7399
7400 progId.Advertise = Wix.YesNoType.yes;
7401
7402 progId.Id = Convert.ToString(row[0]);
7403
7404 if (null != row[3])
7405 {
7406 progId.Description = Convert.ToString(row[3]);
7407 }
7408
7409 if (null != row[4])
7410 {
7411 progId.Icon = Convert.ToString(row[4]);
7412 }
7413
7414 if (null != row[5])
7415 {
7416 progId.IconIndex = Convert.ToInt32(row[5]);
7417 }
7418
7419 this.core.IndexElement(row, progId);
7420 }
7421
7422 // nest the ProgIds
7423 foreach (Row row in table.Rows)
7424 {
7425 Wix.ProgId progId = (Wix.ProgId)this.core.GetIndexedElement(row);
7426
7427 if (null != row[1])
7428 {
7429 Wix.ProgId parentProgId = (Wix.ProgId)this.core.GetIndexedElement("ProgId", Convert.ToString(row[1]));
7430
7431 if (null != parentProgId)
7432 {
7433 parentProgId.AddChild(progId);
7434 }
7435 else
7436 {
7437 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "ProgId_Parent", Convert.ToString(row[1]), "ProgId"));
7438 }
7439 }
7440 else if (null != row[2])
7441 {
7442 // nesting is handled in FinalizeProgIdTable
7443 }
7444 else
7445 {
7446 // TODO: warn for orphaned ProgId
7447 }
7448 }
7449 }
7450
7451 /// <summary>
7452 /// Decompile the Properties table.
7453 /// </summary>
7454 /// <param name="table">The table to decompile.</param>
7455 private void DecompilePropertiesTable(Table table)
7456 {
7457 Wix.PatchCreation patchCreation = (Wix.PatchCreation)this.core.RootElement;
7458
7459 foreach (Row row in table.Rows)
7460 {
7461 string name = Convert.ToString(row[0]);
7462 string value = Convert.ToString(row[1]);
7463
7464 switch (name)
7465 {
7466 case "AllowProductCodeMismatches":
7467 if ("1" == value)
7468 {
7469 patchCreation.AllowProductCodeMismatches = Wix.YesNoType.yes;
7470 }
7471 break;
7472 case "AllowProductVersionMajorMismatches":
7473 if ("1" == value)
7474 {
7475 patchCreation.AllowMajorVersionMismatches = Wix.YesNoType.yes;
7476 }
7477 break;
7478 case "ApiPatchingSymbolFlags":
7479 if (null != value)
7480 {
7481 try
7482 {
7483 // remove the leading "0x" if its present
7484 if (value.StartsWith("0x", StringComparison.Ordinal))
7485 {
7486 value = value.Substring(2);
7487 }
7488
7489 patchCreation.SymbolFlags = Convert.ToInt32(value, 16);
7490 }
7491 catch
7492 {
7493 this.core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[1].Column.Name, row[1]));
7494 }
7495 }
7496 break;
7497 case "DontRemoveTempFolderWhenFinished":
7498 if ("1" == value)
7499 {
7500 patchCreation.CleanWorkingFolder = Wix.YesNoType.no;
7501 }
7502 break;
7503 case "IncludeWholeFilesOnly":
7504 if ("1" == value)
7505 {
7506 patchCreation.WholeFilesOnly = Wix.YesNoType.yes;
7507 }
7508 break;
7509 case "ListOfPatchGUIDsToReplace":
7510 if (null != value)
7511 {
7512 Regex guidRegex = new Regex(@"\{[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}\}");
7513 MatchCollection guidMatches = guidRegex.Matches(value);
7514
7515 foreach (Match guidMatch in guidMatches)
7516 {
7517 Wix.ReplacePatch replacePatch = new Wix.ReplacePatch();
7518
7519 replacePatch.Id = guidMatch.Value;
7520
7521 this.core.RootElement.AddChild(replacePatch);
7522 }
7523 }
7524 break;
7525 case "ListOfTargetProductCodes":
7526 if (null != value)
7527 {
7528 string[] targetProductCodes = value.Split(';');
7529
7530 foreach (string targetProductCodeString in targetProductCodes)
7531 {
7532 Wix.TargetProductCode targetProductCode = new Wix.TargetProductCode();
7533
7534 targetProductCode.Id = targetProductCodeString;
7535
7536 this.core.RootElement.AddChild(targetProductCode);
7537 }
7538 }
7539 break;
7540 case "PatchGUID":
7541 patchCreation.Id = value;
7542 break;
7543 case "PatchSourceList":
7544 patchCreation.SourceList = value;
7545 break;
7546 case "PatchOutputPath":
7547 patchCreation.OutputPath = value;
7548 break;
7549 default:
7550 Wix.PatchProperty patchProperty = new Wix.PatchProperty();
7551
7552 patchProperty.Name = name;
7553
7554 patchProperty.Value = value;
7555
7556 this.core.RootElement.AddChild(patchProperty);
7557 break;
7558 }
7559 }
7560 }
7561
7562 /// <summary>
7563 /// Decompile the Property table.
7564 /// </summary>
7565 /// <param name="table">The table to decompile.</param>
7566 private void DecompilePropertyTable(Table table)
7567 {
7568 foreach (Row row in table.Rows)
7569 {
7570 string id = Convert.ToString(row[0]);
7571 string value = Convert.ToString(row[1]);
7572
7573 if ("AdminProperties" == id || "MsiHiddenProperties" == id || "SecureCustomProperties" == id)
7574 {
7575 if (0 < value.Length)
7576 {
7577 foreach (string propertyId in value.Split(';'))
7578 {
7579 string property = propertyId;
7580 bool suppressModulularization = false;
7581 if (OutputType.Module == this.outputType)
7582 {
7583 if (propertyId.EndsWith(this.modularizationGuid.Substring(1, 36).Replace('-', '_'), StringComparison.Ordinal))
7584 {
7585 property = propertyId.Substring(0, propertyId.Length - this.modularizationGuid.Length + 1);
7586 }
7587 else
7588 {
7589 suppressModulularization = true;
7590 }
7591 }
7592
7593 Wix.Property specialProperty = this.EnsureProperty(property);
7594 if (suppressModulularization)
7595 {
7596 specialProperty.SuppressModularization = Wix.YesNoType.yes;
7597 }
7598
7599 switch (id)
7600 {
7601 case "AdminProperties":
7602 specialProperty.Admin = Wix.YesNoType.yes;
7603 break;
7604 case "MsiHiddenProperties":
7605 specialProperty.Hidden = Wix.YesNoType.yes;
7606 break;
7607 case "SecureCustomProperties":
7608 specialProperty.Secure = Wix.YesNoType.yes;
7609 break;
7610 }
7611 }
7612 }
7613
7614 continue;
7615 }
7616 else if (OutputType.Product == this.outputType)
7617 {
7618 Wix.Product product = (Wix.Product)this.core.RootElement;
7619
7620 switch (id)
7621 {
7622 case "Manufacturer":
7623 product.Manufacturer = value;
7624 continue;
7625 case "ProductCode":
7626 product.Id = value.ToUpper(CultureInfo.InvariantCulture);
7627 continue;
7628 case "ProductLanguage":
7629 product.Language = value;
7630 continue;
7631 case "ProductName":
7632 product.Name = value;
7633 continue;
7634 case "ProductVersion":
7635 product.Version = value;
7636 continue;
7637 case "UpgradeCode":
7638 product.UpgradeCode = value;
7639 continue;
7640 }
7641 }
7642
7643 if (!this.suppressUI || "ErrorDialog" != id)
7644 {
7645 Wix.Property property = this.EnsureProperty(id);
7646
7647 property.Value = value;
7648 }
7649 }
7650 }
7651
7652 /// <summary>
7653 /// Decompile the PublishComponent table.
7654 /// </summary>
7655 /// <param name="table">The table to decompile.</param>
7656 private void DecompilePublishComponentTable(Table table)
7657 {
7658 foreach (Row row in table.Rows)
7659 {
7660 Wix.Category category = new Wix.Category();
7661
7662 category.Id = Convert.ToString(row[0]);
7663
7664 category.Qualifier = Convert.ToString(row[1]);
7665
7666 if (null != row[3])
7667 {
7668 category.AppData = Convert.ToString(row[3]);
7669 }
7670
7671 Wix.Component component = (Wix.Component)this.core.GetIndexedElement("Component", Convert.ToString(row[2]));
7672 if (null != component)
7673 {
7674 component.AddChild(category);
7675 }
7676 else
7677 {
7678 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", Convert.ToString(row[2]), "Component"));
7679 }
7680 }
7681 }
7682
7683 /// <summary>
7684 /// Decompile the RadioButton table.
7685 /// </summary>
7686 /// <param name="table">The table to decompile.</param>
7687 private void DecompileRadioButtonTable(Table table)
7688 {
7689 SortedList radioButtons = new SortedList();
7690 Hashtable radioButtonGroups = new Hashtable();
7691
7692 foreach (Row row in table.Rows)
7693 {
7694 Wix.RadioButton radioButton = new Wix.RadioButton();
7695
7696 radioButton.Value = Convert.ToString(row[2]);
7697
7698 radioButton.X = Convert.ToString(row[3], CultureInfo.InvariantCulture);
7699
7700 radioButton.Y = Convert.ToString(row[4], CultureInfo.InvariantCulture);
7701
7702 radioButton.Width = Convert.ToString(row[5], CultureInfo.InvariantCulture);
7703
7704 radioButton.Height = Convert.ToString(row[6], CultureInfo.InvariantCulture);
7705
7706 if (null != row[7])
7707 {
7708 radioButton.Text = Convert.ToString(row[7]);
7709 }
7710
7711 if (null != row[8])
7712 {
7713 string[] help = (Convert.ToString(row[8])).Split('|');
7714
7715 if (2 == help.Length)
7716 {
7717 if (0 < help[0].Length)
7718 {
7719 radioButton.ToolTip = help[0];
7720 }
7721
7722 if (0 < help[1].Length)
7723 {
7724 radioButton.Help = help[1];
7725 }
7726 }
7727 }
7728
7729 radioButtons.Add(String.Format(CultureInfo.InvariantCulture, "{0}|{1:0000000000}", row[0], row[1]), row);
7730 this.core.IndexElement(row, radioButton);
7731 }
7732
7733 // nest the radio buttons
7734 foreach (Row row in radioButtons.Values)
7735 {
7736 Wix.RadioButton radioButton = (Wix.RadioButton)this.core.GetIndexedElement(row);
7737 Wix.RadioButtonGroup radioButtonGroup = (Wix.RadioButtonGroup)radioButtonGroups[Convert.ToString(row[0])];
7738
7739 if (null == radioButtonGroup)
7740 {
7741 radioButtonGroup = new Wix.RadioButtonGroup();
7742
7743 radioButtonGroup.Property = Convert.ToString(row[0]);
7744
7745 this.core.UIElement.AddChild(radioButtonGroup);
7746 radioButtonGroups.Add(Convert.ToString(row[0]), radioButtonGroup);
7747 }
7748
7749 radioButtonGroup.AddChild(radioButton);
7750 }
7751 }
7752
7753 /// <summary>
7754 /// Decompile the Registry table.
7755 /// </summary>
7756 /// <param name="table">The table to decompile.</param>
7757 private void DecompileRegistryTable(Table table)
7758 {
7759 foreach (Row row in table.Rows)
7760 {
7761 if (("-" == Convert.ToString(row[3]) || "+" == Convert.ToString(row[3]) || "*" == Convert.ToString(row[3])) && null == row[4])
7762 {
7763 Wix.RegistryKey registryKey = new Wix.RegistryKey();
7764
7765 registryKey.Id = Convert.ToString(row[0]);
7766
7767 Wix.RegistryRootType registryRootType;
7768 if (this.GetRegistryRootType(row.SourceLineNumbers, table.Name, row.Fields[1], out registryRootType))
7769 {
7770 registryKey.Root = registryRootType;
7771 }
7772
7773 registryKey.Key = Convert.ToString(row[2]);
7774
7775 switch (Convert.ToString(row[3]))
7776 {
7777 case "+":
7778 registryKey.ForceCreateOnInstall = Wix.YesNoType.yes;
7779 break;
7780 case "-":
7781 registryKey.ForceDeleteOnUninstall = Wix.YesNoType.yes;
7782 break;
7783 case "*":
7784 registryKey.ForceDeleteOnUninstall = Wix.YesNoType.yes;
7785 registryKey.ForceCreateOnInstall = Wix.YesNoType.yes;
7786 break;
7787 }
7788
7789 this.core.IndexElement(row, registryKey);
7790 }
7791 else
7792 {
7793 Wix.RegistryValue registryValue = new Wix.RegistryValue();
7794
7795 registryValue.Id = Convert.ToString(row[0]);
7796
7797 Wix.RegistryRootType registryRootType;
7798 if (this.GetRegistryRootType(row.SourceLineNumbers, table.Name, row.Fields[1], out registryRootType))
7799 {
7800 registryValue.Root = registryRootType;
7801 }
7802
7803 registryValue.Key = Convert.ToString(row[2]);
7804
7805 if (null != row[3])
7806 {
7807 registryValue.Name = Convert.ToString(row[3]);
7808 }
7809
7810 if (null != row[4])
7811 {
7812 string value = Convert.ToString(row[4]);
7813
7814 if (value.StartsWith("#x", StringComparison.Ordinal))
7815 {
7816 registryValue.Type = Wix.RegistryValue.TypeType.binary;
7817 registryValue.Value = value.Substring(2);
7818 }
7819 else if (value.StartsWith("#%", StringComparison.Ordinal))
7820 {
7821 registryValue.Type = Wix.RegistryValue.TypeType.expandable;
7822 registryValue.Value = value.Substring(2);
7823 }
7824 else if (value.StartsWith("#", StringComparison.Ordinal) && !value.StartsWith("##", StringComparison.Ordinal))
7825 {
7826 registryValue.Type = Wix.RegistryValue.TypeType.integer;
7827 registryValue.Value = value.Substring(1);
7828 }
7829 else
7830 {
7831 if (value.StartsWith("##", StringComparison.Ordinal))
7832 {
7833 value = value.Substring(1);
7834 }
7835
7836 if (0 <= value.IndexOf("[~]", StringComparison.Ordinal))
7837 {
7838 registryValue.Type = Wix.RegistryValue.TypeType.multiString;
7839
7840 if ("[~]" == value)
7841 {
7842 value = string.Empty;
7843 }
7844 else if (value.StartsWith("[~]", StringComparison.Ordinal) && value.EndsWith("[~]", StringComparison.Ordinal))
7845 {
7846 value = value.Substring(3, value.Length - 6);
7847 }
7848 else if (value.StartsWith("[~]", StringComparison.Ordinal))
7849 {
7850 registryValue.Action = Wix.RegistryValue.ActionType.append;
7851 value = value.Substring(3);
7852 }
7853 else if (value.EndsWith("[~]", StringComparison.Ordinal))
7854 {
7855 registryValue.Action = Wix.RegistryValue.ActionType.prepend;
7856 value = value.Substring(0, value.Length - 3);
7857 }
7858
7859 string[] multiValues = NullSplitter.Split(value);
7860 foreach (string multiValue in multiValues)
7861 {
7862 Wix.MultiStringValue multiStringValue = new Wix.MultiStringValue();
7863
7864 multiStringValue.Content = multiValue;
7865
7866 registryValue.AddChild(multiStringValue);
7867 }
7868 }
7869 else
7870 {
7871 registryValue.Type = Wix.RegistryValue.TypeType.@string;
7872 registryValue.Value = value;
7873 }
7874 }
7875 }
7876 else
7877 {
7878 registryValue.Type = Wix.RegistryValue.TypeType.@string;
7879 registryValue.Value = String.Empty;
7880 }
7881
7882 this.core.IndexElement(row, registryValue);
7883 }
7884 }
7885 }
7886
7887 /// <summary>
7888 /// Decompile the RegLocator table.
7889 /// </summary>
7890 /// <param name="table">The table to decompile.</param>
7891 private void DecompileRegLocatorTable(Table table)
7892 {
7893 foreach (Row row in table.Rows)
7894 {
7895 Wix.RegistrySearch registrySearch = new Wix.RegistrySearch();
7896
7897 registrySearch.Id = Convert.ToString(row[0]);
7898
7899 switch (Convert.ToInt32(row[1]))
7900 {
7901 case MsiInterop.MsidbRegistryRootClassesRoot:
7902 registrySearch.Root = Wix.RegistrySearch.RootType.HKCR;
7903 break;
7904 case MsiInterop.MsidbRegistryRootCurrentUser:
7905 registrySearch.Root = Wix.RegistrySearch.RootType.HKCU;
7906 break;
7907 case MsiInterop.MsidbRegistryRootLocalMachine:
7908 registrySearch.Root = Wix.RegistrySearch.RootType.HKLM;
7909 break;
7910 case MsiInterop.MsidbRegistryRootUsers:
7911 registrySearch.Root = Wix.RegistrySearch.RootType.HKU;
7912 break;
7913 default:
7914 this.core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[1].Column.Name, row[1]));
7915 break;
7916 }
7917
7918 registrySearch.Key = Convert.ToString(row[2]);
7919
7920 if (null != row[3])
7921 {
7922 registrySearch.Name = Convert.ToString(row[3]);
7923 }
7924
7925 if (null == row[4])
7926 {
7927 registrySearch.Type = Wix.RegistrySearch.TypeType.file;
7928 }
7929 else
7930 {
7931 int type = Convert.ToInt32(row[4]);
7932
7933 if (MsiInterop.MsidbLocatorType64bit == (type & MsiInterop.MsidbLocatorType64bit))
7934 {
7935 registrySearch.Win64 = Wix.YesNoType.yes;
7936 type &= ~MsiInterop.MsidbLocatorType64bit;
7937 }
7938
7939 switch (type)
7940 {
7941 case MsiInterop.MsidbLocatorTypeDirectory:
7942 registrySearch.Type = Wix.RegistrySearch.TypeType.directory;
7943 break;
7944 case MsiInterop.MsidbLocatorTypeFileName:
7945 registrySearch.Type = Wix.RegistrySearch.TypeType.file;
7946 break;
7947 case MsiInterop.MsidbLocatorTypeRawValue:
7948 registrySearch.Type = Wix.RegistrySearch.TypeType.raw;
7949 break;
7950 default:
7951 this.core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[4].Column.Name, row[4]));
7952 break;
7953 }
7954 }
7955
7956 this.core.IndexElement(row, registrySearch);
7957 }
7958 }
7959
7960 /// <summary>
7961 /// Decompile the RemoveFile table.
7962 /// </summary>
7963 /// <param name="table">The table to decompile.</param>
7964 private void DecompileRemoveFileTable(Table table)
7965 {
7966 foreach (Row row in table.Rows)
7967 {
7968 if (null == row[2])
7969 {
7970 Wix.RemoveFolder removeFolder = new Wix.RemoveFolder();
7971
7972 removeFolder.Id = Convert.ToString(row[0]);
7973
7974 // directory/property is set in FinalizeDecompile
7975
7976 switch (Convert.ToInt32(row[4]))
7977 {
7978 case MsiInterop.MsidbRemoveFileInstallModeOnInstall:
7979 removeFolder.On = Wix.InstallUninstallType.install;
7980 break;
7981 case MsiInterop.MsidbRemoveFileInstallModeOnRemove:
7982 removeFolder.On = Wix.InstallUninstallType.uninstall;
7983 break;
7984 case MsiInterop.MsidbRemoveFileInstallModeOnBoth:
7985 removeFolder.On = Wix.InstallUninstallType.both;
7986 break;
7987 default:
7988 this.core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[4].Column.Name, row[4]));
7989 break;
7990 }
7991
7992 Wix.Component component = (Wix.Component)this.core.GetIndexedElement("Component", Convert.ToString(row[1]));
7993 if (null != component)
7994 {
7995 component.AddChild(removeFolder);
7996 }
7997 else
7998 {
7999 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", Convert.ToString(row[1]), "Component"));
8000 }
8001 this.core.IndexElement(row, removeFolder);
8002 }
8003 else
8004 {
8005 Wix.RemoveFile removeFile = new Wix.RemoveFile();
8006
8007 removeFile.Id = Convert.ToString(row[0]);
8008
8009 string[] names = Common.GetNames(Convert.ToString(row[2]));
8010 if (null != names[0] && null != names[1])
8011 {
8012 removeFile.ShortName = names[0];
8013 removeFile.Name = names[1];
8014 }
8015 else if (null != names[0])
8016 {
8017 removeFile.Name = names[0];
8018 }
8019
8020 // directory/property is set in FinalizeDecompile
8021
8022 switch (Convert.ToInt32(row[4]))
8023 {
8024 case MsiInterop.MsidbRemoveFileInstallModeOnInstall:
8025 removeFile.On = Wix.InstallUninstallType.install;
8026 break;
8027 case MsiInterop.MsidbRemoveFileInstallModeOnRemove:
8028 removeFile.On = Wix.InstallUninstallType.uninstall;
8029 break;
8030 case MsiInterop.MsidbRemoveFileInstallModeOnBoth:
8031 removeFile.On = Wix.InstallUninstallType.both;
8032 break;
8033 default:
8034 this.core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[4].Column.Name, row[4]));
8035 break;
8036 }
8037
8038 Wix.Component component = (Wix.Component)this.core.GetIndexedElement("Component", Convert.ToString(row[1]));
8039 if (null != component)
8040 {
8041 component.AddChild(removeFile);
8042 }
8043 else
8044 {
8045 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", Convert.ToString(row[1]), "Component"));
8046 }
8047 this.core.IndexElement(row, removeFile);
8048 }
8049 }
8050 }
8051
8052 /// <summary>
8053 /// Decompile the RemoveIniFile table.
8054 /// </summary>
8055 /// <param name="table">The table to decompile.</param>
8056 private void DecompileRemoveIniFileTable(Table table)
8057 {
8058 foreach (Row row in table.Rows)
8059 {
8060 Wix.IniFile iniFile = new Wix.IniFile();
8061
8062 iniFile.Id = Convert.ToString(row[0]);
8063
8064 string[] names = Common.GetNames(Convert.ToString(row[1]));
8065 if (null != names[0] && null != names[1])
8066 {
8067 iniFile.ShortName = names[0];
8068 iniFile.Name = names[1];
8069 }
8070 else if (null != names[0])
8071 {
8072 iniFile.Name = names[0];
8073 }
8074
8075 if (null != row[2])
8076 {
8077 iniFile.Directory = Convert.ToString(row[2]);
8078 }
8079
8080 iniFile.Section = Convert.ToString(row[3]);
8081
8082 iniFile.Key = Convert.ToString(row[4]);
8083
8084 if (null != row[5])
8085 {
8086 iniFile.Value = Convert.ToString(row[5]);
8087 }
8088
8089 switch (Convert.ToInt32(row[6]))
8090 {
8091 case MsiInterop.MsidbIniFileActionRemoveLine:
8092 iniFile.Action = Wix.IniFile.ActionType.removeLine;
8093 break;
8094 case MsiInterop.MsidbIniFileActionRemoveTag:
8095 iniFile.Action = Wix.IniFile.ActionType.removeTag;
8096 break;
8097 default:
8098 this.core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[6].Column.Name, row[6]));
8099 break;
8100 }
8101
8102 Wix.Component component = (Wix.Component)this.core.GetIndexedElement("Component", Convert.ToString(row[7]));
8103 if (null != component)
8104 {
8105 component.AddChild(iniFile);
8106 }
8107 else
8108 {
8109 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", Convert.ToString(row[7]), "Component"));
8110 }
8111 }
8112 }
8113
8114 /// <summary>
8115 /// Decompile the RemoveRegistry table.
8116 /// </summary>
8117 /// <param name="table">The table to decompile.</param>
8118 private void DecompileRemoveRegistryTable(Table table)
8119 {
8120 foreach (Row row in table.Rows)
8121 {
8122 if ("-" == Convert.ToString(row[3]))
8123 {
8124 Wix.RemoveRegistryKey removeRegistryKey = new Wix.RemoveRegistryKey();
8125
8126 removeRegistryKey.Id = Convert.ToString(row[0]);
8127
8128 Wix.RegistryRootType registryRootType;
8129 if (this.GetRegistryRootType(row.SourceLineNumbers, table.Name, row.Fields[1], out registryRootType))
8130 {
8131 removeRegistryKey.Root = registryRootType;
8132 }
8133
8134 removeRegistryKey.Key = Convert.ToString(row[2]);
8135
8136 removeRegistryKey.Action = Wix.RemoveRegistryKey.ActionType.removeOnInstall;
8137
8138 Wix.Component component = (Wix.Component)this.core.GetIndexedElement("Component", Convert.ToString(row[4]));
8139 if (null != component)
8140 {
8141 component.AddChild(removeRegistryKey);
8142 }
8143 else
8144 {
8145 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", Convert.ToString(row[4]), "Component"));
8146 }
8147 }
8148 else
8149 {
8150 Wix.RemoveRegistryValue removeRegistryValue = new Wix.RemoveRegistryValue();
8151
8152 removeRegistryValue.Id = Convert.ToString(row[0]);
8153
8154 Wix.RegistryRootType registryRootType;
8155 if (this.GetRegistryRootType(row.SourceLineNumbers, table.Name, row.Fields[1], out registryRootType))
8156 {
8157 removeRegistryValue.Root = registryRootType;
8158 }
8159
8160 removeRegistryValue.Key = Convert.ToString(row[2]);
8161
8162 if (null != row[3])
8163 {
8164 removeRegistryValue.Name = Convert.ToString(row[3]);
8165 }
8166
8167 Wix.Component component = (Wix.Component)this.core.GetIndexedElement("Component", Convert.ToString(row[4]));
8168 if (null != component)
8169 {
8170 component.AddChild(removeRegistryValue);
8171 }
8172 else
8173 {
8174 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", Convert.ToString(row[4]), "Component"));
8175 }
8176 }
8177 }
8178 }
8179
8180 /// <summary>
8181 /// Decompile the ReserveCost table.
8182 /// </summary>
8183 /// <param name="table">The table to decompile.</param>
8184 private void DecompileReserveCostTable(Table table)
8185 {
8186 foreach (Row row in table.Rows)
8187 {
8188 Wix.ReserveCost reserveCost = new Wix.ReserveCost();
8189
8190 reserveCost.Id = Convert.ToString(row[0]);
8191
8192 if (null != row[2])
8193 {
8194 reserveCost.Directory = Convert.ToString(row[2]);
8195 }
8196
8197 reserveCost.RunLocal = Convert.ToInt32(row[3]);
8198
8199 reserveCost.RunFromSource = Convert.ToInt32(row[4]);
8200
8201 Wix.Component component = (Wix.Component)this.core.GetIndexedElement("Component", Convert.ToString(row[1]));
8202 if (null != component)
8203 {
8204 component.AddChild(reserveCost);
8205 }
8206 else
8207 {
8208 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", Convert.ToString(row[1]), "Component"));
8209 }
8210 }
8211 }
8212
8213 /// <summary>
8214 /// Decompile the SelfReg table.
8215 /// </summary>
8216 /// <param name="table">The table to decompile.</param>
8217 private void DecompileSelfRegTable(Table table)
8218 {
8219 foreach (Row row in table.Rows)
8220 {
8221 Wix.File file = (Wix.File)this.core.GetIndexedElement("File", Convert.ToString(row[0]));
8222
8223 if (null != file)
8224 {
8225 if (null != row[1])
8226 {
8227 file.SelfRegCost = Convert.ToInt32(row[1]);
8228 }
8229 else
8230 {
8231 file.SelfRegCost = 0;
8232 }
8233 }
8234 else
8235 {
8236 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "File_", Convert.ToString(row[0]), "File"));
8237 }
8238 }
8239 }
8240
8241 /// <summary>
8242 /// Decompile the ServiceControl table.
8243 /// </summary>
8244 /// <param name="table">The table to decompile.</param>
8245 private void DecompileServiceControlTable(Table table)
8246 {
8247 foreach (Row row in table.Rows)
8248 {
8249 Wix.ServiceControl serviceControl = new Wix.ServiceControl();
8250
8251 serviceControl.Id = Convert.ToString(row[0]);
8252
8253 serviceControl.Name = Convert.ToString(row[1]);
8254
8255 int eventValue = Convert.ToInt32(row[2]);
8256 if (MsiInterop.MsidbServiceControlEventStart == (eventValue & MsiInterop.MsidbServiceControlEventStart) &&
8257 MsiInterop.MsidbServiceControlEventUninstallStart == (eventValue & MsiInterop.MsidbServiceControlEventUninstallStart))
8258 {
8259 serviceControl.Start = Wix.InstallUninstallType.both;
8260 }
8261 else if (MsiInterop.MsidbServiceControlEventStart == (eventValue & MsiInterop.MsidbServiceControlEventStart))
8262 {
8263 serviceControl.Start = Wix.InstallUninstallType.install;
8264 }
8265 else if (MsiInterop.MsidbServiceControlEventUninstallStart == (eventValue & MsiInterop.MsidbServiceControlEventUninstallStart))
8266 {
8267 serviceControl.Start = Wix.InstallUninstallType.uninstall;
8268 }
8269
8270 if (MsiInterop.MsidbServiceControlEventStop == (eventValue & MsiInterop.MsidbServiceControlEventStop) &&
8271 MsiInterop.MsidbServiceControlEventUninstallStop == (eventValue & MsiInterop.MsidbServiceControlEventUninstallStop))
8272 {
8273 serviceControl.Stop = Wix.InstallUninstallType.both;
8274 }
8275 else if (MsiInterop.MsidbServiceControlEventStop == (eventValue & MsiInterop.MsidbServiceControlEventStop))
8276 {
8277 serviceControl.Stop = Wix.InstallUninstallType.install;
8278 }
8279 else if (MsiInterop.MsidbServiceControlEventUninstallStop == (eventValue & MsiInterop.MsidbServiceControlEventUninstallStop))
8280 {
8281 serviceControl.Stop = Wix.InstallUninstallType.uninstall;
8282 }
8283
8284 if (MsiInterop.MsidbServiceControlEventDelete == (eventValue & MsiInterop.MsidbServiceControlEventDelete) &&
8285 MsiInterop.MsidbServiceControlEventUninstallDelete == (eventValue & MsiInterop.MsidbServiceControlEventUninstallDelete))
8286 {
8287 serviceControl.Remove = Wix.InstallUninstallType.both;
8288 }
8289 else if (MsiInterop.MsidbServiceControlEventDelete == (eventValue & MsiInterop.MsidbServiceControlEventDelete))
8290 {
8291 serviceControl.Remove = Wix.InstallUninstallType.install;
8292 }
8293 else if (MsiInterop.MsidbServiceControlEventUninstallDelete == (eventValue & MsiInterop.MsidbServiceControlEventUninstallDelete))
8294 {
8295 serviceControl.Remove = Wix.InstallUninstallType.uninstall;
8296 }
8297
8298 if (null != row[3])
8299 {
8300 string[] arguments = NullSplitter.Split(Convert.ToString(row[3]));
8301
8302 foreach (string argument in arguments)
8303 {
8304 Wix.ServiceArgument serviceArgument = new Wix.ServiceArgument();
8305
8306 serviceArgument.Content = argument;
8307
8308 serviceControl.AddChild(serviceArgument);
8309 }
8310 }
8311
8312 if (null != row[4])
8313 {
8314 if (0 == Convert.ToInt32(row[4]))
8315 {
8316 serviceControl.Wait = Wix.YesNoType.no;
8317 }
8318 else
8319 {
8320 serviceControl.Wait = Wix.YesNoType.yes;
8321 }
8322 }
8323
8324 Wix.Component component = (Wix.Component)this.core.GetIndexedElement("Component", Convert.ToString(row[5]));
8325 if (null != component)
8326 {
8327 component.AddChild(serviceControl);
8328 }
8329 else
8330 {
8331 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", Convert.ToString(row[5]), "Component"));
8332 }
8333 }
8334 }
8335
8336 /// <summary>
8337 /// Decompile the ServiceInstall table.
8338 /// </summary>
8339 /// <param name="table">The table to decompile.</param>
8340 private void DecompileServiceInstallTable(Table table)
8341 {
8342 foreach (Row row in table.Rows)
8343 {
8344 Wix.ServiceInstall serviceInstall = new Wix.ServiceInstall();
8345
8346 serviceInstall.Id = Convert.ToString(row[0]);
8347
8348 serviceInstall.Name = Convert.ToString(row[1]);
8349
8350 if (null != row[2])
8351 {
8352 serviceInstall.DisplayName = Convert.ToString(row[2]);
8353 }
8354
8355 int serviceType = Convert.ToInt32(row[3]);
8356 if (MsiInterop.MsidbServiceInstallInteractive == (serviceType & MsiInterop.MsidbServiceInstallInteractive))
8357 {
8358 serviceInstall.Interactive = Wix.YesNoType.yes;
8359 }
8360
8361 if (MsiInterop.MsidbServiceInstallOwnProcess == (serviceType & MsiInterop.MsidbServiceInstallOwnProcess) &&
8362 MsiInterop.MsidbServiceInstallShareProcess == (serviceType & MsiInterop.MsidbServiceInstallShareProcess))
8363 {
8364 // TODO: warn
8365 }
8366 else if (MsiInterop.MsidbServiceInstallOwnProcess == (serviceType & MsiInterop.MsidbServiceInstallOwnProcess))
8367 {
8368 serviceInstall.Type = Wix.ServiceInstall.TypeType.ownProcess;
8369 }
8370 else if (MsiInterop.MsidbServiceInstallShareProcess == (serviceType & MsiInterop.MsidbServiceInstallShareProcess))
8371 {
8372 serviceInstall.Type = Wix.ServiceInstall.TypeType.shareProcess;
8373 }
8374
8375 int startType = Convert.ToInt32(row[4]);
8376 if (MsiInterop.MsidbServiceInstallDisabled == startType)
8377 {
8378 serviceInstall.Start = Wix.ServiceInstall.StartType.disabled;
8379 }
8380 else if (MsiInterop.MsidbServiceInstallDemandStart == startType)
8381 {
8382 serviceInstall.Start = Wix.ServiceInstall.StartType.demand;
8383 }
8384 else if (MsiInterop.MsidbServiceInstallAutoStart == startType)
8385 {
8386 serviceInstall.Start = Wix.ServiceInstall.StartType.auto;
8387 }
8388 else
8389 {
8390 this.core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[4].Column.Name, row[4]));
8391 }
8392
8393 int errorControl = Convert.ToInt32(row[5]);
8394 if (MsiInterop.MsidbServiceInstallErrorCritical == (errorControl & MsiInterop.MsidbServiceInstallErrorCritical))
8395 {
8396 serviceInstall.ErrorControl = Wix.ServiceInstall.ErrorControlType.critical;
8397 }
8398 else if (MsiInterop.MsidbServiceInstallErrorNormal == (errorControl & MsiInterop.MsidbServiceInstallErrorNormal))
8399 {
8400 serviceInstall.ErrorControl = Wix.ServiceInstall.ErrorControlType.normal;
8401 }
8402 else
8403 {
8404 serviceInstall.ErrorControl = Wix.ServiceInstall.ErrorControlType.ignore;
8405 }
8406
8407 if (MsiInterop.MsidbServiceInstallErrorControlVital == (errorControl & MsiInterop.MsidbServiceInstallErrorControlVital))
8408 {
8409 serviceInstall.Vital = Wix.YesNoType.yes;
8410 }
8411
8412 if (null != row[6])
8413 {
8414 serviceInstall.LoadOrderGroup = Convert.ToString(row[6]);
8415 }
8416
8417 if (null != row[7])
8418 {
8419 string[] dependencies = NullSplitter.Split(Convert.ToString(row[7]));
8420
8421 foreach (string dependency in dependencies)
8422 {
8423 if (0 < dependency.Length)
8424 {
8425 Wix.ServiceDependency serviceDependency = new Wix.ServiceDependency();
8426
8427 if (dependency.StartsWith("+", StringComparison.Ordinal))
8428 {
8429 serviceDependency.Group = Wix.YesNoType.yes;
8430 serviceDependency.Id = dependency.Substring(1);
8431 }
8432 else
8433 {
8434 serviceDependency.Id = dependency;
8435 }
8436
8437 serviceInstall.AddChild(serviceDependency);
8438 }
8439 }
8440 }
8441
8442 if (null != row[8])
8443 {
8444 serviceInstall.Account = Convert.ToString(row[8]);
8445 }
8446
8447 if (null != row[9])
8448 {
8449 serviceInstall.Password = Convert.ToString(row[9]);
8450 }
8451
8452 if (null != row[10])
8453 {
8454 serviceInstall.Arguments = Convert.ToString(row[10]);
8455 }
8456
8457 if (null != row[12])
8458 {
8459 serviceInstall.Description = Convert.ToString(row[12]);
8460 }
8461
8462 Wix.Component component = (Wix.Component)this.core.GetIndexedElement("Component", Convert.ToString(row[11]));
8463 if (null != component)
8464 {
8465 component.AddChild(serviceInstall);
8466 }
8467 else
8468 {
8469 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", Convert.ToString(row[11]), "Component"));
8470 }
8471 this.core.IndexElement(row, serviceInstall);
8472 }
8473 }
8474
8475 /// <summary>
8476 /// Decompile the SFPCatalog table.
8477 /// </summary>
8478 /// <param name="table">The table to decompile.</param>
8479 private void DecompileSFPCatalogTable(Table table)
8480 {
8481 foreach (Row row in table.Rows)
8482 {
8483 Wix.SFPCatalog sfpCatalog = new Wix.SFPCatalog();
8484
8485 sfpCatalog.Name = Convert.ToString(row[0]);
8486
8487 sfpCatalog.SourceFile = Convert.ToString(row[1]);
8488
8489 this.core.IndexElement(row, sfpCatalog);
8490 }
8491
8492 // nest the SFPCatalog elements
8493 foreach (Row row in table.Rows)
8494 {
8495 Wix.SFPCatalog sfpCatalog = (Wix.SFPCatalog)this.core.GetIndexedElement(row);
8496
8497 if (null != row[2])
8498 {
8499 Wix.SFPCatalog parentSFPCatalog = (Wix.SFPCatalog)this.core.GetIndexedElement("SFPCatalog", Convert.ToString(row[2]));
8500
8501 if (null != parentSFPCatalog)
8502 {
8503 parentSFPCatalog.AddChild(sfpCatalog);
8504 }
8505 else
8506 {
8507 sfpCatalog.Dependency = Convert.ToString(row[2]);
8508
8509 this.core.RootElement.AddChild(sfpCatalog);
8510 }
8511 }
8512 else
8513 {
8514 this.core.RootElement.AddChild(sfpCatalog);
8515 }
8516 }
8517 }
8518
8519 /// <summary>
8520 /// Decompile the Shortcut table.
8521 /// </summary>
8522 /// <param name="table">The table to decompile.</param>
8523 private void DecompileShortcutTable(Table table)
8524 {
8525 foreach (Row row in table.Rows)
8526 {
8527 Wix.Shortcut shortcut = new Wix.Shortcut();
8528
8529 shortcut.Id = Convert.ToString(row[0]);
8530
8531 shortcut.Directory = Convert.ToString(row[1]);
8532
8533 string[] names = Common.GetNames(Convert.ToString(row[2]));
8534 if (null != names[0] && null != names[1])
8535 {
8536 shortcut.ShortName = names[0];
8537 shortcut.Name = names[1];
8538 }
8539 else if (null != names[0])
8540 {
8541 shortcut.Name = names[0];
8542 }
8543
8544 string target = Convert.ToString(row[4]);
8545 if (target.StartsWith("[", StringComparison.Ordinal) && target.EndsWith("]", StringComparison.Ordinal))
8546 {
8547 // TODO: use this value to do a "more-correct" nesting under the indicated File or CreateDirectory element
8548 shortcut.Target = target;
8549 }
8550 else
8551 {
8552 shortcut.Advertise = Wix.YesNoType.yes;
8553
8554 // primary feature is set in FinalizeFeatureComponentsTable
8555 }
8556
8557 if (null != row[5])
8558 {
8559 shortcut.Arguments = Convert.ToString(row[5]);
8560 }
8561
8562 if (null != row[6])
8563 {
8564 shortcut.Description = Convert.ToString(row[6]);
8565 }
8566
8567 if (null != row[7])
8568 {
8569 shortcut.Hotkey = Convert.ToInt32(row[7]);
8570 }
8571
8572 if (null != row[8])
8573 {
8574 shortcut.Icon = Convert.ToString(row[8]);
8575 }
8576
8577 if (null != row[9])
8578 {
8579 shortcut.IconIndex = Convert.ToInt32(row[9]);
8580 }
8581
8582 if (null != row[10])
8583 {
8584 switch (Convert.ToInt32(row[10]))
8585 {
8586 case 1:
8587 shortcut.Show = Wix.Shortcut.ShowType.normal;
8588 break;
8589 case 3:
8590 shortcut.Show = Wix.Shortcut.ShowType.maximized;
8591 break;
8592 case 7:
8593 shortcut.Show = Wix.Shortcut.ShowType.minimized;
8594 break;
8595 default:
8596 this.core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[10].Column.Name, row[10]));
8597 break;
8598 }
8599 }
8600
8601 if (null != row[11])
8602 {
8603 shortcut.WorkingDirectory = Convert.ToString(row[11]);
8604 }
8605
8606 // Only try to read the MSI 4.0-specific columns if they actually exist
8607 if (15 < row.Fields.Length)
8608 {
8609 if (null != row[12])
8610 {
8611 shortcut.DisplayResourceDll = Convert.ToString(row[12]);
8612 }
8613
8614 if (null != row[13])
8615 {
8616 shortcut.DisplayResourceId = Convert.ToInt32(row[13]);
8617 }
8618
8619 if (null != row[14])
8620 {
8621 shortcut.DescriptionResourceDll = Convert.ToString(row[14]);
8622 }
8623
8624 if (null != row[15])
8625 {
8626 shortcut.DescriptionResourceId = Convert.ToInt32(row[15]);
8627 }
8628 }
8629
8630 Wix.Component component = (Wix.Component)this.core.GetIndexedElement("Component", Convert.ToString(row[3]));
8631 if (null != component)
8632 {
8633 component.AddChild(shortcut);
8634 }
8635 else
8636 {
8637 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", Convert.ToString(row[3]), "Component"));
8638 }
8639
8640 this.core.IndexElement(row, shortcut);
8641 }
8642 }
8643
8644 /// <summary>
8645 /// Decompile the Signature table.
8646 /// </summary>
8647 /// <param name="table">The table to decompile.</param>
8648 private void DecompileSignatureTable(Table table)
8649 {
8650 foreach (Row row in table.Rows)
8651 {
8652 Wix.FileSearch fileSearch = new Wix.FileSearch();
8653
8654 fileSearch.Id = Convert.ToString(row[0]);
8655
8656 string[] names = Common.GetNames(Convert.ToString(row[1]));
8657 if (null != names[0])
8658 {
8659 // it is permissable to just have a long name
8660 if (!this.core.IsValidShortFilename(names[0], false) && null == names[1])
8661 {
8662 fileSearch.Name = names[0];
8663 }
8664 else
8665 {
8666 fileSearch.ShortName = names[0];
8667 }
8668 }
8669
8670 if (null != names[1])
8671 {
8672 fileSearch.Name = names[1];
8673 }
8674
8675 if (null != row[2])
8676 {
8677 fileSearch.MinVersion = Convert.ToString(row[2]);
8678 }
8679
8680 if (null != row[3])
8681 {
8682 fileSearch.MaxVersion = Convert.ToString(row[3]);
8683 }
8684
8685 if (null != row[4])
8686 {
8687 fileSearch.MinSize = Convert.ToInt32(row[4]);
8688 }
8689
8690 if (null != row[5])
8691 {
8692 fileSearch.MaxSize = Convert.ToInt32(row[5]);
8693 }
8694
8695 if (null != row[6])
8696 {
8697 fileSearch.MinDate = this.core.ConvertIntegerToDateTime(Convert.ToInt32(row[6]));
8698 }
8699
8700 if (null != row[7])
8701 {
8702 fileSearch.MaxDate = this.core.ConvertIntegerToDateTime(Convert.ToInt32(row[7]));
8703 }
8704
8705 if (null != row[8])
8706 {
8707 fileSearch.Languages = Convert.ToString(row[8]);
8708 }
8709
8710 this.core.IndexElement(row, fileSearch);
8711 }
8712 }
8713
8714 /// <summary>
8715 /// Decompile the TargetFiles_OptionalData table.
8716 /// </summary>
8717 /// <param name="table">The table to decompile.</param>
8718 private void DecompileTargetFiles_OptionalDataTable(Table table)
8719 {
8720 foreach (Row row in table.Rows)
8721 {
8722 Wix.TargetFile targetFile = (Wix.TargetFile)this.patchTargetFiles[row[0]];
8723 if (null == targetFile)
8724 {
8725 targetFile = new Wix.TargetFile();
8726
8727 targetFile.Id = Convert.ToString(row[1]);
8728
8729 Wix.TargetImage targetImage = (Wix.TargetImage)this.core.GetIndexedElement("TargetImages", Convert.ToString(row[0]));
8730 if (null != targetImage)
8731 {
8732 targetImage.AddChild(targetFile);
8733 }
8734 else
8735 {
8736 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Target", Convert.ToString(row[0]), "TargetImages"));
8737 }
8738 this.patchTargetFiles.Add(row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), targetFile);
8739 }
8740
8741 if (null != row[2])
8742 {
8743 string[] symbolPaths = (Convert.ToString(row[2])).Split(';');
8744
8745 foreach (string symbolPathString in symbolPaths)
8746 {
8747 Wix.SymbolPath symbolPath = new Wix.SymbolPath();
8748
8749 symbolPath.Path = symbolPathString;
8750
8751 targetFile.AddChild(symbolPath);
8752 }
8753 }
8754
8755 if (null != row[3] && null != row[4])
8756 {
8757 string[] ignoreOffsets = (Convert.ToString(row[3])).Split(',');
8758 string[] ignoreLengths = (Convert.ToString(row[4])).Split(',');
8759
8760 if (ignoreOffsets.Length == ignoreLengths.Length)
8761 {
8762 for (int i = 0; i < ignoreOffsets.Length; i++)
8763 {
8764 Wix.IgnoreRange ignoreRange = new Wix.IgnoreRange();
8765
8766 if (ignoreOffsets[i].StartsWith("0x", StringComparison.Ordinal))
8767 {
8768 ignoreRange.Offset = Convert.ToInt32(ignoreOffsets[i].Substring(2), 16);
8769 }
8770 else
8771 {
8772 ignoreRange.Offset = Convert.ToInt32(ignoreOffsets[i], CultureInfo.InvariantCulture);
8773 }
8774
8775 if (ignoreLengths[i].StartsWith("0x", StringComparison.Ordinal))
8776 {
8777 ignoreRange.Length = Convert.ToInt32(ignoreLengths[i].Substring(2), 16);
8778 }
8779 else
8780 {
8781 ignoreRange.Length = Convert.ToInt32(ignoreLengths[i], CultureInfo.InvariantCulture);
8782 }
8783
8784 targetFile.AddChild(ignoreRange);
8785 }
8786 }
8787 else
8788 {
8789 // TODO: warn
8790 }
8791 }
8792 else if (null != row[3] || null != row[4])
8793 {
8794 // TODO: warn about mismatch between columns
8795 }
8796
8797 // the RetainOffsets column is handled in FinalizeFamilyFileRangesTable
8798 }
8799 }
8800
8801 /// <summary>
8802 /// Decompile the TargetImages table.
8803 /// </summary>
8804 /// <param name="table">The table to decompile.</param>
8805 private void DecompileTargetImagesTable(Table table)
8806 {
8807 foreach (Row row in table.Rows)
8808 {
8809 Wix.TargetImage targetImage = new Wix.TargetImage();
8810
8811 targetImage.Id = Convert.ToString(row[0]);
8812
8813 targetImage.SourceFile = Convert.ToString(row[1]);
8814
8815 if (null != row[2])
8816 {
8817 string[] symbolPaths = (Convert.ToString(row[3])).Split(';');
8818
8819 foreach (string symbolPathString in symbolPaths)
8820 {
8821 Wix.SymbolPath symbolPath = new Wix.SymbolPath();
8822
8823 symbolPath.Path = symbolPathString;
8824
8825 targetImage.AddChild(symbolPath);
8826 }
8827 }
8828
8829 targetImage.Order = Convert.ToInt32(row[4]);
8830
8831 if (null != row[5])
8832 {
8833 targetImage.Validation = Convert.ToString(row[5]);
8834 }
8835
8836 if (0 != Convert.ToInt32(row[6]))
8837 {
8838 targetImage.IgnoreMissingFiles = Wix.YesNoType.yes;
8839 }
8840
8841 Wix.UpgradeImage upgradeImage = (Wix.UpgradeImage)this.core.GetIndexedElement("UpgradedImages", Convert.ToString(row[3]));
8842 if (null != upgradeImage)
8843 {
8844 upgradeImage.AddChild(targetImage);
8845 }
8846 else
8847 {
8848 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Upgraded", Convert.ToString(row[3]), "UpgradedImages"));
8849 }
8850 this.core.IndexElement(row, targetImage);
8851 }
8852 }
8853
8854 /// <summary>
8855 /// Decompile the TextStyle table.
8856 /// </summary>
8857 /// <param name="table">The table to decompile.</param>
8858 private void DecompileTextStyleTable(Table table)
8859 {
8860 foreach (Row row in table.Rows)
8861 {
8862 Wix.TextStyle textStyle = new Wix.TextStyle();
8863
8864 textStyle.Id = Convert.ToString(row[0]);
8865
8866 textStyle.FaceName = Convert.ToString(row[1]);
8867
8868 textStyle.Size = Convert.ToString(row[2]);
8869
8870 if (null != row[3])
8871 {
8872 int color = Convert.ToInt32(row[3]);
8873
8874 textStyle.Red = color & 0xFF;
8875
8876 textStyle.Green = (color & 0xFF00) >> 8;
8877
8878 textStyle.Blue = (color & 0xFF0000) >> 16;
8879 }
8880
8881 if (null != row[4])
8882 {
8883 int styleBits = Convert.ToInt32(row[4]);
8884
8885 if (MsiInterop.MsidbTextStyleStyleBitsBold == (styleBits & MsiInterop.MsidbTextStyleStyleBitsBold))
8886 {
8887 textStyle.Bold = Wix.YesNoType.yes;
8888 }
8889
8890 if (MsiInterop.MsidbTextStyleStyleBitsItalic == (styleBits & MsiInterop.MsidbTextStyleStyleBitsItalic))
8891 {
8892 textStyle.Italic = Wix.YesNoType.yes;
8893 }
8894
8895 if (MsiInterop.MsidbTextStyleStyleBitsUnderline == (styleBits & MsiInterop.MsidbTextStyleStyleBitsUnderline))
8896 {
8897 textStyle.Underline = Wix.YesNoType.yes;
8898 }
8899
8900 if (MsiInterop.MsidbTextStyleStyleBitsStrike == (styleBits & MsiInterop.MsidbTextStyleStyleBitsStrike))
8901 {
8902 textStyle.Strike = Wix.YesNoType.yes;
8903 }
8904 }
8905
8906 this.core.UIElement.AddChild(textStyle);
8907 }
8908 }
8909
8910 /// <summary>
8911 /// Decompile the TypeLib table.
8912 /// </summary>
8913 /// <param name="table">The table to decompile.</param>
8914 private void DecompileTypeLibTable(Table table)
8915 {
8916 foreach (Row row in table.Rows)
8917 {
8918 Wix.TypeLib typeLib = new Wix.TypeLib();
8919
8920 typeLib.Id = Convert.ToString(row[0]);
8921
8922 typeLib.Advertise = Wix.YesNoType.yes;
8923
8924 typeLib.Language = Convert.ToInt32(row[1]);
8925
8926 if (null != row[3])
8927 {
8928 int version = Convert.ToInt32(row[3]);
8929
8930 if (65536 == version)
8931 {
8932 this.core.OnMessage(WixWarnings.PossiblyIncorrectTypelibVersion(row.SourceLineNumbers, typeLib.Id));
8933 }
8934
8935 typeLib.MajorVersion = ((version & 0xFFFF00) >> 8);
8936 typeLib.MinorVersion = (version & 0xFF);
8937 }
8938
8939 if (null != row[4])
8940 {
8941 typeLib.Description = Convert.ToString(row[4]);
8942 }
8943
8944 if (null != row[5])
8945 {
8946 typeLib.HelpDirectory = Convert.ToString(row[5]);
8947 }
8948
8949 if (null != row[7])
8950 {
8951 typeLib.Cost = Convert.ToInt32(row[7]);
8952 }
8953
8954 // nested under the appropriate File element in FinalizeFileTable
8955 this.core.IndexElement(row, typeLib);
8956 }
8957 }
8958
8959 /// <summary>
8960 /// Decompile the Upgrade table.
8961 /// </summary>
8962 /// <param name="table">The table to decompile.</param>
8963 private void DecompileUpgradeTable(Table table)
8964 {
8965 Hashtable upgradeElements = new Hashtable();
8966
8967 foreach (UpgradeRow upgradeRow in table.Rows)
8968 {
8969 if (Compiler.UpgradeDetectedProperty == upgradeRow.ActionProperty || Compiler.DowngradeDetectedProperty == upgradeRow.ActionProperty)
8970 {
8971 continue; // MajorUpgrade rows processed in FinalizeUpgradeTable
8972 }
8973
8974 Wix.Upgrade upgrade = (Wix.Upgrade)upgradeElements[upgradeRow.UpgradeCode];
8975
8976 // create the parent Upgrade element if it doesn't already exist
8977 if (null == upgrade)
8978 {
8979 upgrade = new Wix.Upgrade();
8980
8981 upgrade.Id = upgradeRow.UpgradeCode;
8982
8983 this.core.RootElement.AddChild(upgrade);
8984 upgradeElements.Add(upgrade.Id, upgrade);
8985 }
8986
8987 Wix.UpgradeVersion upgradeVersion = new Wix.UpgradeVersion();
8988
8989 if (null != upgradeRow.VersionMin)
8990 {
8991 upgradeVersion.Minimum = upgradeRow.VersionMin;
8992 }
8993
8994 if (null != upgradeRow.VersionMax)
8995 {
8996 upgradeVersion.Maximum = upgradeRow.VersionMax;
8997 }
8998
8999 if (null != upgradeRow.Language)
9000 {
9001 upgradeVersion.Language = upgradeRow.Language;
9002 }
9003
9004 if (MsiInterop.MsidbUpgradeAttributesMigrateFeatures == (upgradeRow.Attributes & MsiInterop.MsidbUpgradeAttributesMigrateFeatures))
9005 {
9006 upgradeVersion.MigrateFeatures = Wix.YesNoType.yes;
9007 }
9008
9009 if (MsiInterop.MsidbUpgradeAttributesOnlyDetect == (upgradeRow.Attributes & MsiInterop.MsidbUpgradeAttributesOnlyDetect))
9010 {
9011 upgradeVersion.OnlyDetect = Wix.YesNoType.yes;
9012 }
9013
9014 if (MsiInterop.MsidbUpgradeAttributesIgnoreRemoveFailure == (upgradeRow.Attributes & MsiInterop.MsidbUpgradeAttributesIgnoreRemoveFailure))
9015 {
9016 upgradeVersion.IgnoreRemoveFailure = Wix.YesNoType.yes;
9017 }
9018
9019 if (MsiInterop.MsidbUpgradeAttributesVersionMinInclusive == (upgradeRow.Attributes & MsiInterop.MsidbUpgradeAttributesVersionMinInclusive))
9020 {
9021 upgradeVersion.IncludeMinimum = Wix.YesNoType.yes;
9022 }
9023
9024 if (MsiInterop.MsidbUpgradeAttributesVersionMaxInclusive == (upgradeRow.Attributes & MsiInterop.MsidbUpgradeAttributesVersionMaxInclusive))
9025 {
9026 upgradeVersion.IncludeMaximum = Wix.YesNoType.yes;
9027 }
9028
9029 if (MsiInterop.MsidbUpgradeAttributesLanguagesExclusive == (upgradeRow.Attributes & MsiInterop.MsidbUpgradeAttributesLanguagesExclusive))
9030 {
9031 upgradeVersion.ExcludeLanguages = Wix.YesNoType.yes;
9032 }
9033
9034 if (null != upgradeRow.Remove)
9035 {
9036 upgradeVersion.RemoveFeatures = upgradeRow.Remove;
9037 }
9038
9039 upgradeVersion.Property = upgradeRow.ActionProperty;
9040
9041 upgrade.AddChild(upgradeVersion);
9042 }
9043 }
9044
9045 /// <summary>
9046 /// Decompile the UpgradedFiles_OptionalData table.
9047 /// </summary>
9048 /// <param name="table">The table to decompile.</param>
9049 private void DecompileUpgradedFiles_OptionalDataTable(Table table)
9050 {
9051 foreach (Row row in table.Rows)
9052 {
9053 Wix.UpgradeFile upgradeFile = new Wix.UpgradeFile();
9054
9055 upgradeFile.File = Convert.ToString(row[1]);
9056
9057 if (null != row[2])
9058 {
9059 string[] symbolPaths = (Convert.ToString(row[2])).Split(';');
9060
9061 foreach (string symbolPathString in symbolPaths)
9062 {
9063 Wix.SymbolPath symbolPath = new Wix.SymbolPath();
9064
9065 symbolPath.Path = symbolPathString;
9066
9067 upgradeFile.AddChild(symbolPath);
9068 }
9069 }
9070
9071 if (null != row[3] && 1 == Convert.ToInt32(row[3]))
9072 {
9073 upgradeFile.AllowIgnoreOnError = Wix.YesNoType.yes;
9074 }
9075
9076 if (null != row[4] && 0 != Convert.ToInt32(row[4]))
9077 {
9078 upgradeFile.WholeFile = Wix.YesNoType.yes;
9079 }
9080
9081 upgradeFile.Ignore = Wix.YesNoType.no;
9082
9083 Wix.UpgradeImage upgradeImage = (Wix.UpgradeImage)this.core.GetIndexedElement("UpgradedImages", Convert.ToString(row[0]));
9084 if (null != upgradeImage)
9085 {
9086 upgradeImage.AddChild(upgradeFile);
9087 }
9088 else
9089 {
9090 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Upgraded", Convert.ToString(row[0]), "UpgradedImages"));
9091 }
9092 }
9093 }
9094
9095 /// <summary>
9096 /// Decompile the UpgradedFilesToIgnore table.
9097 /// </summary>
9098 /// <param name="table">The table to decompile.</param>
9099 private void DecompileUpgradedFilesToIgnoreTable(Table table)
9100 {
9101 foreach (Row row in table.Rows)
9102 {
9103 if ("*" != Convert.ToString(row[0]))
9104 {
9105 Wix.UpgradeFile upgradeFile = new Wix.UpgradeFile();
9106
9107 upgradeFile.File = Convert.ToString(row[1]);
9108
9109 upgradeFile.Ignore = Wix.YesNoType.yes;
9110
9111 Wix.UpgradeImage upgradeImage = (Wix.UpgradeImage)this.core.GetIndexedElement("UpgradedImages", Convert.ToString(row[0]));
9112 if (null != upgradeImage)
9113 {
9114 upgradeImage.AddChild(upgradeFile);
9115 }
9116 else
9117 {
9118 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Upgraded", Convert.ToString(row[0]), "UpgradedImages"));
9119 }
9120 }
9121 else
9122 {
9123 this.core.OnMessage(WixWarnings.UnrepresentableColumnValue(row.SourceLineNumbers, table.Name, row.Fields[0].Column.Name, row[0]));
9124 }
9125 }
9126 }
9127
9128 /// <summary>
9129 /// Decompile the UpgradedImages table.
9130 /// </summary>
9131 /// <param name="table">The table to decompile.</param>
9132 private void DecompileUpgradedImagesTable(Table table)
9133 {
9134 foreach (Row row in table.Rows)
9135 {
9136 Wix.UpgradeImage upgradeImage = new Wix.UpgradeImage();
9137
9138 upgradeImage.Id = Convert.ToString(row[0]);
9139
9140 upgradeImage.SourceFile = Convert.ToString(row[1]);
9141
9142 if (null != row[2])
9143 {
9144 upgradeImage.SourcePatch = Convert.ToString(row[2]);
9145 }
9146
9147 if (null != row[3])
9148 {
9149 string[] symbolPaths = (Convert.ToString(row[3])).Split(';');
9150
9151 foreach (string symbolPathString in symbolPaths)
9152 {
9153 Wix.SymbolPath symbolPath = new Wix.SymbolPath();
9154
9155 symbolPath.Path = symbolPathString;
9156
9157 upgradeImage.AddChild(symbolPath);
9158 }
9159 }
9160
9161 Wix.Family family = (Wix.Family)this.core.GetIndexedElement("ImageFamilies", Convert.ToString(row[4]));
9162 if (null != family)
9163 {
9164 family.AddChild(upgradeImage);
9165 }
9166 else
9167 {
9168 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Family", Convert.ToString(row[4]), "ImageFamilies"));
9169 }
9170 this.core.IndexElement(row, upgradeImage);
9171 }
9172 }
9173
9174 /// <summary>
9175 /// Decompile the UIText table.
9176 /// </summary>
9177 /// <param name="table">The table to decompile.</param>
9178 private void DecompileUITextTable(Table table)
9179 {
9180 foreach (Row row in table.Rows)
9181 {
9182 Wix.UIText uiText = new Wix.UIText();
9183
9184 uiText.Id = Convert.ToString(row[0]);
9185
9186 uiText.Content = Convert.ToString(row[1]);
9187
9188 this.core.UIElement.AddChild(uiText);
9189 }
9190 }
9191
9192 /// <summary>
9193 /// Decompile the Verb table.
9194 /// </summary>
9195 /// <param name="table">The table to decompile.</param>
9196 private void DecompileVerbTable(Table table)
9197 {
9198 foreach (Row row in table.Rows)
9199 {
9200 Wix.Verb verb = new Wix.Verb();
9201
9202 verb.Id = Convert.ToString(row[1]);
9203
9204 if (null != row[2])
9205 {
9206 verb.Sequence = Convert.ToInt32(row[2]);
9207 }
9208
9209 if (null != row[3])
9210 {
9211 verb.Command = Convert.ToString(row[3]);
9212 }
9213
9214 if (null != row[4])
9215 {
9216 verb.Argument = Convert.ToString(row[4]);
9217 }
9218
9219 this.core.IndexElement(row, verb);
9220 }
9221 }
9222
9223 /// <summary>
9224 /// Gets the RegistryRootType from an integer representation of the root.
9225 /// </summary>
9226 /// <param name="sourceLineNumbers">The source line information for the root.</param>
9227 /// <param name="tableName">The name of the table containing the field.</param>
9228 /// <param name="field">The field containing the root value.</param>
9229 /// <param name="registryRootType">The strongly-typed representation of the root.</param>
9230 /// <returns>true if the value could be converted; false otherwise.</returns>
9231 private bool GetRegistryRootType(SourceLineNumber sourceLineNumbers, string tableName, Field field, out Wix.RegistryRootType registryRootType)
9232 {
9233 switch (Convert.ToInt32(field.Data))
9234 {
9235 case (-1):
9236 registryRootType = Wix.RegistryRootType.HKMU;
9237 return true;
9238 case MsiInterop.MsidbRegistryRootClassesRoot:
9239 registryRootType = Wix.RegistryRootType.HKCR;
9240 return true;
9241 case MsiInterop.MsidbRegistryRootCurrentUser:
9242 registryRootType = Wix.RegistryRootType.HKCU;
9243 return true;
9244 case MsiInterop.MsidbRegistryRootLocalMachine:
9245 registryRootType = Wix.RegistryRootType.HKLM;
9246 return true;
9247 case MsiInterop.MsidbRegistryRootUsers:
9248 registryRootType = Wix.RegistryRootType.HKU;
9249 return true;
9250 default:
9251 this.core.OnMessage(WixWarnings.IllegalColumnValue(sourceLineNumbers, tableName, field.Column.Name, field.Data));
9252 registryRootType = Wix.RegistryRootType.HKCR; // assign anything to satisfy the out parameter
9253 return false;
9254 }
9255 }
9256
9257 /// <summary>
9258 /// Set the primary feature for a component.
9259 /// </summary>
9260 /// <param name="row">The row which specifies a primary feature.</param>
9261 /// <param name="featureColumnIndex">The index of the column contaning the feature identifier.</param>
9262 /// <param name="componentColumnIndex">The index of the column containing the component identifier.</param>
9263 private void SetPrimaryFeature(Row row, int featureColumnIndex, int componentColumnIndex)
9264 {
9265 // only products contain primary features
9266 if (OutputType.Product == this.outputType)
9267 {
9268 Field featureField = row.Fields[featureColumnIndex];
9269 Field componentField = row.Fields[componentColumnIndex];
9270
9271 Wix.ComponentRef componentRef = (Wix.ComponentRef)this.core.GetIndexedElement("FeatureComponents", Convert.ToString(featureField.Data), Convert.ToString(componentField.Data));
9272
9273 if (null != componentRef)
9274 {
9275 componentRef.Primary = Wix.YesNoType.yes;
9276 }
9277 else
9278 {
9279 this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, row.TableDefinition.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), featureField.Column.Name, Convert.ToString(featureField.Data), componentField.Column.Name, Convert.ToString(componentField.Data), "FeatureComponents"));
9280 }
9281 }
9282 }
9283
9284 /// <summary>
9285 /// Checks the InstallExecuteSequence table to determine where RemoveExistingProducts is scheduled and removes it.
9286 /// </summary>
9287 /// <param name="tables">The collection of all tables.</param>
9288 private static Wix.MajorUpgrade.ScheduleType DetermineMajorUpgradeScheduling(TableIndexedCollection tables)
9289 {
9290 int sequenceRemoveExistingProducts = 0;
9291 int sequenceInstallValidate = 0;
9292 int sequenceInstallInitialize = 0;
9293 int sequenceInstallFinalize = 0;
9294 int sequenceInstallExecute = 0;
9295 int sequenceInstallExecuteAgain = 0;
9296
9297 Table installExecuteSequenceTable = tables["InstallExecuteSequence"];
9298 if (null != installExecuteSequenceTable)
9299 {
9300 int removeExistingProductsRow = -1;
9301 for (int i = 0; i < installExecuteSequenceTable.Rows.Count; i++)
9302 {
9303 Row row = installExecuteSequenceTable.Rows[i];
9304 string action = Convert.ToString(row[0]);
9305 int sequence = Convert.ToInt32(row[2]);
9306
9307 switch (action)
9308 {
9309 case "RemoveExistingProducts":
9310 sequenceRemoveExistingProducts = sequence;
9311 removeExistingProductsRow = i;
9312 break;
9313 case "InstallValidate":
9314 sequenceInstallValidate = sequence;
9315 break;
9316 case "InstallInitialize":
9317 sequenceInstallInitialize = sequence;
9318 break;
9319 case "InstallExecute":
9320 sequenceInstallExecute = sequence;
9321 break;
9322 case "InstallExecuteAgain":
9323 sequenceInstallExecuteAgain = sequence;
9324 break;
9325 case "InstallFinalize":
9326 sequenceInstallFinalize = sequence;
9327 break;
9328 }
9329 }
9330
9331 installExecuteSequenceTable.Rows.RemoveAt(removeExistingProductsRow);
9332 }
9333
9334 if (0 != sequenceInstallValidate && sequenceInstallValidate < sequenceRemoveExistingProducts && sequenceRemoveExistingProducts < sequenceInstallInitialize)
9335 {
9336 return Wix.MajorUpgrade.ScheduleType.afterInstallValidate;
9337 }
9338 else if (0 != sequenceInstallInitialize && sequenceInstallInitialize < sequenceRemoveExistingProducts && sequenceRemoveExistingProducts < sequenceInstallExecute)
9339 {
9340 return Wix.MajorUpgrade.ScheduleType.afterInstallInitialize;
9341 }
9342 else if (0 != sequenceInstallExecute && sequenceInstallExecute < sequenceRemoveExistingProducts && sequenceRemoveExistingProducts < sequenceInstallExecuteAgain)
9343 {
9344 return Wix.MajorUpgrade.ScheduleType.afterInstallExecute;
9345 }
9346 else if (0 != sequenceInstallExecuteAgain && sequenceInstallExecuteAgain < sequenceRemoveExistingProducts && sequenceRemoveExistingProducts < sequenceInstallFinalize)
9347 {
9348 return Wix.MajorUpgrade.ScheduleType.afterInstallExecuteAgain;
9349 }
9350 else
9351 {
9352 return Wix.MajorUpgrade.ScheduleType.afterInstallFinalize;
9353 }
9354 }
9355#endif
9356 }
9357}