// 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. using System; using System.IO; using WixToolset.Dtf.WindowsInstaller; using WixToolset.Dtf.WindowsInstaller.Package; namespace WixToolset.Dtf.Tools.DDiff { public class MspDiffEngine : MsiDiffEngine { public MspDiffEngine() { } private string GetPatchTargetOption(string[] options) { for(int i = 0; i < options.Length - 1; i++) { switch(options[i].ToLower()) { case "/p": goto case "-patchtarget"; case "-p": goto case "-patchtarget"; case "/patchtarget": goto case "-patchtarget"; case "-patchtarget": return options[i+1]; } } return null; } public override float GetDiffQuality(string diffInput1, string diffInput2, string[] options, IDiffEngineFactory diffFactory) { if(diffInput1 != null && File.Exists(diffInput1) && diffInput2 != null && File.Exists(diffInput2) && GetPatchTargetOption(options) != null && (IsMspPatch(diffInput1) && IsMspPatch(diffInput2))) { return .80f; } else if(diffInput1 != null && File.Exists(diffInput1) && diffInput2 != null && File.Exists(diffInput2) && GetPatchTargetOption(options) == null && (IsMspPatch(diffInput1) && IsMsiDatabase(diffInput2)) || (IsMsiDatabase(diffInput1) && IsMspPatch(diffInput2))) { return .75f; } else { return 0; } } public override bool GetDiff(string diffInput1, string diffInput2, string[] options, TextWriter diffOutput, string linePrefix, IDiffEngineFactory diffFactory) { bool difference = false; InstallPackage db1, db2; if(IsMspPatch(diffInput1)) { string patchTargetDbFile = GetPatchTargetOption(options); if(patchTargetDbFile == null) patchTargetDbFile = diffInput2; string tempPatchedDbFile = Path.GetTempFileName(); File.Copy(patchTargetDbFile, tempPatchedDbFile, true); File.SetAttributes(tempPatchedDbFile, File.GetAttributes(tempPatchedDbFile) & ~System.IO.FileAttributes.ReadOnly); db1 = new InstallPackage(tempPatchedDbFile, DatabaseOpenMode.Direct); db1.ApplyPatch(new PatchPackage(diffInput1), null); db1.Commit(); } else { db1 = new InstallPackage(diffInput1, DatabaseOpenMode.ReadOnly); } if(IsMspPatch(diffInput2)) { string patchTargetDbFile = GetPatchTargetOption(options); if(patchTargetDbFile == null) patchTargetDbFile = diffInput1; string tempPatchedDbFile = Path.GetTempFileName(); File.Copy(patchTargetDbFile, tempPatchedDbFile, true); File.SetAttributes(tempPatchedDbFile, File.GetAttributes(tempPatchedDbFile) & ~System.IO.FileAttributes.ReadOnly); db2 = new InstallPackage(tempPatchedDbFile, DatabaseOpenMode.Direct); db2.ApplyPatch(new PatchPackage(diffInput2), null); db2.Commit(); } else { db2 = new InstallPackage(diffInput2, DatabaseOpenMode.ReadOnly); } if(GetSummaryInfoDiff(db1, db2, options, diffOutput, linePrefix, diffFactory)) difference = true; if(GetDatabaseDiff(db1, db2, options, diffOutput, linePrefix, diffFactory)) difference = true; if(GetStreamsDiff(db1, db2, options, diffOutput, linePrefix, diffFactory)) difference = true; db1.Close(); db2.Close(); try { if(IsMspPatch(diffInput1)) File.Delete(db1.FilePath); if(IsMspPatch(diffInput1)) File.Delete(db2.FilePath); } catch(IOException) { #if DEBUG Console.WriteLine("Could not delete temporary files {0} and {1}", db1.FilePath, db2.FilePath); #endif } if(IsMspPatch(diffInput1) && IsMspPatch(diffInput2)) { Database dbp1 = new Database(diffInput1, DatabaseOpenMode.ReadOnly); Database dbp2 = new Database(diffInput2, DatabaseOpenMode.ReadOnly); if(GetStreamsDiff(dbp1, dbp2, options, diffOutput, linePrefix, diffFactory)) difference = true; dbp1.Close(); dbp2.Close(); } return difference; } public override IDiffEngine Clone() { return new MspDiffEngine(); } } }