// 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.
namespace WixToolset.Extensions
{
#if TODO_CONSIDER_DECOMPILER
using System;
using System.IO;
using System.Text;
using System.Collections;
using System.Diagnostics;
using System.Globalization;
using Util = WixToolset.Extensions.Serialize.Util;
using WixToolset.Data;
using WixToolset.Extensibility;
using Wix = WixToolset.Data.Serialize;
///
/// The decompiler for the WiX Toolset Utility Extension.
///
public sealed class UtilDecompiler : DecompilerExtension
{
///
/// Creates a decompiler for Utility Extension.
///
public UtilDecompiler()
{
this.TableDefinitions = UtilExtensionData.GetExtensionTableDefinitions();
}
///
/// Get the extensions library to be removed.
///
/// Table definitions for library.
/// Library to remove from decompiled output.
public override Library GetLibraryToRemove(TableDefinitionCollection tableDefinitions)
{
return UtilExtensionData.GetExtensionLibrary(tableDefinitions);
}
///
/// Called at the beginning of the decompilation of a database.
///
/// The collection of all tables.
public override void Initialize(TableIndexedCollection tables)
{
this.CleanupSecureCustomProperties(tables);
this.CleanupInternetShortcutRemoveFileTables(tables);
}
///
/// Decompile the SecureCustomProperties field to PropertyRefs for known extension properties.
///
///
/// If we've referenced any of the suite or directory properties, add
/// a PropertyRef to refer to the Property (and associated custom action)
/// from the extension's library. Then remove the property from
/// SecureCustomExtensions property so later decompilation won't create
/// new Property elements.
///
/// The collection of all tables.
private void CleanupSecureCustomProperties(TableIndexedCollection tables)
{
Table propertyTable = tables["Property"];
if (null != propertyTable)
{
foreach (Row row in propertyTable.Rows)
{
if ("SecureCustomProperties" == row[0].ToString())
{
StringBuilder remainingProperties = new StringBuilder();
string[] secureCustomProperties = row[1].ToString().Split(';');
foreach (string property in secureCustomProperties)
{
if (property.StartsWith("WIX_SUITE_", StringComparison.Ordinal) || property.StartsWith("WIX_DIR_", StringComparison.Ordinal)
|| property.StartsWith("WIX_ACCOUNT_", StringComparison.Ordinal))
{
Wix.PropertyRef propertyRef = new Wix.PropertyRef();
propertyRef.Id = property;
this.Core.RootElement.AddChild(propertyRef);
}
else
{
if (0 < remainingProperties.Length)
{
remainingProperties.Append(";");
}
remainingProperties.Append(property);
}
}
row[1] = remainingProperties.ToString();
break;
}
}
}
}
///
/// Remove RemoveFile rows that the InternetShortcut compiler extension adds for us.
///
/// The collection of all tables.
private void CleanupInternetShortcutRemoveFileTables(TableIndexedCollection tables)
{
// index the WixInternetShortcut table
Table wixInternetShortcutTable = tables["WixInternetShortcut"];
Hashtable wixInternetShortcuts = new Hashtable();
if (null != wixInternetShortcutTable)
{
foreach (Row row in wixInternetShortcutTable.Rows)
{
wixInternetShortcuts.Add(row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), row);
}
}
// remove the RemoveFile rows with primary keys that match the WixInternetShortcut table's
Table removeFileTable = tables["RemoveFile"];
if (null != removeFileTable)
{
for (int i = removeFileTable.Rows.Count - 1; 0 <= i; i--)
{
if (null != wixInternetShortcuts[removeFileTable.Rows[i][0]])
{
removeFileTable.Rows.RemoveAt(i);
}
}
}
}
///
/// Decompiles an extension table.
///
/// The table to decompile.
public override void DecompileTable(Table table)
{
switch (table.Name)
{
case "WixCloseApplication":
this.DecompileWixCloseApplicationTable(table);
break;
case "WixRemoveFolderEx":
this.DecompileWixRemoveFolderExTable(table);
break;
case "WixRestartResource":
this.DecompileWixRestartResourceTable(table);
break;
case "FileShare":
this.DecompileFileShareTable(table);
break;
case "FileSharePermissions":
this.DecompileFileSharePermissionsTable(table);
break;
case "WixInternetShortcut":
this.DecompileWixInternetShortcutTable(table);
break;
case "Group":
this.DecompileGroupTable(table);
break;
case "Perfmon":
this.DecompilePerfmonTable(table);
break;
case "PerfmonManifest":
this.DecompilePerfmonManifestTable(table);
break;
case "EventManifest":
this.DecompileEventManifestTable(table);
break;
case "SecureObjects":
this.DecompileSecureObjectsTable(table);
break;
case "ServiceConfig":
this.DecompileServiceConfigTable(table);
break;
case "User":
this.DecompileUserTable(table);
break;
case "UserGroup":
this.DecompileUserGroupTable(table);
break;
case "XmlConfig":
this.DecompileXmlConfigTable(table);
break;
case "XmlFile":
// XmlFile decompilation has been moved to FinalizeXmlFileTable function
break;
default:
base.DecompileTable(table);
break;
}
}
///
/// Finalize decompilation.
///
/// The collection of all tables.
public override void Finish(TableIndexedCollection tables)
{
this.FinalizePerfmonTable(tables);
this.FinalizePerfmonManifestTable(tables);
this.FinalizeSecureObjectsTable(tables);
this.FinalizeServiceConfigTable(tables);
this.FinalizeXmlConfigTable(tables);
this.FinalizeXmlFileTable(tables);
this.FinalizeEventManifestTable(tables);
}
///
/// Decompile the WixCloseApplication table.
///
/// The table to decompile.
private void DecompileWixCloseApplicationTable(Table table)
{
foreach (Row row in table.Rows)
{
Util.CloseApplication closeApplication = new Util.CloseApplication();
closeApplication.Id = (string)row[0];
closeApplication.Target = (string)row[1];
if (null != row[2])
{
closeApplication.Description = (string)row[2];
}
if (null != row[3])
{
closeApplication.Content = (string)row[3];
}
// set defaults
closeApplication.CloseMessage = Util.YesNoType.no;
closeApplication.RebootPrompt = Util.YesNoType.yes;
closeApplication.ElevatedCloseMessage = Util.YesNoType.no;
if (null != row[4])
{
int attribute = (int)row[4];
closeApplication.CloseMessage = (0x1 == (attribute & 0x1)) ? Util.YesNoType.yes : Util.YesNoType.no;
closeApplication.RebootPrompt = (0x2 == (attribute & 0x2)) ? Util.YesNoType.yes : Util.YesNoType.no;
closeApplication.ElevatedCloseMessage = (0x4 == (attribute & 0x4)) ? Util.YesNoType.yes : Util.YesNoType.no;
}
if (null != row[5])
{
closeApplication.Sequence = (int)row[5];
}
if (null != row[6])
{
closeApplication.Property = (string)row[6];
}
this.Core.RootElement.AddChild(closeApplication);
}
}
///
/// Decompile the WixRemoveFolderEx table.
///
/// The table to decompile.
private void DecompileWixRemoveFolderExTable(Table table)
{
foreach (Row row in table.Rows)
{
// Set the Id even if auto-generated previously.
Util.RemoveFolderEx removeFolder = new Util.RemoveFolderEx();
removeFolder.Id = (string)row[0];
removeFolder.Property = (string)row[2];
int installMode = (int)row[3];
switch ((UtilCompiler.WixRemoveFolderExOn)installMode)
{
case UtilCompiler.WixRemoveFolderExOn.Install:
removeFolder.On = Util.RemoveFolderEx.OnType.install;
break;
case UtilCompiler.WixRemoveFolderExOn.Uninstall:
removeFolder.On = Util.RemoveFolderEx.OnType.uninstall;
break;
case UtilCompiler.WixRemoveFolderExOn.Both:
removeFolder.On = Util.RemoveFolderEx.OnType.both;
break;
default:
this.Core.OnMessage(WixWarnings.UnrepresentableColumnValue(row.SourceLineNumbers, table.Name, "InstallMode", installMode));
break;
}
// Add to the appropriate Component or section element.
string componentId = (string)row[1];
Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", componentId);
if (null != component)
{
component.AddChild(removeFolder);
}
else
{
this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", componentId, "Component"));
}
}
}
///
/// Decompile the WixRestartResource table.
///
/// The table to decompile.
private void DecompileWixRestartResourceTable(Table table)
{
foreach (Row row in table.Rows)
{
// Set the Id even if auto-generated previously.
Util.RestartResource restartResource = new Util.RestartResource();
restartResource.Id = (string)row[0];
// Determine the resource type and set accordingly.
string resource = (string)row[2];
int attributes = (int)row[3];
UtilCompiler.WixRestartResourceAttributes type = (UtilCompiler.WixRestartResourceAttributes)(attributes & (int)UtilCompiler.WixRestartResourceAttributes.TypeMask);
switch (type)
{
case UtilCompiler.WixRestartResourceAttributes.Filename:
restartResource.Path = resource;
break;
case UtilCompiler.WixRestartResourceAttributes.ProcessName:
restartResource.ProcessName = resource;
break;
case UtilCompiler.WixRestartResourceAttributes.ServiceName:
restartResource.ServiceName = resource;
break;
default:
this.Core.OnMessage(WixWarnings.UnrepresentableColumnValue(row.SourceLineNumbers, table.Name, "Attributes", attributes));
break;
}
// Add to the appropriate Component or section element.
string componentId = (string)row[1];
if (!String.IsNullOrEmpty(componentId))
{
Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", componentId);
if (null != component)
{
component.AddChild(restartResource);
}
else
{
this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", componentId, "Component"));
}
}
else
{
this.Core.RootElement.AddChild(restartResource);
}
}
}
///
/// Decompile the FileShare table.
///
/// The table to decompile.
private void DecompileFileShareTable(Table table)
{
foreach (Row row in table.Rows)
{
Util.FileShare fileShare = new Util.FileShare();
fileShare.Id = (string)row[0];
fileShare.Name = (string)row[1];
if (null != row[3])
{
fileShare.Description = (string)row[3];
}
// the Directory_ column is set by the parent Component
// the User_ and Permissions columns are deprecated
Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]);
if (null != component)
{
component.AddChild(fileShare);
}
else
{
this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component"));
}
this.Core.IndexElement(row, fileShare);
}
}
///
/// Decompile the FileSharePermissions table.
///
/// The table to decompile.
private void DecompileFileSharePermissionsTable(Table table)
{
foreach (Row row in table.Rows)
{
Util.FileSharePermission fileSharePermission = new Util.FileSharePermission();
fileSharePermission.User = (string)row[1];
string[] specialPermissions = UtilConstants.FolderPermissions;
int permissions = (int)row[2];
for (int i = 0; i < 32; i++)
{
if (0 != ((permissions >> i) & 1))
{
string name = null;
if (16 > i && specialPermissions.Length > i)
{
name = specialPermissions[i];
}
else if (28 > i && UtilConstants.StandardPermissions.Length > (i - 16))
{
name = UtilConstants.StandardPermissions[i - 16];
}
else if (0 <= (i - 28) && UtilConstants.GenericPermissions.Length > (i - 28))
{
name = UtilConstants.GenericPermissions[i - 28];
}
if (null == name)
{
this.Core.OnMessage(WixWarnings.UnknownPermission(row.SourceLineNumbers, row.Table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), i));
}
else
{
switch (name)
{
case "ChangePermission":
fileSharePermission.ChangePermission = Util.YesNoType.yes;
break;
case "CreateChild":
fileSharePermission.CreateChild = Util.YesNoType.yes;
break;
case "CreateFile":
fileSharePermission.CreateFile = Util.YesNoType.yes;
break;
case "Delete":
fileSharePermission.Delete = Util.YesNoType.yes;
break;
case "DeleteChild":
fileSharePermission.DeleteChild = Util.YesNoType.yes;
break;
case "GenericAll":
fileSharePermission.GenericAll = Util.YesNoType.yes;
break;
case "GenericExecute":
fileSharePermission.GenericExecute = Util.YesNoType.yes;
break;
case "GenericRead":
fileSharePermission.GenericRead = Util.YesNoType.yes;
break;
case "GenericWrite":
fileSharePermission.GenericWrite = Util.YesNoType.yes;
break;
case "Read":
fileSharePermission.Read = Util.YesNoType.yes;
break;
case "ReadAttributes":
fileSharePermission.ReadAttributes = Util.YesNoType.yes;
break;
case "ReadExtendedAttributes":
fileSharePermission.ReadExtendedAttributes = Util.YesNoType.yes;
break;
case "ReadPermission":
fileSharePermission.ReadPermission = Util.YesNoType.yes;
break;
case "Synchronize":
fileSharePermission.Synchronize = Util.YesNoType.yes;
break;
case "TakeOwnership":
fileSharePermission.TakeOwnership = Util.YesNoType.yes;
break;
case "Traverse":
fileSharePermission.Traverse = Util.YesNoType.yes;
break;
case "WriteAttributes":
fileSharePermission.WriteAttributes = Util.YesNoType.yes;
break;
case "WriteExtendedAttributes":
fileSharePermission.WriteExtendedAttributes = Util.YesNoType.yes;
break;
default:
Debug.Fail(String.Format("Unknown permission '{0}'.", name));
break;
}
}
}
}
Util.FileShare fileShare = (Util.FileShare)this.Core.GetIndexedElement("FileShare", (string)row[0]);
if (null != fileShare)
{
fileShare.AddChild(fileSharePermission);
}
else
{
this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "FileShare_", (string)row[0], "FileShare"));
}
}
}
///
/// Decompile the Group table.
///
/// The table to decompile.
private void DecompileGroupTable(Table table)
{
foreach (Row row in table.Rows)
{
Util.Group group = new Util.Group();
group.Id = (string)row[0];
if (null != row[1])
{
this.Core.OnMessage(WixWarnings.UnrepresentableColumnValue(row.SourceLineNumbers, table.Name, "Component_", (string)row[1]));
}
group.Name = (string)row[2];
if (null != row[3])
{
group.Domain = (string)row[3];
}
this.Core.RootElement.AddChild(group);
}
}
///
/// Decompile the WixInternetShortcut table.
///
/// The table to decompile.
private void DecompileWixInternetShortcutTable(Table table)
{
foreach (Row row in table.Rows)
{
Util.InternetShortcut internetShortcut = new Util.InternetShortcut();
internetShortcut.Id = (string)row[0];
internetShortcut.Directory = (string)row[2];
// remove .lnk/.url extension because compiler extension adds it back for us
internetShortcut.Name = Path.ChangeExtension((string)row[3], null);
internetShortcut.Target = (string)row[4];
internetShortcut.IconFile = (string)row[6];
internetShortcut.IconIndex = (int)row[7];
UtilCompiler.InternetShortcutType shortcutType = (UtilCompiler.InternetShortcutType)row[5];
switch (shortcutType)
{
case UtilCompiler.InternetShortcutType.Link:
internetShortcut.Type = Util.InternetShortcut.TypeType.link;
break;
case UtilCompiler.InternetShortcutType.Url:
internetShortcut.Type = Util.InternetShortcut.TypeType.url;
break;
}
Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[1]);
if (null != component)
{
component.AddChild(internetShortcut);
}
else
{
this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[1], "Component"));
}
this.Core.IndexElement(row, internetShortcut);
}
}
///
/// Decompile the Perfmon table.
///
/// The table to decompile.
private void DecompilePerfmonTable(Table table)
{
foreach (Row row in table.Rows)
{
Util.PerfCounter perfCounter = new Util.PerfCounter();
perfCounter.Name = (string)row[2];
this.Core.IndexElement(row, perfCounter);
}
}
///
/// Decompile the PerfmonManifest table.
///
/// The table to decompile.
private void DecompilePerfmonManifestTable(Table table)
{
foreach (Row row in table.Rows)
{
Util.PerfCounterManifest perfCounterManifest = new Util.PerfCounterManifest();
perfCounterManifest.ResourceFileDirectory = (string)row[2];
this.Core.IndexElement(row, perfCounterManifest);
}
}
///
/// Decompile the EventManifest table.
///
/// The table to decompile.
private void DecompileEventManifestTable(Table table)
{
foreach (Row row in table.Rows)
{
Util.EventManifest eventManifest = new Util.EventManifest();
this.Core.IndexElement(row, eventManifest);
}
}
///
/// Decompile the SecureObjects table.
///
/// The table to decompile.
private void DecompileSecureObjectsTable(Table table)
{
foreach (Row row in table.Rows)
{
Util.PermissionEx permissionEx = new Util.PermissionEx();
string[] specialPermissions;
switch ((string)row[1])
{
case "CreateFolder":
specialPermissions = UtilConstants.FolderPermissions;
break;
case "File":
specialPermissions = UtilConstants.FilePermissions;
break;
case "Registry":
specialPermissions = UtilConstants.RegistryPermissions;
break;
case "ServiceInstall":
specialPermissions = UtilConstants.ServicePermissions;
break;
default:
this.Core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, row.Table.Name, row.Fields[1].Column.Name, row[1]));
return;
}
int permissionBits = (int)row[4];
for (int i = 0; i < 32; i++)
{
if (0 != ((permissionBits >> i) & 1))
{
string name = null;
if (16 > i && specialPermissions.Length > i)
{
name = specialPermissions[i];
}
else if (28 > i && UtilConstants.StandardPermissions.Length > (i - 16))
{
name = UtilConstants.StandardPermissions[i - 16];
}
else if (0 <= (i - 28) && UtilConstants.GenericPermissions.Length > (i - 28))
{
name = UtilConstants.GenericPermissions[i - 28];
}
if (null == name)
{
this.Core.OnMessage(WixWarnings.UnknownPermission(row.SourceLineNumbers, row.Table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), i));
}
else
{
switch (name)
{
case "Append":
permissionEx.Append = Util.YesNoType.yes;
break;
case "ChangePermission":
permissionEx.ChangePermission = Util.YesNoType.yes;
break;
case "CreateChild":
permissionEx.CreateChild = Util.YesNoType.yes;
break;
case "CreateFile":
permissionEx.CreateFile = Util.YesNoType.yes;
break;
case "CreateLink":
permissionEx.CreateLink = Util.YesNoType.yes;
break;
case "CreateSubkeys":
permissionEx.CreateSubkeys = Util.YesNoType.yes;
break;
case "Delete":
permissionEx.Delete = Util.YesNoType.yes;
break;
case "DeleteChild":
permissionEx.DeleteChild = Util.YesNoType.yes;
break;
case "EnumerateSubkeys":
permissionEx.EnumerateSubkeys = Util.YesNoType.yes;
break;
case "Execute":
permissionEx.Execute = Util.YesNoType.yes;
break;
case "GenericAll":
permissionEx.GenericAll = Util.YesNoType.yes;
break;
case "GenericExecute":
permissionEx.GenericExecute = Util.YesNoType.yes;
break;
case "GenericRead":
permissionEx.GenericRead = Util.YesNoType.yes;
break;
case "GenericWrite":
permissionEx.GenericWrite = Util.YesNoType.yes;
break;
case "Notify":
permissionEx.Notify = Util.YesNoType.yes;
break;
case "Read":
permissionEx.Read = Util.YesNoType.yes;
break;
case "ReadAttributes":
permissionEx.ReadAttributes = Util.YesNoType.yes;
break;
case "ReadExtendedAttributes":
permissionEx.ReadExtendedAttributes = Util.YesNoType.yes;
break;
case "ReadPermission":
permissionEx.ReadPermission = Util.YesNoType.yes;
break;
case "ServiceChangeConfig":
permissionEx.ServiceChangeConfig = Util.YesNoType.yes;
break;
case "ServiceEnumerateDependents":
permissionEx.ServiceEnumerateDependents = Util.YesNoType.yes;
break;
case "ServiceInterrogate":
permissionEx.ServiceInterrogate = Util.YesNoType.yes;
break;
case "ServicePauseContinue":
permissionEx.ServicePauseContinue = Util.YesNoType.yes;
break;
case "ServiceQueryConfig":
permissionEx.ServiceQueryConfig = Util.YesNoType.yes;
break;
case "ServiceQueryStatus":
permissionEx.ServiceQueryStatus = Util.YesNoType.yes;
break;
case "ServiceStart":
permissionEx.ServiceStart = Util.YesNoType.yes;
break;
case "ServiceStop":
permissionEx.ServiceStop = Util.YesNoType.yes;
break;
case "ServiceUserDefinedControl":
permissionEx.ServiceUserDefinedControl = Util.YesNoType.yes;
break;
case "Synchronize":
permissionEx.Synchronize = Util.YesNoType.yes;
break;
case "TakeOwnership":
permissionEx.TakeOwnership = Util.YesNoType.yes;
break;
case "Traverse":
permissionEx.Traverse = Util.YesNoType.yes;
break;
case "Write":
permissionEx.Write = Util.YesNoType.yes;
break;
case "WriteAttributes":
permissionEx.WriteAttributes = Util.YesNoType.yes;
break;
case "WriteExtendedAttributes":
permissionEx.WriteExtendedAttributes = Util.YesNoType.yes;
break;
default:
throw new InvalidOperationException(String.Format("Unknown permission attribute '{0}'.", name));
}
}
}
}
if (null != row[2])
{
permissionEx.Domain = (string)row[2];
}
permissionEx.User = (string)row[3];
this.Core.IndexElement(row, permissionEx);
}
}
///
/// Decompile the ServiceConfig table.
///
/// The table to decompile.
private void DecompileServiceConfigTable(Table table)
{
foreach (Row row in table.Rows)
{
Util.ServiceConfig serviceConfig = new Util.ServiceConfig();
serviceConfig.ServiceName = (string)row[0];
switch ((string)row[3])
{
case "none":
serviceConfig.FirstFailureActionType = Util.ServiceConfig.FirstFailureActionTypeType.none;
break;
case "reboot":
serviceConfig.FirstFailureActionType = Util.ServiceConfig.FirstFailureActionTypeType.reboot;
break;
case "restart":
serviceConfig.FirstFailureActionType = Util.ServiceConfig.FirstFailureActionTypeType.restart;
break;
case "runCommand":
serviceConfig.FirstFailureActionType = Util.ServiceConfig.FirstFailureActionTypeType.runCommand;
break;
default:
this.Core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[3].Column.Name, row[3]));
break;
}
switch ((string)row[4])
{
case "none":
serviceConfig.SecondFailureActionType = Util.ServiceConfig.SecondFailureActionTypeType.none;
break;
case "reboot":
serviceConfig.SecondFailureActionType = Util.ServiceConfig.SecondFailureActionTypeType.reboot;
break;
case "restart":
serviceConfig.SecondFailureActionType = Util.ServiceConfig.SecondFailureActionTypeType.restart;
break;
case "runCommand":
serviceConfig.SecondFailureActionType = Util.ServiceConfig.SecondFailureActionTypeType.runCommand;
break;
default:
this.Core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[4].Column.Name, row[4]));
break;
}
switch ((string)row[5])
{
case "none":
serviceConfig.ThirdFailureActionType = Util.ServiceConfig.ThirdFailureActionTypeType.none;
break;
case "reboot":
serviceConfig.ThirdFailureActionType = Util.ServiceConfig.ThirdFailureActionTypeType.reboot;
break;
case "restart":
serviceConfig.ThirdFailureActionType = Util.ServiceConfig.ThirdFailureActionTypeType.restart;
break;
case "runCommand":
serviceConfig.ThirdFailureActionType = Util.ServiceConfig.ThirdFailureActionTypeType.runCommand;
break;
default:
this.Core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[5].Column.Name, row[5]));
break;
}
if (null != row[6])
{
serviceConfig.ResetPeriodInDays = (int)row[6];
}
if (null != row[7])
{
serviceConfig.RestartServiceDelayInSeconds = (int)row[7];
}
if (null != row[8])
{
serviceConfig.ProgramCommandLine = (string)row[8];
}
if (null != row[9])
{
serviceConfig.RebootMessage = (string)row[9];
}
this.Core.IndexElement(row, serviceConfig);
}
}
///
/// Decompile the User table.
///
/// The table to decompile.
private void DecompileUserTable(Table table)
{
foreach (Row row in table.Rows)
{
Util.User user = new Util.User();
user.Id = (string)row[0];
user.Name = (string)row[2];
if (null != row[3])
{
user.Domain = (string)row[3];
}
if (null != row[4])
{
user.Password = (string)row[4];
}
if (null != row[5])
{
int attributes = (int)row[5];
if (UtilCompiler.UserDontExpirePasswrd == (attributes & UtilCompiler.UserDontExpirePasswrd))
{
user.PasswordNeverExpires = Util.YesNoType.yes;
}
if (UtilCompiler.UserPasswdCantChange == (attributes & UtilCompiler.UserPasswdCantChange))
{
user.CanNotChangePassword = Util.YesNoType.yes;
}
if (UtilCompiler.UserPasswdChangeReqdOnLogin == (attributes & UtilCompiler.UserPasswdChangeReqdOnLogin))
{
user.PasswordExpired = Util.YesNoType.yes;
}
if (UtilCompiler.UserDisableAccount == (attributes & UtilCompiler.UserDisableAccount))
{
user.Disabled = Util.YesNoType.yes;
}
if (UtilCompiler.UserFailIfExists == (attributes & UtilCompiler.UserFailIfExists))
{
user.FailIfExists = Util.YesNoType.yes;
}
if (UtilCompiler.UserUpdateIfExists == (attributes & UtilCompiler.UserUpdateIfExists))
{
user.UpdateIfExists = Util.YesNoType.yes;
}
if (UtilCompiler.UserLogonAsService == (attributes & UtilCompiler.UserLogonAsService))
{
user.LogonAsService = Util.YesNoType.yes;
}
if (UtilCompiler.UserDontRemoveOnUninstall == (attributes & UtilCompiler.UserDontRemoveOnUninstall))
{
user.RemoveOnUninstall = Util.YesNoType.no;
}
if (UtilCompiler.UserDontCreateUser == (attributes & UtilCompiler.UserDontCreateUser))
{
user.CreateUser = Util.YesNoType.no;
}
if (UtilCompiler.UserNonVital == (attributes & UtilCompiler.UserNonVital))
{
user.Vital = Util.YesNoType.no;
}
}
if (null != row[1])
{
Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[1]);
if (null != component)
{
component.AddChild(user);
}
else
{
this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[1], "Component"));
}
}
else
{
this.Core.RootElement.AddChild(user);
}
this.Core.IndexElement(row, user);
}
}
///
/// Decompile the UserGroup table.
///
/// The table to decompile.
private void DecompileUserGroupTable(Table table)
{
foreach (Row row in table.Rows)
{
Util.User user = (Util.User)this.Core.GetIndexedElement("User", (string)row[0]);
if (null != user)
{
Util.GroupRef groupRef = new Util.GroupRef();
groupRef.Id = (string)row[1];
user.AddChild(groupRef);
}
else
{
this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Group_", (string)row[0], "Group"));
}
}
}
///
/// Decompile the XmlConfig table.
///
/// The table to decompile.
private void DecompileXmlConfigTable(Table table)
{
foreach (Row row in table.Rows)
{
Util.XmlConfig xmlConfig = new Util.XmlConfig();
xmlConfig.Id = (string)row[0];
xmlConfig.File = (string)row[1];
xmlConfig.ElementPath = (string)row[2];
if (null != row[3])
{
xmlConfig.VerifyPath = (string)row[3];
}
if (null != row[4])
{
xmlConfig.Name = (string)row[4];
}
if (null != row[5])
{
xmlConfig.Value = (string)row[5];
}
int flags = (int)row[6];
if (0x1 == (flags & 0x1))
{
xmlConfig.Node = Util.XmlConfig.NodeType.element;
}
else if (0x2 == (flags & 0x2))
{
xmlConfig.Node = Util.XmlConfig.NodeType.value;
}
else if (0x4 == (flags & 0x4))
{
xmlConfig.Node = Util.XmlConfig.NodeType.document;
}
if (0x10 == (flags & 0x10))
{
xmlConfig.Action = Util.XmlConfig.ActionType.create;
}
else if (0x20 == (flags & 0x20))
{
xmlConfig.Action = Util.XmlConfig.ActionType.delete;
}
if (0x100 == (flags & 0x100))
{
xmlConfig.On = Util.XmlConfig.OnType.install;
}
else if (0x200 == (flags & 0x200))
{
xmlConfig.On = Util.XmlConfig.OnType.uninstall;
}
if (0x00001000 == (flags & 0x00001000))
{
xmlConfig.PreserveModifiedDate = Util.YesNoType.yes;
}
if (null != row[8])
{
xmlConfig.Sequence = (int)row[8];
}
this.Core.IndexElement(row, xmlConfig);
}
}
///
/// Finalize the Perfmon table.
///
/// The collection of all tables.
///
/// Since the PerfCounter element nests under a File element, but
/// the Perfmon table does not have a foreign key relationship with
/// the File table (instead it has a formatted string that usually
/// refers to a file row - but doesn't have to), the nesting must
/// be inferred during finalization.
///
private void FinalizePerfmonTable(TableIndexedCollection tables)
{
Table perfmonTable = tables["Perfmon"];
if (null != perfmonTable)
{
foreach (Row row in perfmonTable.Rows)
{
string formattedFile = (string)row[1];
Util.PerfCounter perfCounter = (Util.PerfCounter)this.Core.GetIndexedElement(row);
// try to "de-format" the File column's value to determine the proper parent File element
if ((formattedFile.StartsWith("[#", StringComparison.Ordinal) || formattedFile.StartsWith("[!", StringComparison.Ordinal))
&& formattedFile.EndsWith("]", StringComparison.Ordinal))
{
string fileId = formattedFile.Substring(2, formattedFile.Length - 3);
Wix.File file = (Wix.File)this.Core.GetIndexedElement("File", fileId);
if (null != file)
{
file.AddChild(perfCounter);
}
else
{
this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, perfmonTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "File", formattedFile, "File"));
}
}
else
{
this.Core.OnMessage(UtilErrors.IllegalFileValueInPerfmonOrManifest(formattedFile, "Perfmon"));
}
}
}
}
///
/// Finalize the PerfmonManifest table.
///
/// The collection of all tables.
private void FinalizePerfmonManifestTable(TableIndexedCollection tables)
{
Table perfmonManifestTable = tables["PerfmonManifest"];
if (null != perfmonManifestTable)
{
foreach (Row row in perfmonManifestTable.Rows)
{
string formattedFile = (string)row[1];
Util.PerfCounterManifest perfCounterManifest = (Util.PerfCounterManifest)this.Core.GetIndexedElement(row);
// try to "de-format" the File column's value to determine the proper parent File element
if ((formattedFile.StartsWith("[#", StringComparison.Ordinal) || formattedFile.StartsWith("[!", StringComparison.Ordinal))
&& formattedFile.EndsWith("]", StringComparison.Ordinal))
{
string fileId = formattedFile.Substring(2, formattedFile.Length - 3);
Wix.File file = (Wix.File)this.Core.GetIndexedElement("File", fileId);
if (null != file)
{
file.AddChild(perfCounterManifest);
}
else
{
this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, perfCounterManifest.ResourceFileDirectory, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "File", formattedFile, "File"));
}
}
else
{
this.Core.OnMessage(UtilErrors.IllegalFileValueInPerfmonOrManifest(formattedFile, "PerfmonManifest"));
}
}
}
}
///
/// Finalize the SecureObjects table.
///
/// The collection of all tables.
///
/// Nests the PermissionEx elements below their parent elements. There are no declared foreign
/// keys for the parents of the SecureObjects table.
///
private void FinalizeSecureObjectsTable(TableIndexedCollection tables)
{
Table createFolderTable = tables["CreateFolder"];
Table secureObjectsTable = tables["SecureObjects"];
Hashtable createFolders = new Hashtable();
// index the CreateFolder table because the foreign key to this table from the
// LockPermissions table is only part of the primary key of this table
if (null != createFolderTable)
{
foreach (Row row in createFolderTable.Rows)
{
Wix.CreateFolder createFolder = (Wix.CreateFolder)this.Core.GetIndexedElement(row);
string directoryId = (string)row[0];
if (!createFolders.Contains(directoryId))
{
createFolders.Add(directoryId, new ArrayList());
}
((ArrayList)createFolders[directoryId]).Add(createFolder);
}
}
if (null != secureObjectsTable)
{
foreach (Row row in secureObjectsTable.Rows)
{
string id = (string)row[0];
string table = (string)row[1];
Util.PermissionEx permissionEx = (Util.PermissionEx)this.Core.GetIndexedElement(row);
if ("CreateFolder" == table)
{
ArrayList createFolderElements = (ArrayList)createFolders[id];
if (null != createFolderElements)
{
foreach (Wix.CreateFolder createFolder in createFolderElements)
{
createFolder.AddChild(permissionEx);
}
}
else
{
this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, "SecureObjects", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "LockObject", id, table));
}
}
else
{
Wix.IParentElement parentElement = (Wix.IParentElement)this.Core.GetIndexedElement(table, id);
if (null != parentElement)
{
parentElement.AddChild(permissionEx);
}
else
{
this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, "SecureObjects", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "LockObject", id, table));
}
}
}
}
}
///
/// Finalize the ServiceConfig table.
///
/// The collection of all tables.
///
/// Since there is no foreign key from the ServiceName column to the
/// ServiceInstall table, this relationship must be handled late.
///
private void FinalizeServiceConfigTable(TableIndexedCollection tables)
{
Table serviceConfigTable = tables["ServiceConfig"];
Table serviceInstallTable = tables["ServiceInstall"];
Hashtable serviceInstalls = new Hashtable();
// index the ServiceInstall table because the foreign key used by the ServiceConfig
// table is actually the ServiceInstall.Name, not the ServiceInstall.ServiceInstall
// this is unfortunate because the service Name is not guaranteed to be unique, so
// decompiler must assume there could be multiple matches and add the ServiceConfig to each
// TODO: the Component column information should be taken into acount to accurately identify
// the correct column to use
if (null != serviceInstallTable)
{
foreach (Row row in serviceInstallTable.Rows)
{
string name = (string)row[1];
Wix.ServiceInstall serviceInstall = (Wix.ServiceInstall)this.Core.GetIndexedElement(row);
if (!serviceInstalls.Contains(name))
{
serviceInstalls.Add(name, new ArrayList());
}
((ArrayList)serviceInstalls[name]).Add(serviceInstall);
}
}
if (null != serviceConfigTable)
{
foreach (Row row in serviceConfigTable.Rows)
{
Util.ServiceConfig serviceConfig = (Util.ServiceConfig)this.Core.GetIndexedElement(row);
if (0 == (int)row[2])
{
Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[1]);
if (null != component)
{
component.AddChild(serviceConfig);
}
else
{
this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, serviceConfigTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[1], "Component"));
}
}
else
{
ArrayList serviceInstallElements = (ArrayList)serviceInstalls[row[0]];
if (null != serviceInstallElements)
{
foreach (Wix.ServiceInstall serviceInstall in serviceInstallElements)
{
serviceInstall.AddChild(serviceConfig);
}
}
else
{
this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, serviceConfigTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "ServiceName", (string)row[0], "ServiceInstall"));
}
}
}
}
}
///
/// Finalize the XmlConfig table.
///
/// Collection of all tables.
private void FinalizeXmlConfigTable(TableIndexedCollection tables)
{
Table xmlConfigTable = tables["XmlConfig"];
if (null != xmlConfigTable)
{
foreach (Row row in xmlConfigTable.Rows)
{
Util.XmlConfig xmlConfig = (Util.XmlConfig)this.Core.GetIndexedElement(row);
if (null == row[6] || 0 == (int)row[6])
{
Util.XmlConfig parentXmlConfig = (Util.XmlConfig)this.Core.GetIndexedElement("XmlConfig", (string)row[2]);
if (null != parentXmlConfig)
{
parentXmlConfig.AddChild(xmlConfig);
}
else
{
this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, xmlConfigTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "ElementPath", (string)row[2], "XmlConfig"));
}
}
else
{
Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[7]);
if (null != component)
{
component.AddChild(xmlConfig);
}
else
{
this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, xmlConfigTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[7], "Component"));
}
}
}
}
}
///
/// Finalize the XmlFile table.
///
/// The collection of all tables.
///
/// Some of the XmlFile table rows are compiler generated from util:EventManifest node
/// These rows should not be appended to component.
///
private void FinalizeXmlFileTable(TableIndexedCollection tables)
{
Table xmlFileTable = tables["XmlFile"];
Table eventManifestTable = tables["EventManifest"];
if (null != xmlFileTable)
{
foreach (Row row in xmlFileTable.Rows)
{
bool bManifestGenerated = false;
string xmlFileConfigId = (string)row[0];
if (null != eventManifestTable)
{
foreach (Row emrow in eventManifestTable.Rows)
{
string formattedFile = (string)emrow[1];
if ((formattedFile.StartsWith("[#", StringComparison.Ordinal) || formattedFile.StartsWith("[!", StringComparison.Ordinal))
&& formattedFile.EndsWith("]", StringComparison.Ordinal))
{
string fileId = formattedFile.Substring(2, formattedFile.Length - 3);
if (String.Equals(String.Concat("Config_", fileId, "ResourceFile"), xmlFileConfigId))
{
Util.EventManifest eventManifest = (Util.EventManifest)this.Core.GetIndexedElement(emrow);
if (null != eventManifest)
{
eventManifest.ResourceFile = (string)row[4];
}
bManifestGenerated = true;
}
else if (String.Equals(String.Concat("Config_", fileId, "MessageFile"), xmlFileConfigId))
{
Util.EventManifest eventManifest = (Util.EventManifest)this.Core.GetIndexedElement(emrow);
if (null != eventManifest)
{
eventManifest.MessageFile = (string)row[4];
}
bManifestGenerated = true;
}
}
}
}
if (true == bManifestGenerated)
continue;
Util.XmlFile xmlFile = new Util.XmlFile();
xmlFile.Id = (string)row[0];
xmlFile.File = (string)row[1];
xmlFile.ElementPath = (string)row[2];
if (null != row[3])
{
xmlFile.Name = (string)row[3];
}
if (null != row[4])
{
xmlFile.Value = (string)row[4];
}
int flags = (int)row[5];
if (0x1 == (flags & 0x1) && 0x2 == (flags & 0x2))
{
this.Core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, xmlFileTable.Name, row.Fields[5].Column.Name, row[5]));
}
else if (0x1 == (flags & 0x1))
{
xmlFile.Action = Util.XmlFile.ActionType.createElement;
}
else if (0x2 == (flags & 0x2))
{
xmlFile.Action = Util.XmlFile.ActionType.deleteValue;
}
else
{
xmlFile.Action = Util.XmlFile.ActionType.setValue;
}
if (0x100 == (flags & 0x100))
{
xmlFile.SelectionLanguage = Util.XmlFile.SelectionLanguageType.XPath;
}
if (0x00001000 == (flags & 0x00001000))
{
xmlFile.PreserveModifiedDate = Util.YesNoType.yes;
}
if (0x00010000 == (flags & 0x00010000))
{
xmlFile.Permanent = Util.YesNoType.yes;
}
if (null != row[7])
{
xmlFile.Sequence = (int)row[7];
}
Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[6]);
if (null != component)
{
component.AddChild(xmlFile);
}
else
{
this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, xmlFileTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[6], "Component"));
}
}
}
}
///
/// Finalize the eventManifest table.
/// This function must be called after FinalizeXmlFileTable
///
/// The collection of all tables.
private void FinalizeEventManifestTable(TableIndexedCollection tables)
{
Table eventManifestTable = tables["EventManifest"];
if (null != eventManifestTable)
{
foreach (Row row in eventManifestTable.Rows)
{
string formattedFile = (string)row[1];
Util.EventManifest eventManifest = (Util.EventManifest)this.Core.GetIndexedElement(row);
// try to "de-format" the File column's value to determine the proper parent File element
if ((formattedFile.StartsWith("[#", StringComparison.Ordinal) || formattedFile.StartsWith("[!", StringComparison.Ordinal))
&& formattedFile.EndsWith("]", StringComparison.Ordinal))
{
string fileId = formattedFile.Substring(2, formattedFile.Length - 3);
Wix.File file = (Wix.File)this.Core.GetIndexedElement("File", fileId);
if (null != file)
{
file.AddChild(eventManifest);
}
}
else
{
this.Core.OnMessage(UtilErrors.IllegalFileValueInPerfmonOrManifest(formattedFile, "EventManifest"));
}
}
}
}
}
#endif
}