From 188952d84f5789128ddd32e7adf09e60899af43a Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Tue, 27 Sep 2022 01:47:25 -0700 Subject: Implement transform decompiling and use it in patch filter tests --- .../Data/IWindowsInstallerDecompileResult.cs | 6 + .../burn/WixToolsetTest.BurnE2E/SlipstreamTests.cs | 2 +- .../Bind/CreatePatchTransformsCommand.cs | 2 +- .../CommandLine/DecompilerSubcommand.cs | 51 +++- .../CommandLine/TransformSubcommand.cs | 2 +- .../Unbind/UnbindDatabaseCommand.cs | 42 +-- .../Unbind/UnbindTransformCommand.cs | 314 ++++++++++++--------- .../WindowsInstallerDecompileResult.cs | 3 + .../WindowsInstallerDecompiler.cs | 37 ++- .../WixToolsetTest.CoreIntegration/PatchFixture.cs | 86 +++++- .../PatchFamilyFileFilter/.data/Av1.0.0.txt | 1 + .../PatchFamilyFileFilter/.data/Av1.0.1.txt | 1 + .../PatchFamilyFileFilter/.data/Bv1.0.0.txt | 1 + .../PatchFamilyFileFilter/.data/Bv1.0.1.txt | 1 + .../TestData/PatchFamilyFileFilter/Package.wxs | 30 ++ .../TestData/PatchFamilyFileFilter/Patch.wxs | 16 ++ .../TestData/PatchFamilyFilter/.data/Av1.0.0.txt | 1 - .../TestData/PatchFamilyFilter/.data/Av1.0.1.txt | 1 - .../TestData/PatchFamilyFilter/.data/Bv1.0.0.txt | 1 - .../TestData/PatchFamilyFilter/.data/Bv1.0.1.txt | 1 - .../TestData/PatchFamilyFilter/Package.wxs | 28 -- .../TestData/PatchFamilyFilter/Patch.wxs | 16 -- .../TestData/PatchFamilyRegistryFilter/Patch.wxs | 16 ++ 23 files changed, 436 insertions(+), 223 deletions(-) create mode 100644 src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFileFilter/.data/Av1.0.0.txt create mode 100644 src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFileFilter/.data/Av1.0.1.txt create mode 100644 src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFileFilter/.data/Bv1.0.0.txt create mode 100644 src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFileFilter/.data/Bv1.0.1.txt create mode 100644 src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFileFilter/Package.wxs create mode 100644 src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFileFilter/Patch.wxs delete mode 100644 src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFilter/.data/Av1.0.0.txt delete mode 100644 src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFilter/.data/Av1.0.1.txt delete mode 100644 src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFilter/.data/Bv1.0.0.txt delete mode 100644 src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFilter/.data/Bv1.0.1.txt delete mode 100644 src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFilter/Package.wxs delete mode 100644 src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFilter/Patch.wxs create mode 100644 src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyRegistryFilter/Patch.wxs diff --git a/src/api/wix/WixToolset.Extensibility/Data/IWindowsInstallerDecompileResult.cs b/src/api/wix/WixToolset.Extensibility/Data/IWindowsInstallerDecompileResult.cs index 724dd7fc..4e528bee 100644 --- a/src/api/wix/WixToolset.Extensibility/Data/IWindowsInstallerDecompileResult.cs +++ b/src/api/wix/WixToolset.Extensibility/Data/IWindowsInstallerDecompileResult.cs @@ -5,12 +5,18 @@ namespace WixToolset.Extensibility.Data using System.Collections.Generic; using System.Xml.Linq; using WixToolset.Data; + using WixToolset.Data.WindowsInstaller; /// /// The result from decompiling a Windows Installer database. /// public interface IWindowsInstallerDecompileResult { + /// + /// Decompiled WindowsInstallerData. + /// + WindowsInstallerData Data { get; set; } + /// /// Decompiled document. /// diff --git a/src/test/burn/WixToolsetTest.BurnE2E/SlipstreamTests.cs b/src/test/burn/WixToolsetTest.BurnE2E/SlipstreamTests.cs index 9ef100ce..aa005cb1 100644 --- a/src/test/burn/WixToolsetTest.BurnE2E/SlipstreamTests.cs +++ b/src/test/burn/WixToolsetTest.BurnE2E/SlipstreamTests.cs @@ -266,7 +266,7 @@ namespace WixToolsetTest.BurnE2E packageBv1.VerifyTestRegistryRootDeleted(); } - [RuntimeFact(Skip = "https://github.com/wixtoolset/issues/issues/6402")] + [RuntimeFact] public void CanAutomaticallyPredetermineSlipstreamPatchesAtBuildTime() { var testRegistryValueA = "PackageA"; diff --git a/src/wix/WixToolset.Core.WindowsInstaller/Bind/CreatePatchTransformsCommand.cs b/src/wix/WixToolset.Core.WindowsInstaller/Bind/CreatePatchTransformsCommand.cs index 17583e96..5cdafe7e 100644 --- a/src/wix/WixToolset.Core.WindowsInstaller/Bind/CreatePatchTransformsCommand.cs +++ b/src/wix/WixToolset.Core.WindowsInstaller/Bind/CreatePatchTransformsCommand.cs @@ -94,7 +94,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind var exportBasePath = Path.Combine(this.IntermediateFolder, stageFolder); var extractFilesFolder = Path.Combine(exportBasePath, "File"); - var command = new UnbindDatabaseCommand(this.Messaging, this.BackendHelper, this.PathResolver, path, OutputType.Product, exportBasePath, extractFilesFolder, this.IntermediateFolder, enableDemodularization: false, skipSummaryInfo: false); + var command = new UnbindDatabaseCommand(this.Messaging, this.BackendHelper, this.PathResolver, path, null, OutputType.Product, exportBasePath, extractFilesFolder, this.IntermediateFolder, enableDemodularization: false, skipSummaryInfo: false); data = command.Execute(); } diff --git a/src/wix/WixToolset.Core.WindowsInstaller/CommandLine/DecompilerSubcommand.cs b/src/wix/WixToolset.Core.WindowsInstaller/CommandLine/DecompilerSubcommand.cs index b46df22a..f59d83b6 100644 --- a/src/wix/WixToolset.Core.WindowsInstaller/CommandLine/DecompilerSubcommand.cs +++ b/src/wix/WixToolset.Core.WindowsInstaller/CommandLine/DecompilerSubcommand.cs @@ -34,6 +34,8 @@ namespace WixToolset.Core.WindowsInstaller.CommandLine private string ExportBasePath { get; set; } + private bool SaveAsData { get; set; } + private bool SuppressCustomTables { get; set; } private bool SuppressDroppingEmptyTables { get; set; } @@ -47,13 +49,14 @@ namespace WixToolset.Core.WindowsInstaller.CommandLine return new CommandLineHelp("Converts a Windows Installer database back into source code.", "msi decompile [options] inputfile", new[] { new CommandLineHelpSwitch("-cub", "Optional path to a custom validation .CUBe file."), + new CommandLineHelpSwitch("-data", "Save output as data instead of as a source file."), new CommandLineHelpSwitch("-sct", "Suppress decompiling custom tables."), new CommandLineHelpSwitch("-sdet", "Suppress dropping empty tables."), new CommandLineHelpSwitch("-sras", "Suppress relative action sequencing."), new CommandLineHelpSwitch("-sui", "Suppress decompiling UI tables."), new CommandLineHelpSwitch("-type", "Optional specify the input file type: msi or msm. If not specified, type will be inferred by file extension."), new CommandLineHelpSwitch("-intermediateFolder", "Optional working folder. If not specified %TMP% will be used."), - new CommandLineHelpSwitch("-out", "-o", "Path to output the decompiled .wxs file. If not specified, outputs next to inputfile"), + new CommandLineHelpSwitch("-out", "-o", "Path to output the decompiled output file. If not specified, outputs next to inputfile"), new CommandLineHelpSwitch("-x", "Folder to export embedded binaries and icons to."), }); } @@ -77,7 +80,9 @@ namespace WixToolset.Core.WindowsInstaller.CommandLine if (String.IsNullOrEmpty(this.OutputPath)) { - this.OutputPath = Path.ChangeExtension(this.InputPath, ".wxs"); + var defaultExtension = this.CalculateExtensionFromDecompileType(decompileType); + + this.OutputPath = Path.ChangeExtension(this.InputPath, defaultExtension); } var extensionManager = this.ServiceProvider.GetService(); @@ -92,7 +97,7 @@ namespace WixToolset.Core.WindowsInstaller.CommandLine context.SymbolDefinitionCreator = creator; context.OutputPath = this.OutputPath; - context.ExtractFolder = this.ExportBasePath ?? this.IntermediateFolder; + context.ExtractFolder = this.ExportBasePath; context.SuppressCustomTables = this.SuppressCustomTables; context.SuppressDroppingEmptyTables = this.SuppressDroppingEmptyTables; context.SuppressRelativeActionSequencing = this.SuppressRelativeActionSequencing; @@ -106,7 +111,17 @@ namespace WixToolset.Core.WindowsInstaller.CommandLine if (!this.Messaging.EncounteredError) { Directory.CreateDirectory(Path.GetDirectoryName(Path.GetFullPath(context.OutputPath))); - result.Document.Save(context.OutputPath, SaveOptions.OmitDuplicateNamespaces); + if (this.SaveAsData || result.Document == null) + { + using (var output = WixOutput.Create(context.OutputPath)) + { + result.Data.Save(output); + } + } + else + { + result.Document.Save(context.OutputPath, SaveOptions.OmitDuplicateNamespaces); + } } } catch (WixException e) @@ -129,6 +144,10 @@ namespace WixToolset.Core.WindowsInstaller.CommandLine this.IntermediateFolder = parser.GetNextArgumentAsDirectoryOrError(argument); return true; + case "data": + this.SaveAsData = true; + return true; + case "o": case "out": this.OutputPath = parser.GetNextArgumentAsFilePathOrError(argument, "output file"); @@ -197,9 +216,33 @@ namespace WixToolset.Core.WindowsInstaller.CommandLine case ".msm": decompileType = OutputType.Module; break; + + case "transform": + case "mst": + case ".mst": + decompileType = OutputType.Transform; + break; } return decompileType != OutputType.Unknown; } + + private string CalculateExtensionFromDecompileType(OutputType decompileType) + { + switch (decompileType) + { + case OutputType.Product: + return this.SaveAsData ? ".wixmsi" : ".wxs"; + + case OutputType.Module: + return this.SaveAsData ? ".wixmsm" : ".wxs"; + + case OutputType.Transform: + return ".wixmst"; + + default: + return this.SaveAsData ? ".wixdata" : ".wxs"; + } + } } } diff --git a/src/wix/WixToolset.Core.WindowsInstaller/CommandLine/TransformSubcommand.cs b/src/wix/WixToolset.Core.WindowsInstaller/CommandLine/TransformSubcommand.cs index 68cb6554..e37267bb 100644 --- a/src/wix/WixToolset.Core.WindowsInstaller/CommandLine/TransformSubcommand.cs +++ b/src/wix/WixToolset.Core.WindowsInstaller/CommandLine/TransformSubcommand.cs @@ -379,7 +379,7 @@ namespace WixToolset.Core.WindowsInstaller.CommandLine { if (!DataLoader.TryLoadWindowsInstallerData(path, out var data)) { - var unbindCommand = new UnbindDatabaseCommand(this.Messaging, this.BackendHelper, this.PathResolver, path, OutputType.Product, this.ExportBasePath, null, this.IntermediateFolder, enableDemodularization: false, skipSummaryInfo: false); + var unbindCommand = new UnbindDatabaseCommand(this.Messaging, this.BackendHelper, this.PathResolver, path, null, OutputType.Product, this.ExportBasePath, null, this.IntermediateFolder, enableDemodularization: false, skipSummaryInfo: false); data = unbindCommand.Execute(); } diff --git a/src/wix/WixToolset.Core.WindowsInstaller/Unbind/UnbindDatabaseCommand.cs b/src/wix/WixToolset.Core.WindowsInstaller/Unbind/UnbindDatabaseCommand.cs index 5eeb67c8..7f6537e5 100644 --- a/src/wix/WixToolset.Core.WindowsInstaller/Unbind/UnbindDatabaseCommand.cs +++ b/src/wix/WixToolset.Core.WindowsInstaller/Unbind/UnbindDatabaseCommand.cs @@ -21,12 +21,13 @@ namespace WixToolset.Core.WindowsInstaller.Unbind { private static readonly Regex Modularization = 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}"); - public UnbindDatabaseCommand(IMessaging messaging, IBackendHelper backendHelper, IPathResolver pathResolver, string databasePath, OutputType outputType, string exportBasePath, string extractFilesFolder, string intermediateFolder, bool enableDemodularization, bool skipSummaryInfo) + public UnbindDatabaseCommand(IMessaging messaging, IBackendHelper backendHelper, IPathResolver pathResolver, string databasePath, Database database, OutputType outputType, string exportBasePath, string extractFilesFolder, string intermediateFolder, bool enableDemodularization, bool skipSummaryInfo) { this.Messaging = messaging; this.BackendHelper = backendHelper; this.PathResolver = pathResolver; this.DatabasePath = databasePath; + this.Database = database; this.OutputType = outputType; this.ExportBasePath = exportBasePath; this.ExtractFilesFolder = extractFilesFolder; @@ -45,21 +46,21 @@ namespace WixToolset.Core.WindowsInstaller.Unbind private Database Database { get; set; } - public string DatabasePath { get; } + private string DatabasePath { get; } - public OutputType OutputType { get; } + private OutputType OutputType { get; } - public string ExportBasePath { get; } + private string ExportBasePath { get; } - public string ExtractFilesFolder { get; } + private string ExtractFilesFolder { get; } - public string IntermediateFolder { get; } + private string IntermediateFolder { get; } - public bool EnableDemodularization { get; } + private bool EnableDemodularization { get; } - public bool SkipSummaryInfo { get; } + private bool SkipSummaryInfo { get; } - public TableDefinitionCollection TableDefinitions { get; } + private TableDefinitionCollection TableDefinitions { get; } public bool AdminImage { get; private set; } @@ -77,22 +78,24 @@ namespace WixToolset.Core.WindowsInstaller.Unbind Type = this.OutputType }; + Database database = null; try { - using (var database = new Database(this.DatabasePath, OpenDatabase.ReadOnly)) + if (this.Database == null) { + database = new Database(this.DatabasePath, OpenDatabase.ReadOnly); this.Database = database; + } - Directory.CreateDirectory(this.IntermediateFolder); + Directory.CreateDirectory(this.IntermediateFolder); - data.Codepage = this.GetCodePage(); + data.Codepage = this.GetCodePage(); - var modularizationGuid = this.ProcessTables(data, exportedFiles); + var modularizationGuid = this.ProcessTables(data, exportedFiles); - var summaryInfo = this.ProcessSummaryInfo(data, modularizationGuid); + var summaryInfo = this.ProcessSummaryInfo(data, modularizationGuid); - this.UpdateUnrealFileColumns(this.DatabasePath, data, summaryInfo, exportedFiles); - } + this.UpdateUnrealFileColumns(this.DatabasePath, data, summaryInfo, exportedFiles); } catch (Win32Exception e) { @@ -103,6 +106,10 @@ namespace WixToolset.Core.WindowsInstaller.Unbind throw; } + finally + { + database?.Dispose(); + } this.AdminImage = adminImage; this.Data = data; @@ -542,9 +549,8 @@ namespace WixToolset.Core.WindowsInstaller.Unbind source = Path.Combine(this.ExtractFilesFolder, fileRow.File); } } - else + else if (componentDirectoryIndex.TryGetValue(fileRow.Component, out var directoryId)) // this can happen when unbinding an invalid MSI file or MST file with select table modifications. { - var directoryId = componentDirectoryIndex[fileRow.Component]; var relativeFileLayoutPath = this.PathResolver.GetFileSourcePath(directories, directoryId, fileRow.FileName, compressed: false, useLongName: summaryInformation.LongFilenames); source = Path.Combine(databaseFolder, relativeFileLayoutPath); diff --git a/src/wix/WixToolset.Core.WindowsInstaller/Unbind/UnbindTransformCommand.cs b/src/wix/WixToolset.Core.WindowsInstaller/Unbind/UnbindTransformCommand.cs index bce60e40..f2567ebb 100644 --- a/src/wix/WixToolset.Core.WindowsInstaller/Unbind/UnbindTransformCommand.cs +++ b/src/wix/WixToolset.Core.WindowsInstaller/Unbind/UnbindTransformCommand.cs @@ -1,11 +1,8 @@ // 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. -#if TODO_KEEP_FOR_PATCH_UNBINDING_CONSIDERATION_IN_FUTURE - namespace WixToolset.Core.WindowsInstaller.Unbind { using System; - using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Globalization; @@ -19,10 +16,11 @@ namespace WixToolset.Core.WindowsInstaller.Unbind internal class UnbindTransformCommand { - public UnbindTransformCommand(IMessaging messaging, IBackendHelper backendHelper, FileSystemManager fileSystemManager, string transformFile, string exportBasePath, string intermediateFolder) + public UnbindTransformCommand(IMessaging messaging, IBackendHelper backendHelper, IPathResolver pathResolver, FileSystemManager fileSystemManager, string transformFile, string exportBasePath, string intermediateFolder) { this.Messaging = messaging; this.BackendHelper = backendHelper; + this.PathResolver = pathResolver; this.FileSystemManager = fileSystemManager; this.TransformFile = transformFile; this.ExportBasePath = exportBasePath; @@ -35,6 +33,8 @@ namespace WixToolset.Core.WindowsInstaller.Unbind private IBackendHelper BackendHelper { get; } + private IPathResolver PathResolver { get; } + private FileSystemManager FileSystemManager { get; } private string TransformFile { get; } @@ -49,8 +49,10 @@ namespace WixToolset.Core.WindowsInstaller.Unbind public WindowsInstallerData Execute() { - var transform = new WindowsInstallerData(new SourceLineNumber(this.TransformFile)); - transform.Type = OutputType.Transform; + var transform = new WindowsInstallerData(new SourceLineNumber(this.TransformFile)) + { + Type = OutputType.Transform + }; // get the summary information table using (var summaryInformation = new SummaryInformation(this.TransformFile)) @@ -71,181 +73,215 @@ namespace WixToolset.Core.WindowsInstaller.Unbind } // create a schema msi which hopefully matches the table schemas in the transform - var schemaOutput = new WindowsInstallerData(null); + var schemaDatabasePath = Path.Combine(this.IntermediateFolder, "schema.msi"); + var schemaData = this.CreateSchemaData(schemaDatabasePath); + + // Bind the schema msi. + this.GenerateDatabase(schemaData); + + var transformViewTable = this.OpenTransformViewForAddedAndModifiedRows(schemaDatabasePath); + + var addedRows = this.CreatePlaceholdersForModifiedRowsAndIndexAddedRows(schemaData, transformViewTable); + + // Re-bind the schema output with the placeholder rows over top the original schema database. + this.GenerateDatabase(schemaData); + + this.PopulateTransformFromView(schemaDatabasePath, transform, transformViewTable, addedRows); + + return transform; + } + + private WindowsInstallerData CreateSchemaData(string schemaDatabasePath) + { + var schemaData = new WindowsInstallerData(new SourceLineNumber(schemaDatabasePath)) + { + Type = OutputType.Product, + }; + foreach (var tableDefinition in this.TableDefinitions) { // skip unreal tables and the Patch table if (!tableDefinition.Unreal && "Patch" != tableDefinition.Name) { - schemaOutput.EnsureTable(tableDefinition); + schemaData.EnsureTable(tableDefinition); } } - var addedRows = new Dictionary(); - Table transformViewTable; - - // Bind the schema msi. - var msiDatabaseFile = Path.Combine(this.IntermediateFolder, "schema.msi"); - this.GenerateDatabase(schemaOutput, msiDatabaseFile); + return schemaData; + } - // Apply the transform to the database and retrieve the modifications. - using (var msiDatabase = new Database(msiDatabaseFile, OpenDatabase.Transact)) + private Table OpenTransformViewForAddedAndModifiedRows(string schemaDatabasePath) + { + // Apply the transform with the ViewTransform option to collect all the modifications. + using (var msiDatabase = this.ApplyTransformToSchemaDatabase(schemaDatabasePath, TransformErrorConditions.All | TransformErrorConditions.ViewTransform)) { - // apply the transform with the ViewTransform option to collect all the modifications - msiDatabase.ApplyTransform(this.TransformFile, TransformErrorConditions.All | TransformErrorConditions.ViewTransform); - // unbind the database - var unbindCommand = new UnbindDatabaseCommand(this.Messaging, this.BackendHelper, msiDatabase, msiDatabaseFile, OutputType.Product, this.ExportBasePath, this.IntermediateFolder, enableDemodularization: false, skipSummaryInfo: true); + var unbindCommand = new UnbindDatabaseCommand(this.Messaging, this.BackendHelper, this.PathResolver, schemaDatabasePath, msiDatabase, OutputType.Product, null, null, this.IntermediateFolder, enableDemodularization: false, skipSummaryInfo: true); var transformViewOutput = unbindCommand.Execute(); - // index the added and possibly modified rows (added rows may also appears as modified rows) - transformViewTable = transformViewOutput.Tables["_TransformView"]; - var modifiedRows = new Hashtable(); - foreach (var row in transformViewTable.Rows) - { - var tableName = (string)row[0]; - var columnName = (string)row[1]; - var primaryKeys = (string)row[2]; - - if ("INSERT" == columnName) - { - var index = String.Concat(tableName, ':', primaryKeys); + return transformViewOutput.Tables["_TransformView"]; + } + } - addedRows.Add(index, null); - } - else if ("CREATE" != columnName && "DELETE" != columnName && "DROP" != columnName && null != primaryKeys) // modified row - { - var index = String.Concat(tableName, ':', primaryKeys); + private Dictionary CreatePlaceholdersForModifiedRowsAndIndexAddedRows(WindowsInstallerData schemaData, Table transformViewTable) + { + // Index the added and possibly modified rows (added rows may also appears as modified rows). + var addedRows = new Dictionary(); + var modifiedRows = new Dictionary(); - modifiedRows[index] = row; - } - } + foreach (var row in transformViewTable.Rows) + { + var tableName = row.FieldAsString(0); + var columnName = row.FieldAsString(1); + var primaryKeys = row.FieldAsString(2); - // create placeholder rows for modified rows to make the transform insert the updated values when its applied - foreach (Row row in modifiedRows.Values) + if ("INSERT" == columnName) { - var tableName = (string)row[0]; - var columnName = (string)row[1]; - var primaryKeys = (string)row[2]; + var index = String.Concat(tableName, ':', primaryKeys); + addedRows.Add(index, null); + } + else if ("CREATE" != columnName && "DELETE" != columnName && "DROP" != columnName && null != primaryKeys) // modified row + { var index = String.Concat(tableName, ':', primaryKeys); - // ignore information for added rows - if (!addedRows.ContainsKey(index)) + if (!modifiedRows.ContainsKey(index)) { - var table = schemaOutput.Tables[tableName]; - this.CreateRow(table, primaryKeys, true); + modifiedRows.Add(index, new TableNameWithPrimaryKeys { TableName = tableName, PrimaryKeys = primaryKeys }); } } } - // Re-bind the schema output with the placeholder rows. - this.GenerateDatabase(schemaOutput, msiDatabaseFile); - - // apply the transform to the database and retrieve the modifications - using (var msiDatabase = new Database(msiDatabaseFile, OpenDatabase.Transact)) + // Create placeholder rows for modified rows to make the transform insert the updated values when its applied. + foreach (var kvp in modifiedRows) { - try - { - // apply the transform - msiDatabase.ApplyTransform(this.TransformFile, TransformErrorConditions.All); + var index = kvp.Key; + var tableNameWithPrimaryKey = kvp.Value; - // commit the database to guard against weird errors with streams - msiDatabase.Commit(); - } - catch (Win32Exception ex) + // Ignore added rows. + if (!addedRows.ContainsKey(index)) { - if (0x65B == ex.NativeErrorCode) - { - // this commonly happens when the transform was built - // against a database schema different from the internal - // table definitions - throw new WixException(ErrorMessages.TransformSchemaMismatch()); - } + var table = schemaData.Tables[tableNameWithPrimaryKey.TableName]; + this.CreateRow(table, tableNameWithPrimaryKey.PrimaryKeys, setRequiredFields: true); } + } + + return addedRows; + } + + private void PopulateTransformFromView(string schemaDatabasePath, WindowsInstallerData transform, Table transformViewTable, Dictionary addedRows) + { + WindowsInstallerData output; + // Apply the transform to the database and retrieve the modifications + using (var database = this.ApplyTransformToSchemaDatabase(schemaDatabasePath, TransformErrorConditions.All)) + { // unbind the database - var unbindCommand = new UnbindDatabaseCommand(this.Messaging, this.BackendHelper, msiDatabase, msiDatabaseFile, OutputType.Product, this.ExportBasePath, this.IntermediateFolder, enableDemodularization: false, skipSummaryInfo: true); - var output = unbindCommand.Execute(); + var unbindCommand = new UnbindDatabaseCommand(this.Messaging, this.BackendHelper, this.PathResolver, schemaDatabasePath, database, OutputType.Product, this.ExportBasePath, null, this.IntermediateFolder, enableDemodularization: false, skipSummaryInfo: true); + output = unbindCommand.Execute(); + } - // index all the rows to easily find modified rows - var rows = new Dictionary(); - foreach (var table in output.Tables) + // index all the rows to easily find modified rows + var rows = new Dictionary(); + foreach (var table in output.Tables) + { + foreach (var row in table.Rows) { - foreach (var row in table.Rows) - { - rows.Add(String.Concat(table.Name, ':', row.GetPrimaryKey('\t', " ")), row); - } + rows.Add(String.Concat(table.Name, ':', row.GetPrimaryKey('\t', " ")), row); } + } - // process the _TransformView rows into transform rows - foreach (var row in transformViewTable.Rows) - { - var tableName = (string)row[0]; - var columnName = (string)row[1]; - var primaryKeys = (string)row[2]; + // process the _TransformView rows into transform rows + foreach (var row in transformViewTable.Rows) + { + var tableName = row.FieldAsString(0); + var columnName = row.FieldAsString(1); + var primaryKeys = row.FieldAsString(2); - var table = transform.EnsureTable(this.TableDefinitions[tableName]); + var table = transform.EnsureTable(this.TableDefinitions[tableName]); - if ("CREATE" == columnName) // added table - { - table.Operation = TableOperation.Add; - } - else if ("DELETE" == columnName) // deleted row - { - var deletedRow = this.CreateRow(table, primaryKeys, false); - deletedRow.Operation = RowOperation.Delete; - } - else if ("DROP" == columnName) // dropped table - { - table.Operation = TableOperation.Drop; - } - else if ("INSERT" == columnName) // added row - { - var index = String.Concat(tableName, ':', primaryKeys); - var addedRow = rows[index]; - addedRow.Operation = RowOperation.Add; - table.Rows.Add(addedRow); - } - else if (null != primaryKeys) // modified row + if ("CREATE" == columnName) // added table + { + table.Operation = TableOperation.Add; + } + else if ("DELETE" == columnName) // deleted row + { + var deletedRow = this.CreateRow(table, primaryKeys, false); + deletedRow.Operation = RowOperation.Delete; + } + else if ("DROP" == columnName) // dropped table + { + table.Operation = TableOperation.Drop; + } + else if ("INSERT" == columnName) // added row + { + var index = String.Concat(tableName, ':', primaryKeys); + var addedRow = rows[index]; + addedRow.Operation = RowOperation.Add; + table.Rows.Add(addedRow); + } + else if (null != primaryKeys) // modified row + { + var index = String.Concat(tableName, ':', primaryKeys); + + // the _TransformView table includes information for added rows + // that looks like modified rows so it sometimes needs to be ignored + if (!addedRows.ContainsKey(index)) { - var index = String.Concat(tableName, ':', primaryKeys); + var modifiedRow = rows[index]; - // the _TransformView table includes information for added rows - // that looks like modified rows so it sometimes needs to be ignored - if (!addedRows.ContainsKey(index)) + // mark the field as modified + var indexOfModifiedValue = -1; + for (var i = 0; i < modifiedRow.TableDefinition.Columns.Length; ++i) { - var modifiedRow = rows[index]; - - // mark the field as modified - var indexOfModifiedValue = -1; - for (var i = 0; i < modifiedRow.TableDefinition.Columns.Length; ++i) + if (columnName.Equals(modifiedRow.TableDefinition.Columns[i].Name, StringComparison.Ordinal)) { - if (columnName.Equals(modifiedRow.TableDefinition.Columns[i].Name, StringComparison.Ordinal)) - { - indexOfModifiedValue = i; - break; - } + indexOfModifiedValue = i; + break; } - modifiedRow.Fields[indexOfModifiedValue].Modified = true; + } + modifiedRow.Fields[indexOfModifiedValue].Modified = true; - // move the modified row into the transform the first time its encountered - if (RowOperation.None == modifiedRow.Operation) - { - modifiedRow.Operation = RowOperation.Modify; - table.Rows.Add(modifiedRow); - } + // move the modified row into the transform the first time its encountered + if (RowOperation.None == modifiedRow.Operation) + { + modifiedRow.Operation = RowOperation.Modify; + table.Rows.Add(modifiedRow); } } - else // added column - { - var column = table.Definition.Columns.Single(c => c.Name.Equals(columnName, StringComparison.Ordinal)); - column.Added = true; - } + } + else // added column + { + var column = table.Definition.Columns.Single(c => c.Name.Equals(columnName, StringComparison.Ordinal)); + column.Added = true; } } + } - return transform; + private Database ApplyTransformToSchemaDatabase(string schemaDatabasePath, TransformErrorConditions transformConditions) + { + var msiDatabase = new Database(schemaDatabasePath, OpenDatabase.Transact); + + try + { + // apply the transform + msiDatabase.ApplyTransform(this.TransformFile, transformConditions); + + // commit the database to guard against weird errors with streams + msiDatabase.Commit(); + } + catch (Win32Exception ex) + { + if (0x65B == ex.NativeErrorCode) + { + // this commonly happens when the transform was built + // against a database schema different from the internal + // table definitions + throw new WixException(ErrorMessages.TransformSchemaMismatch()); + } + } + + return msiDatabase; } /// @@ -305,11 +341,17 @@ namespace WixToolset.Core.WindowsInstaller.Unbind return row; } - private void GenerateDatabase(WindowsInstallerData output, string databaseFile) + private void GenerateDatabase(WindowsInstallerData data) { - var command = new GenerateDatabaseCommand(this.Messaging, this.BackendHelper, this.FileSystemManager, output, databaseFile, this.TableDefinitions, this.IntermediateFolder, keepAddedColumns: true, suppressAddingValidationRows: true, useSubdirectory: false); + var command = new GenerateDatabaseCommand(this.Messaging, this.BackendHelper, this.FileSystemManager, data, data.SourceLineNumbers.FileName, this.TableDefinitions, this.IntermediateFolder, keepAddedColumns: true, suppressAddingValidationRows: true, useSubdirectory: false); command.Execute(); } + + private class TableNameWithPrimaryKeys + { + public string TableName { get; set; } + + public string PrimaryKeys { get; set; } + } } } -#endif diff --git a/src/wix/WixToolset.Core.WindowsInstaller/WindowsInstallerDecompileResult.cs b/src/wix/WixToolset.Core.WindowsInstaller/WindowsInstallerDecompileResult.cs index 272fb3c2..0db00c50 100644 --- a/src/wix/WixToolset.Core.WindowsInstaller/WindowsInstallerDecompileResult.cs +++ b/src/wix/WixToolset.Core.WindowsInstaller/WindowsInstallerDecompileResult.cs @@ -5,10 +5,13 @@ namespace WixToolset.Core.WindowsInstaller using System.Collections.Generic; using System.Xml.Linq; using WixToolset.Data; + using WixToolset.Data.WindowsInstaller; using WixToolset.Extensibility.Data; internal class WindowsInstallerDecompileResult : IWindowsInstallerDecompileResult { + public WindowsInstallerData Data { get; set; } + public XDocument Document { get; set; } public IList ExtractedFilePaths { get; set; } diff --git a/src/wix/WixToolset.Core.WindowsInstaller/WindowsInstallerDecompiler.cs b/src/wix/WixToolset.Core.WindowsInstaller/WindowsInstallerDecompiler.cs index c78ea93a..f3d116f6 100644 --- a/src/wix/WixToolset.Core.WindowsInstaller/WindowsInstallerDecompiler.cs +++ b/src/wix/WixToolset.Core.WindowsInstaller/WindowsInstallerDecompiler.cs @@ -3,13 +3,15 @@ namespace WixToolset.Core.WindowsInstaller { using System; - using System.ComponentModel.Design; + using System.Collections.Generic; using System.IO; using System.Linq; + using WixToolset.Core.WindowsInstaller.Bind; using WixToolset.Core.WindowsInstaller.Decompile; using WixToolset.Core.WindowsInstaller.Unbind; using WixToolset.Data; using WixToolset.Data.WindowsInstaller; + using WixToolset.Extensibility; using WixToolset.Extensibility.Data; using WixToolset.Extensibility.Services; @@ -22,12 +24,15 @@ namespace WixToolset.Core.WindowsInstaller { this.ServiceProvider = serviceProvider; this.Messaging = serviceProvider.GetService(); + this.ExtensionManager = serviceProvider.GetService(); } private IServiceProvider ServiceProvider { get; } private IMessaging Messaging { get; } + private IExtensionManager ExtensionManager { get; } + public IWindowsInstallerDecompileResult Decompile(IWindowsInstallerDecompileContext context) { if (context.SymbolDefinitionCreator == null) @@ -62,7 +67,7 @@ namespace WixToolset.Core.WindowsInstaller private IWindowsInstallerDecompileResult Execute(IWindowsInstallerDecompileContext context) { // Delete the directory and its files to prevent cab extraction failure due to an existing file. - if (Directory.Exists(context.ExtractFolder)) + if (!String.IsNullOrEmpty(context.ExtractFolder) && Directory.Exists(context.ExtractFolder)) { Directory.Delete(context.ExtractFolder, true); } @@ -71,11 +76,23 @@ namespace WixToolset.Core.WindowsInstaller var pathResolver = context.ServiceProvider.GetService(); + if (context.DecompileType == OutputType.Transform) + { + return this.DecompileTransform(context, backendHelper, pathResolver); + } + else + { + return this.DecompileDatabase(context, backendHelper, pathResolver); + } + } + + private IWindowsInstallerDecompileResult DecompileDatabase(IWindowsInstallerDecompileContext context, IWindowsInstallerBackendHelper backendHelper, IPathResolver pathResolver) + { var extractFilesFolder = context.SuppressExtractCabinets || (String.IsNullOrEmpty(context.CabinetExtractFolder) && String.IsNullOrEmpty(context.ExtractFolder)) ? null : String.IsNullOrEmpty(context.CabinetExtractFolder) ? Path.Combine(context.ExtractFolder, "File") : context.CabinetExtractFolder; var outputType = context.TreatProductAsModule ? OutputType.Module : context.DecompileType; - var unbindCommand = new UnbindDatabaseCommand(this.Messaging, backendHelper, pathResolver, context.DecompilePath, outputType, context.ExtractFolder, extractFilesFolder, context.IntermediateFolder, enableDemodularization: true, skipSummaryInfo: false); + var unbindCommand = new UnbindDatabaseCommand(this.Messaging, backendHelper, pathResolver, context.DecompilePath, null, outputType, context.ExtractFolder, extractFilesFolder, context.IntermediateFolder, enableDemodularization: true, skipSummaryInfo: false); var output = unbindCommand.Execute(); var extractedFilePaths = unbindCommand.ExportedFiles; @@ -84,10 +101,24 @@ namespace WixToolset.Core.WindowsInstaller var document = decompiler.Decompile(output); var result = context.ServiceProvider.GetService(); + result.Data = output; result.Document = document; result.Platform = GetPlatformFromOutput(output); result.ExtractedFilePaths = extractedFilePaths.ToList(); + return result; + } + + private IWindowsInstallerDecompileResult DecompileTransform(IWindowsInstallerDecompileContext context, IWindowsInstallerBackendHelper backendHelper, IPathResolver pathResolver) + { + var fileSystemExtensions = this.ExtensionManager.GetServices(); + var fileSystemManager = new FileSystemManager(fileSystemExtensions); + + var unbindCommand = new UnbindTransformCommand(this.Messaging, backendHelper, pathResolver, fileSystemManager, context.DecompilePath, context.ExtractFolder, context.IntermediateFolder); + var output = unbindCommand.Execute(); + + var result = context.ServiceProvider.GetService(); + result.Data = output; return result; } diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/PatchFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/PatchFixture.cs index b0d49c05..123e5742 100644 --- a/src/wix/test/WixToolsetTest.CoreIntegration/PatchFixture.cs +++ b/src/wix/test/WixToolsetTest.CoreIntegration/PatchFixture.cs @@ -18,6 +18,8 @@ namespace WixToolsetTest.CoreIntegration using WixToolset.Core.TestPackage; using WixToolset.Data; using WixToolset.Data.Burn; + using WixToolset.Data.WindowsInstaller; + using WixToolset.Dtf.Compression.Cab; using Xunit; public class PatchFixture : IDisposable @@ -395,9 +397,9 @@ namespace WixToolsetTest.CoreIntegration } [Fact] - public void CanBuildPatchWithFiltering() + public void CanBuildPatchWithFileFiltering() { - var sourceFolder = TestData.Get(@"TestData", "PatchFamilyFilter"); + var sourceFolder = TestData.Get(@"TestData", "PatchFamilyFileFilter"); using (var fs = new DisposableFileSystem()) { @@ -406,23 +408,50 @@ namespace WixToolsetTest.CoreIntegration var patchPath = BuildMsp("Patch1.msp", sourceFolder, tempFolderPatch, "1.0.1", bindpaths: new[] { Path.GetDirectoryName(this.templateBaselinePdb), Path.GetDirectoryName(this.templateUpdatePdb) }); - var doc = GetExtractPatchXml(patchPath); - WixAssert.StringEqual("{11111111-2222-3333-4444-555555555555}", doc.Root.Element(TargetProductCodeName).Value); - - var names = Query.GetSubStorageNames(patchPath); - WixAssert.CompareLineByLine(new[] { "#RTM.1", "RTM.1" }, names); + var mainTransform = ExtractBaselinePatch(patchPath, "RTM.1", baseFolder); + Assert.Null(mainTransform.Tables["Registry"]); + var fileRow = mainTransform.Tables["File"].Rows.Single(); + Assert.Equal("a.txt", fileRow.FieldAsString(0)); + Assert.Equal(152, fileRow.FieldAsInteger(3)); - var cab = Path.Combine(baseFolder, "foo.cab"); - Query.ExtractStream(patchPath, "foo.cab", cab); + var pairedTransform = ExtractBaselinePatch(patchPath, "#RTM.1", baseFolder); + fileRow = mainTransform.Tables["File"].Rows.Single(); + Assert.Equal("a.txt", fileRow.FieldAsString(0)); + Assert.Equal(152, fileRow.FieldAsInteger(3)); - var files = Query.GetCabinetFiles(cab); + var files = ExtractFilesFromPatchCabinet(patchPath, "foo.cab", baseFolder); var file = files.Single(); - WixAssert.StringEqual("a.txt", file.Name); var contents = file.OpenText().ReadToEnd(); WixAssert.StringEqual("This is A v1.0.1 from the '.update-data' folder in 'PatchTemplatePackage'.\r\n\r\nLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod.\r\n", contents); } } + [Fact] + public void CanBuildPatchWithRegistryFiltering() + { + var sourceFolder = TestData.Get(@"TestData", "PatchFamilyRegistryFilter"); + + using (var fs = new DisposableFileSystem()) + { + var baseFolder = fs.GetFolder(); + var tempFolderPatch = Path.Combine(baseFolder, "patch"); + + var patchPath = BuildMsp("Patch1.msp", sourceFolder, tempFolderPatch, "1.0.1", bindpaths: new[] { Path.GetDirectoryName(this.templateBaselinePdb), Path.GetDirectoryName(this.templateUpdatePdb) }, warningsAsErrors: false); + + var mainTransform = ExtractBaselinePatch(patchPath, "RTM.1", baseFolder); + Assert.Null(mainTransform.Tables["File"]); + var row = mainTransform.Tables["Registry"].Rows.Single(); + Assert.Equal("regUty0zLJ5uYhRlGzmOzENKmnAtno", row.FieldAsString(0)); + Assert.Equal("1.0.1", row.FieldAsString(4)); + + var pairedTransform = ExtractBaselinePatch(patchPath, "#RTM.1", baseFolder); + Assert.Null(pairedTransform.Tables["File"]); + + var files = ExtractFilesFromPatchCabinet(patchPath, "foo.cab", baseFolder); + Assert.Empty(files); + } + } + private static string BuildMsi(string outputName, string sourceFolder, string baseFolder, string defineV, string defineA, string defineB, IEnumerable bindpaths = null) { var extensionPath = Path.GetFullPath(new Uri(typeof(ExampleExtensionFactory).Assembly.CodeBase).LocalPath); @@ -552,6 +581,41 @@ namespace WixToolsetTest.CoreIntegration Assert.Equal(0, proc.ExitCode); } + private static WindowsInstallerData DecompileMst(string transformPath, string baseFolder) + { + var outputPath = Path.ChangeExtension(transformPath, ".wixmst"); + + var args = new List + { + "msi", "decompile", + transformPath, + "-intermediateFolder", Path.Combine(baseFolder), + "-o", outputPath, + }; + + var result = WixRunner.Execute(args.ToArray()); + + result.AssertSuccess(); + + return WindowsInstallerData.Load(outputPath); + } + + private static WindowsInstallerData ExtractBaselinePatch(string patchPath, string substorageName, string baseFolder) + { + var mstPath = Path.Combine(baseFolder, substorageName, substorageName + ".mst"); + Query.ExtractSubStorage(patchPath, substorageName, mstPath); + + return DecompileMst(mstPath, baseFolder); + } + + private static CabFileInfo[] ExtractFilesFromPatchCabinet(string patchPath, string cabinetName, string baseFolder) + { + var cab = Path.Combine(baseFolder, cabinetName); + Query.ExtractStream(patchPath, cabinetName, cab); + + return Query.GetCabinetFiles(cab); + } + private static XDocument GetExtractPatchXml(string path) { var buffer = new StringBuilder(65535); diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFileFilter/.data/Av1.0.0.txt b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFileFilter/.data/Av1.0.0.txt new file mode 100644 index 00000000..6fd385bd --- /dev/null +++ b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFileFilter/.data/Av1.0.0.txt @@ -0,0 +1 @@ +This is A v1.0.0 diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFileFilter/.data/Av1.0.1.txt b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFileFilter/.data/Av1.0.1.txt new file mode 100644 index 00000000..b1f0bc01 --- /dev/null +++ b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFileFilter/.data/Av1.0.1.txt @@ -0,0 +1 @@ +This ia A v1.0.1 diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFileFilter/.data/Bv1.0.0.txt b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFileFilter/.data/Bv1.0.0.txt new file mode 100644 index 00000000..ece55fec --- /dev/null +++ b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFileFilter/.data/Bv1.0.0.txt @@ -0,0 +1 @@ +This is B v1.0.0 diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFileFilter/.data/Bv1.0.1.txt b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFileFilter/.data/Bv1.0.1.txt new file mode 100644 index 00000000..cf3372fd --- /dev/null +++ b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFileFilter/.data/Bv1.0.1.txt @@ -0,0 +1 @@ +This ia B v1.0.1 diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFileFilter/Package.wxs b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFileFilter/Package.wxs new file mode 100644 index 00000000..6e1db0bc --- /dev/null +++ b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFileFilter/Package.wxs @@ -0,0 +1,30 @@ + diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFileFilter/Patch.wxs b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFileFilter/Patch.wxs new file mode 100644 index 00000000..3723af48 --- /dev/null +++ b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFileFilter/Patch.wxs @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFilter/.data/Av1.0.0.txt b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFilter/.data/Av1.0.0.txt deleted file mode 100644 index 6fd385bd..00000000 --- a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFilter/.data/Av1.0.0.txt +++ /dev/null @@ -1 +0,0 @@ -This is A v1.0.0 diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFilter/.data/Av1.0.1.txt b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFilter/.data/Av1.0.1.txt deleted file mode 100644 index b1f0bc01..00000000 --- a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFilter/.data/Av1.0.1.txt +++ /dev/null @@ -1 +0,0 @@ -This ia A v1.0.1 diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFilter/.data/Bv1.0.0.txt b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFilter/.data/Bv1.0.0.txt deleted file mode 100644 index ece55fec..00000000 --- a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFilter/.data/Bv1.0.0.txt +++ /dev/null @@ -1 +0,0 @@ -This is B v1.0.0 diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFilter/.data/Bv1.0.1.txt b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFilter/.data/Bv1.0.1.txt deleted file mode 100644 index cf3372fd..00000000 --- a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFilter/.data/Bv1.0.1.txt +++ /dev/null @@ -1 +0,0 @@ -This ia B v1.0.1 diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFilter/Package.wxs b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFilter/Package.wxs deleted file mode 100644 index c9dcdd72..00000000 --- a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFilter/Package.wxs +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFilter/Patch.wxs b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFilter/Patch.wxs deleted file mode 100644 index f48fd1ef..00000000 --- a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyFilter/Patch.wxs +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyRegistryFilter/Patch.wxs b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyRegistryFilter/Patch.wxs new file mode 100644 index 00000000..dab89379 --- /dev/null +++ b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/PatchFamilyRegistryFilter/Patch.wxs @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + -- cgit v1.2.3-55-g6feb