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