Exemple #1
0
        public override SignatureVerificationResult VerifySignature(string path, string parent)
        {
            // Let the base class take care of verifying the AuthentiCode/StrongName
            SignatureVerificationResult svr = base.VerifySignature(path, parent);

            if (VerifyRecursive)
            {
                if (PEHeader.ImageSectionHeaders.Select(s => s.SectionName).Contains(".wixburn"))
                {
                    Log.WriteMessage(LogVerbosity.Diagnostic, SignCheckResources.DiagSectionHeader, ".wixburn");
                    Log.WriteMessage(LogVerbosity.Detailed, SignCheckResources.WixBundle, svr.FullPath);
                    Unbinder unbinder = null;

                    try
                    {
                        Log.WriteMessage(LogVerbosity.Diagnostic, SignCheckResources.DiagExtractingFileContents, svr.TempPath);
                        unbinder          = new Unbinder();
                        unbinder.Message += UnbinderEventHandler;
                        Output o = unbinder.Unbind(svr.FullPath, OutputType.Bundle, svr.TempPath);

                        if (Directory.Exists(svr.TempPath))
                        {
                            foreach (string file in Directory.EnumerateFiles(svr.TempPath, "*.*", SearchOption.AllDirectories))
                            {
                                SignatureVerificationResult bundleEntryResult = VerifyFile(Path.GetFullPath(file), svr.Filename, Path.GetFileName(file));
                                //CheckAndUpdateExclusion(bundleEntryResult, "*"+Path.GetFileName(file), file, svr.Filename);
                                svr.NestedResults.Add(bundleEntryResult);
                            }
                        }

                        Directory.Delete(svr.TempPath, recursive: true);
                    }
                    finally
                    {
                        unbinder.DeleteTempFiles();
                    }
                }
            }

            // TODO: Check for SFXCAB, IronMan, etc.

            return(svr);
        }
Exemple #2
0
        /// <summary>
        /// Main running method for the application.
        /// </summary>
        /// <param name="args">Commandline arguments to the application.</param>
        /// <returns>Returns the application error code.</returns>
        private int Run(string[] args)
        {
            Microsoft.Tools.WindowsInstallerXml.Binder binder = null;
            Differ   differ   = null;
            Unbinder unbinder = null;

            TempFileCollection tempFileCollection = null;

            try
            {
                // parse the command line
                this.ParseCommandLine(args);

                // validate the inputs
                if (this.xmlInputs && this.adminImage)
                {
                    this.messageHandler.Display(this, WixErrors.IllegalCommandlineArgumentCombination("a", "xi"));
                    this.showHelp = true;
                }

                string[] allValidExtensions               = new string[] { wixMstExtension, wixOutExtension, wixPdbExtension, msiExtension };
                string[] expectedSingleInputExtensions    = new string[] { wixMstExtension, wixOutExtension };
                string[] expectedDoubleInputXmlExtensions = new string[] { wixOutExtension, wixPdbExtension };
                string[] expectedDoubleInputMsiExtensions = new string[] { msiExtension };

                // Validate that all inputs have the correct extension and we dont have too many inputs.
                if (1 == this.inputFiles.Count)
                {
                    string inputFile = this.inputFiles[0];

                    bool hasValidExtension = false;
                    foreach (string extension in expectedSingleInputExtensions)
                    {
                        if (String.Equals(Path.GetExtension(inputFile), extension, StringComparison.OrdinalIgnoreCase))
                        {
                            hasValidExtension = true;
                            break;
                        }
                    }

                    if (!hasValidExtension)
                    {
                        bool missingInput = false;

                        // Check if its using an extension that could be valid in other scenarios.
                        foreach (string validExtension in allValidExtensions)
                        {
                            if (String.Equals(Path.GetExtension(inputFile), validExtension, StringComparison.OrdinalIgnoreCase))
                            {
                                this.messageHandler.Display(this, WixErrors.WrongFileExtensionForNumberOfInputs(Path.GetExtension(inputFile), inputFile));
                                missingInput = true;
                                break;
                            }
                        }

                        if (!missingInput)
                        {
                            this.messageHandler.Display(this, WixErrors.UnexpectedFileExtension(inputFile, String.Join(", ", expectedSingleInputExtensions)));
                        }
                    }
                }
                else if (2 == this.inputFiles.Count)
                {
                    foreach (string inputFile in inputFiles)
                    {
                        bool     hasValidExtension  = false;
                        string[] expectedExtensions = allValidExtensions;
                        if (this.xmlInputs)
                        {
                            foreach (string extension in expectedDoubleInputXmlExtensions)
                            {
                                if (String.Equals(Path.GetExtension(inputFile), extension, StringComparison.OrdinalIgnoreCase))
                                {
                                    hasValidExtension  = true;
                                    expectedExtensions = expectedDoubleInputXmlExtensions;
                                    break;
                                }
                            }
                        }
                        else
                        {
                            foreach (string extension in expectedDoubleInputMsiExtensions)
                            {
                                if (String.Equals(Path.GetExtension(inputFile), extension, StringComparison.OrdinalIgnoreCase))
                                {
                                    hasValidExtension  = true;
                                    expectedExtensions = expectedDoubleInputMsiExtensions;
                                    break;
                                }
                            }
                        }

                        if (!hasValidExtension)
                        {
                            this.messageHandler.Display(this, WixErrors.UnexpectedFileExtension(inputFile, String.Join(", ", expectedExtensions)));
                        }
                    }
                }
                else
                {
                    this.showHelp = true;
                }

                // exit if there was an error parsing the command line or with a file extension (otherwise the logo appears after error messages)
                if (this.messageHandler.EncounteredError)
                {
                    return(this.messageHandler.LastErrorNumber);
                }

                if (null == this.outputFile)
                {
                    this.showHelp = true;
                }

                if (this.showLogo)
                {
                    AppCommon.DisplayToolHeader();
                }

                if (this.showHelp)
                {
                    Console.WriteLine(TorchStrings.HelpMessage);
                    AppCommon.DisplayToolFooter();
                    return(this.messageHandler.LastErrorNumber);
                }

                foreach (string parameter in this.invalidArgs)
                {
                    this.messageHandler.Display(this, WixWarnings.UnsupportedCommandLineArgument(parameter));
                }
                this.invalidArgs = null;

                binder   = new Microsoft.Tools.WindowsInstallerXml.Binder();
                differ   = new Differ();
                unbinder = new Unbinder();

                // load any extensions
                foreach (string extension in this.extensionList)
                {
                    WixExtension wixExtension = WixExtension.Load(extension);
                    unbinder.AddExtension(wixExtension);
                    binder.AddExtension(wixExtension);
                    differ.AddExtension(wixExtension);
                }

                binder.Message   += new MessageEventHandler(this.messageHandler.Display);
                differ.Message   += new MessageEventHandler(this.messageHandler.Display);
                unbinder.Message += new MessageEventHandler(this.messageHandler.Display);

                binder.TempFilesLocation   = Environment.GetEnvironmentVariable("WIX_TEMP");
                unbinder.TempFilesLocation = Environment.GetEnvironmentVariable("WIX_TEMP");
                tempFileCollection         = new TempFileCollection(Environment.GetEnvironmentVariable("WIX_TEMP"));

                binder.WixVariableResolver       = new WixVariableResolver();
                differ.PreserveUnchangedRows     = this.preserveUnchangedRows;
                differ.ShowPedanticMessages      = this.showPedanticMessages;
                unbinder.SuppressExtractCabinets = true;
                unbinder.IsAdminImage            = this.adminImage;

                if (null == this.exportBasePath)
                {
                    this.exportBasePath = tempFileCollection.BasePath;
                }

                // load and process the inputs
                Output transform;
                if (1 == this.inputFiles.Count)
                {
                    transform = Output.Load(this.inputFiles[0], false, false);
                    if (OutputType.Transform != transform.Type)
                    {
                        this.messageHandler.Display(this, WixErrors.InvalidWixTransform(this.inputFiles[0]));
                        return(this.messageHandler.LastErrorNumber);
                    }
                }
                else // 2 inputs
                {
                    Output targetOutput;
                    Output updatedOutput;

                    if (this.xmlInputs)
                    {
                        // load the target database
                        if (String.Equals(Path.GetExtension(inputFiles[0]), wixPdbExtension, StringComparison.OrdinalIgnoreCase))
                        {
                            Pdb targetPdb = Pdb.Load(this.inputFiles[0], false, false);
                            targetOutput = targetPdb.Output;
                        }
                        else
                        {
                            targetOutput = Output.Load(this.inputFiles[0], false, false);
                        }

                        // load the updated database
                        if (String.Equals(Path.GetExtension(inputFiles[1]), wixPdbExtension, StringComparison.OrdinalIgnoreCase))
                        {
                            Pdb updatedPdb = Pdb.Load(this.inputFiles[1], false, false);
                            updatedOutput = updatedPdb.Output;
                        }
                        else
                        {
                            updatedOutput = Output.Load(this.inputFiles[1], false, false);
                        }

                        this.xmlOutput = true;
                    }
                    else
                    {
                        // load the target database
                        targetOutput = unbinder.Unbind(this.inputFiles[0], OutputType.Product, Path.Combine(this.exportBasePath, "targetBinaries"));

                        // load the updated database
                        updatedOutput = unbinder.Unbind(this.inputFiles[1], OutputType.Product, Path.Combine(this.exportBasePath, "updatedBinaries"));
                    }

                    // diff the target and updated databases
                    transform = differ.Diff(targetOutput, updatedOutput, this.validationFlags);

                    if (null == transform.Tables || 0 >= transform.Tables.Count)
                    {
                        throw new WixException(WixErrors.NoDifferencesInTransform(transform.SourceLineNumbers));
                    }
                }

                // output the transform
                if (null != transform)
                {
                    // If either the user selected xml output or gave xml input, save as xml output.
                    // With xml inputs, many funtions of the binder have not been performed on the inputs (ie. file sequencing). This results in bad IDT files which cannot be put in a transform.
                    if (this.xmlOutput)
                    {
                        transform.Save(this.outputFile, null, null, tempFileCollection.BasePath);
                    }
                    else
                    {
                        binder.Bind(transform, this.outputFile);
                    }
                }
            }
            catch (WixException we)
            {
                if (we is WixInvalidIdtException)
                {
                    // make sure the IDT files stay around
                    this.tidy = false;
                }

                this.messageHandler.Display(this, we.Error);
            }
            catch (Exception e)
            {
                // make sure the files stay around for debugging
                this.tidy = false;

                this.messageHandler.Display(this, WixErrors.UnexpectedException(e.Message, e.GetType().ToString(), e.StackTrace));
                if (e is NullReferenceException || e is SEHException)
                {
                    throw;
                }
            }
            finally
            {
                if (null != binder)
                {
                    if (this.tidy)
                    {
                        if (!binder.DeleteTempFiles())
                        {
                            Console.WriteLine(TorchStrings.WAR_FailedToDeleteTempDir, binder.TempFilesLocation);
                        }
                    }
                    else
                    {
                        Console.WriteLine(TorchStrings.INF_BinderTempDirLocatedAt, binder.TempFilesLocation);
                    }
                }

                if (null != unbinder)
                {
                    if (this.tidy)
                    {
                        if (!unbinder.DeleteTempFiles())
                        {
                            Console.WriteLine(TorchStrings.WAR_FailedToDeleteTempDir, binder.TempFilesLocation);
                        }
                    }
                    else
                    {
                        Console.WriteLine(TorchStrings.INF_UnbinderTempDirLocatedAt, binder.TempFilesLocation);
                    }
                }

                if (null != tempFileCollection)
                {
                    if (this.tidy)
                    {
                        try
                        {
                            Directory.Delete(tempFileCollection.BasePath, true);
                        }
                        catch (DirectoryNotFoundException)
                        {
                            // if the path doesn't exist, then there is nothing for us to worry about
                        }
                        catch
                        {
                            Console.WriteLine(TorchStrings.WAR_FailedToDeleteTempDir, tempFileCollection.BasePath);
                        }
                    }
                    else
                    {
                        Console.WriteLine(TorchStrings.INF_TorchTempDirLocatedAt, tempFileCollection.BasePath);
                    }
                }
            }

            return(this.messageHandler.LastErrorNumber);
        }
Exemple #3
0
        /// <summary>
        /// Compare two result files.
        /// </summary>
        /// <param name="expectedResult">The expected result file.</param>
        /// <param name="actualResult">The actual result file.</param>
        /// <returns>Any differences found.</returns>
        public static ArrayList CompareResults(string expectedResult, string actualResult)
        {
            ArrayList differences = new ArrayList();
            Output targetOutput;
            Output updatedOutput;

            OutputType outputType;
            string extension = Path.GetExtension(expectedResult);
            if (String.Compare(extension, ".msi", true, CultureInfo.InvariantCulture) == 0)
            {
                outputType = OutputType.Product;
            }
            else if (String.Compare(extension, ".msm", true, CultureInfo.InvariantCulture) == 0)
            {
                outputType = OutputType.Module;
            }
            else if (String.Compare(extension, ".msp", true, CultureInfo.InvariantCulture) == 0)
            {
                outputType = OutputType.Patch;
            }
            else if (String.Compare(extension, ".mst", true, CultureInfo.InvariantCulture) == 0)
            {
                outputType = OutputType.Transform;
            }
            else if (String.Compare(extension, ".pcp", true, CultureInfo.InvariantCulture) == 0)
            {
                outputType = OutputType.PatchCreation;
            }
            else if (String.Compare(extension, ".wixout", true, CultureInfo.InvariantCulture) == 0)
            {
                outputType = OutputType.Unknown;
            }
            else
            {
                throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Cannot determine the type of msi database file based on file extension '{0}'.", extension));
            }

            if (outputType != OutputType.Unknown)
            {
                Unbinder unbinder = new Unbinder();
                unbinder.SuppressDemodularization = true;

                // don't allow concurrent calls to Unbind
                try
                {
                    mutex.WaitOne();
                    targetOutput = unbinder.Unbind(expectedResult, outputType, null);
                    updatedOutput = unbinder.Unbind(actualResult, outputType, null);
                    unbinder.DeleteTempFiles();
                }
                finally
                {
                    mutex.ReleaseMutex();
                }

            }
            else
            {
                targetOutput = Output.Load(expectedResult, false, false);
                updatedOutput = Output.Load(actualResult, false, false);
            }

            differences.AddRange(CompareOutput(targetOutput, updatedOutput));

            // If the Output type is a Patch, then compare the patch's transforms
            if (outputType == OutputType.Patch)
            {
                // Compare transforms
                foreach (SubStorage targetTransform in targetOutput.SubStorages)
                {
                    SubStorage updatedTransform = null;

                    // Find the same transform in the other patch
                    foreach (SubStorage transform in updatedOutput.SubStorages)
                    {
                        if (transform.Name == targetTransform.Name)
                        {
                            updatedTransform = transform;
                            break;
                        }
                    }

                    if (null != updatedTransform)
                    {
                        // Both patch's have this transform
                        ArrayList transformDifferences = CompareUnit.CompareOutput(targetTransform.Data, updatedTransform.Data);

                        // add a description of the transforms being compared
                        if (0 < transformDifferences.Count)
                        {
                            transformDifferences.Insert(0, String.Concat("Differences found while comparing the transform ", targetTransform.Name, " from the two patches"));
                            differences.AddRange(transformDifferences);
                        }
                    }
                    else
                    {
                        differences.Add(String.Format("The {0} tranform has been dropped", targetTransform.Name));
                    }
                }

                // Check if the updated patch has had transforms added
                foreach (SubStorage updatedTransform in updatedOutput.SubStorages)
                {
                    SubStorage targetTransform = null;
                    foreach (SubStorage transform in targetOutput.SubStorages)
                    {
                        if (transform.Name == updatedTransform.Name)
                        {
                            targetTransform = transform;
                            break;
                        }
                    }

                    if (targetTransform == null)
                    {
                        differences.Add(String.Format("The {0} tranform has been added", updatedTransform.Name));
                    }
                }
            }

            // add a description of the files being compared
            if (0 < differences.Count)
            {
                differences.Insert(0, "Differences found while comparing:");
                differences.Insert(1, expectedResult);
                differences.Insert(2, actualResult);
            }

            return differences;
        }
Exemple #4
0
        /// <summary>
        /// Compare two result files.
        /// </summary>
        /// <param name="expectedResult">The expected result file.</param>
        /// <param name="actualResult">The actual result file.</param>
        /// <param name="tables">The list of tables to compare</param>
        /// <returns>Any differences found.</returns>
        public static ArrayList CompareResults(string expectedResult, string actualResult, params string[] tables)
        {
            ArrayList differences = new ArrayList();
            Output    targetOutput;
            Output    updatedOutput;

            expectedResult = Environment.ExpandEnvironmentVariables(expectedResult);
            actualResult   = Environment.ExpandEnvironmentVariables(actualResult);

            OutputType outputType;
            string     extension = Path.GetExtension(expectedResult);

            if (String.Compare(extension, ".msi", true, CultureInfo.InvariantCulture) == 0)
            {
                outputType = OutputType.Product;
            }
            else if (String.Compare(extension, ".msm", true, CultureInfo.InvariantCulture) == 0)
            {
                outputType = OutputType.Module;
            }
            else if (String.Compare(extension, ".msp", true, CultureInfo.InvariantCulture) == 0)
            {
                outputType = OutputType.Patch;
            }
            else if (String.Compare(extension, ".mst", true, CultureInfo.InvariantCulture) == 0)
            {
                outputType = OutputType.Transform;
            }
            else if (String.Compare(extension, ".pcp", true, CultureInfo.InvariantCulture) == 0)
            {
                outputType = OutputType.PatchCreation;
            }
            else if (String.Compare(extension, ".wixout", true, CultureInfo.InvariantCulture) == 0)
            {
                outputType = OutputType.Unknown;
            }
            else
            {
                throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Cannot determine the type of msi database file based on file extension '{0}'.", extension));
            }

            if (outputType != OutputType.Unknown)
            {
                Unbinder unbinder = new Unbinder();
                unbinder.SuppressDemodularization = true;

                targetOutput  = unbinder.Unbind(expectedResult, outputType, null);
                updatedOutput = unbinder.Unbind(actualResult, outputType, null);
            }
            else
            {
                targetOutput  = Output.Load(expectedResult, false, false);
                updatedOutput = Output.Load(actualResult, false, false);
            }

            differences.AddRange(CompareOutput(targetOutput, updatedOutput, tables));

            // If the Output type is a Patch, then compare the patch's transforms
            if (outputType == OutputType.Patch)
            {
                // Compare transforms
                foreach (SubStorage targetTransform in targetOutput.SubStorages)
                {
                    SubStorage updatedTransform = null;

                    // Find the same transform in the other patch
                    foreach (SubStorage transform in updatedOutput.SubStorages)
                    {
                        if (transform.Name == targetTransform.Name)
                        {
                            updatedTransform = transform;
                            break;
                        }
                    }

                    if (null != updatedTransform)
                    {
                        // Both patch's have this transform
                        ArrayList transformDifferences = Verifier.CompareOutput(targetTransform.Data, updatedTransform.Data);

                        // add a description of the transforms being compared
                        if (0 < transformDifferences.Count)
                        {
                            transformDifferences.Insert(0, String.Concat("Differences found while comparing the transform ", targetTransform.Name, " from the two patches"));
                            differences.AddRange(transformDifferences);
                        }
                    }
                    else
                    {
                        differences.Add(String.Format("The {0} tranform has been dropped", targetTransform.Name));
                    }
                }

                // Check if the updated patch has had transforms added
                foreach (SubStorage updatedTransform in updatedOutput.SubStorages)
                {
                    SubStorage targetTransform = null;
                    foreach (SubStorage transform in targetOutput.SubStorages)
                    {
                        if (transform.Name == updatedTransform.Name)
                        {
                            targetTransform = transform;
                            break;
                        }
                    }

                    if (targetTransform == null)
                    {
                        differences.Add(String.Format("The {0} tranform has been added", updatedTransform.Name));
                    }
                }
            }

            // add a description of the files being compared
            if (0 < differences.Count)
            {
                differences.Insert(0, "Differences found while comparing:");
                differences.Insert(1, expectedResult);
                differences.Insert(2, actualResult);
            }

            return(differences);
        }
Exemple #5
0
        /// <summary>
        /// Main running method for the application.
        /// </summary>
        /// <param name="args">Commandline arguments to the application.</param>
        /// <returns>Returns the application error code.</returns>
        private int Run(string[] args)
        {
            Decompiler decompiler = null;
            Mutator    mutator    = null;
            Unbinder   unbinder   = null;

            try
            {
                // parse the command line
                this.ParseCommandLine(args);

                // exit if there was an error parsing the command line (otherwise the logo appears after error messages)
                if (this.messageHandler.EncounteredError)
                {
                    return(this.messageHandler.LastErrorNumber);
                }

                if (null == this.inputFile)
                {
                    this.showHelp = true;
                }
                else if (null == this.outputFile)
                {
                    if (null == this.outputDirectory)
                    {
                        this.outputFile = Path.ChangeExtension(Path.GetFileName(this.inputFile), ".wxs");
                    }
                    else
                    {
                        this.outputFile = Path.Combine(this.outputDirectory, Path.ChangeExtension(Path.GetFileName(this.inputFile), ".wxs"));
                    }
                }

                if (this.showLogo)
                {
                    AppCommon.DisplayToolHeader();
                }

                if (this.showHelp)
                {
                    Console.WriteLine(DarkStrings.HelpMessage);
                    AppCommon.DisplayToolFooter();
                    return(this.messageHandler.LastErrorNumber);
                }

                foreach (string parameter in this.invalidArgs)
                {
                    this.messageHandler.Display(this, WixWarnings.UnsupportedCommandLineArgument(parameter));
                }
                this.invalidArgs = null;

                // create the decompiler and mutator
                decompiler   = new Decompiler();
                mutator      = new Mutator();
                mutator.Core = new HarvesterCore(new MessageEventHandler(this.messageHandler.Display));
                unbinder     = new Unbinder();

                // read the configuration file (dark.exe.config)
                AppCommon.ReadConfiguration(this.extensionList);

                // load any extensions
                foreach (string extension in this.extensionList)
                {
                    WixExtension wixExtension = WixExtension.Load(extension);

                    decompiler.AddExtension(wixExtension);
                    unbinder.AddExtension(wixExtension);
                }

                // set options
                decompiler.SuppressCustomTables             = this.suppressCustomTables;
                decompiler.SuppressDroppingEmptyTables      = this.suppressDroppingEmptyTables;
                decompiler.SuppressRelativeActionSequencing = this.suppressRelativeActionSequencing;
                decompiler.SuppressUI        = this.suppressUI;
                decompiler.TempFilesLocation = Environment.GetEnvironmentVariable("WIX_TEMP");
                if (!String.IsNullOrEmpty(this.exportBasePath))
                {
                    decompiler.ExportFilePath = this.exportBasePath;
                }

                unbinder.TempFilesLocation = Environment.GetEnvironmentVariable("WIX_TEMP");

                decompiler.Message += new MessageEventHandler(this.messageHandler.Display);
                unbinder.Message   += new MessageEventHandler(this.messageHandler.Display);

                // print friendly message saying what file is being decompiled
                Console.WriteLine(Path.GetFileName(this.inputFile));

                // unbind
                // TODO: passing a bundle to the decompiler without the /x parameter specified stumbles here
                //        as the exportBasePath will be null. Need a design decision whether to throw an
                //        message below or throw a message here
                Output output = unbinder.Unbind(this.inputFile, this.outputType, this.exportBasePath);

                if (null != output)
                {
                    if (OutputType.Patch == this.outputType || OutputType.Transform == this.outputType || this.outputXml)
                    {
                        output.Save(this.outputFile, null, new WixVariableResolver(), null);
                    }
                    else // decompile
                    {
                        Wix.Wix wix = decompiler.Decompile(output);

                        // output
                        if (null != wix)
                        {
                            XmlTextWriter writer = null;

                            // mutate the Wix document
                            if (!mutator.Mutate(wix))
                            {
                                return(this.messageHandler.LastErrorNumber);
                            }

                            try
                            {
                                Directory.CreateDirectory(Path.GetDirectoryName(Path.GetFullPath(this.outputFile)));

                                writer = new XmlTextWriter(this.outputFile, System.Text.Encoding.UTF8);

                                writer.Indentation = 4;
                                writer.IndentChar  = ' ';
                                writer.QuoteChar   = '"';
                                writer.Formatting  = Formatting.Indented;

                                writer.WriteStartDocument();
                                wix.OutputXml(writer);
                                writer.WriteEndDocument();
                            }
                            catch (Exception e)
                            {
                                this.messageHandler.Display(this, WixErrors.FileWriteError(this.outputFile, e.Message));
                                return(this.messageHandler.LastErrorNumber);
                            }
                            finally
                            {
                                if (null != writer)
                                {
                                    writer.Close();
                                }
                            }
                        }
                    }
                }
            }
            catch (WixException we)
            {
                this.messageHandler.Display(this, we.Error);
            }
            catch (Exception e)
            {
                this.messageHandler.Display(this, WixErrors.UnexpectedException(e.Message, e.GetType().ToString(), e.StackTrace));
                if (e is NullReferenceException || e is SEHException)
                {
                    throw;
                }
            }
            finally
            {
                if (null != decompiler)
                {
                    if (this.tidy)
                    {
                        if (!decompiler.DeleteTempFiles())
                        {
                            Console.WriteLine(DarkStrings.WAR_FailedToDeleteTempDir, decompiler.TempFilesLocation);
                        }
                    }
                    else
                    {
                        Console.WriteLine(DarkStrings.INF_TempDirLocatedAt, decompiler.TempFilesLocation);
                    }
                }

                if (null != unbinder)
                {
                    if (this.tidy)
                    {
                        if (!unbinder.DeleteTempFiles())
                        {
                            Console.WriteLine(DarkStrings.WAR_FailedToDeleteTempDir, unbinder.TempFilesLocation);
                        }
                    }
                    else
                    {
                        Console.WriteLine(DarkStrings.INF_TempDirLocatedAt, unbinder.TempFilesLocation);
                    }
                }
            }

            return(this.messageHandler.LastErrorNumber);
        }
Exemple #6
0
        /// <summary>
        /// Main running method for the application.
        /// </summary>
        /// <param name="args">Commandline arguments to the application.</param>
        /// <returns>Returns the application error code.</returns>
        private int Run(string[] args)
        {
            Microsoft.Tools.WindowsInstallerXml.Binder binder = null;
            Differ differ = null;
            Unbinder unbinder = null;

            TempFileCollection tempFileCollection = null;

            try
            {
                // parse the command line
                this.ParseCommandLine(args);

                // validate the inputs
                if (this.xmlInputs && this.adminImage)
                {
                    this.messageHandler.Display(this, WixErrors.IllegalCommandlineArgumentCombination("a", "xi"));
                    this.showHelp = true;
                }

                string[] allValidExtensions = new string[] { wixMstExtension, wixOutExtension, wixPdbExtension, msiExtension };
                string[] expectedSingleInputExtensions = new string[] { wixMstExtension, wixOutExtension };
                string[] expectedDoubleInputXmlExtensions = new string[] { wixOutExtension, wixPdbExtension };
                string[] expectedDoubleInputMsiExtensions = new string[] { msiExtension };

                // Validate that all inputs have the correct extension and we dont have too many inputs.
                if (1 == this.inputFiles.Count)
                {
                    string inputFile = this.inputFiles[0];

                    bool hasValidExtension = false;
                    foreach (string extension in expectedSingleInputExtensions)
                    {
                        if (String.Equals(Path.GetExtension(inputFile), extension, StringComparison.OrdinalIgnoreCase))
                        {
                            hasValidExtension = true;
                            break;
                        }
                    }

                    if (!hasValidExtension)
                    {
                        bool missingInput = false;

                        // Check if its using an extension that could be valid in other scenarios.
                        foreach (string validExtension in allValidExtensions)
                        {
                            if (String.Equals(Path.GetExtension(inputFile), validExtension, StringComparison.OrdinalIgnoreCase))
                            {
                                this.messageHandler.Display(this, WixErrors.WrongFileExtensionForNumberOfInputs(Path.GetExtension(inputFile), inputFile));
                                missingInput = true;
                                break;
                            }
                        }

                        if (!missingInput)
                        {
                            this.messageHandler.Display(this, WixErrors.UnexpectedFileExtension(inputFile, String.Join(", ", expectedSingleInputExtensions)));
                        }
                    }
                }
                else if (2 == this.inputFiles.Count)
                {
                    foreach (string inputFile in inputFiles)
                    {
                        bool hasValidExtension = false;
                        string[] expectedExtensions = allValidExtensions;
                        if (this.xmlInputs)
                        {
                            foreach (string extension in expectedDoubleInputXmlExtensions)
                            {
                                if (String.Equals(Path.GetExtension(inputFile), extension, StringComparison.OrdinalIgnoreCase))
                                {
                                    hasValidExtension = true;
                                    expectedExtensions = expectedDoubleInputXmlExtensions;
                                    break;
                                }
                            }
                        }
                        else
                        {
                            foreach (string extension in expectedDoubleInputMsiExtensions)
                            {
                                if (String.Equals(Path.GetExtension(inputFile), extension, StringComparison.OrdinalIgnoreCase))
                                {
                                    hasValidExtension = true;
                                    expectedExtensions = expectedDoubleInputMsiExtensions;
                                    break;
                                }
                            }
                        }

                        if (!hasValidExtension)
                        {
                            this.messageHandler.Display(this, WixErrors.UnexpectedFileExtension(inputFile, String.Join(", ", expectedExtensions)));
                        }
                    }
                }
                else
                {
                    this.showHelp = true;
                }

                // exit if there was an error parsing the command line or with a file extension (otherwise the logo appears after error messages)
                if (this.messageHandler.EncounteredError)
                {
                    return this.messageHandler.LastErrorNumber;
                }

                if (null == this.outputFile)
                {
                    this.showHelp = true;
                }

                if (this.showLogo)
                {
                    AppCommon.DisplayToolHeader();
                }

                if (this.showHelp)
                {
                    Console.WriteLine(TorchStrings.HelpMessage);
                    AppCommon.DisplayToolFooter();
                    return this.messageHandler.LastErrorNumber;
                }

                foreach (string parameter in this.invalidArgs)
                {
                    this.messageHandler.Display(this, WixWarnings.UnsupportedCommandLineArgument(parameter));
                }
                this.invalidArgs = null;

                binder = new Microsoft.Tools.WindowsInstallerXml.Binder();
                differ = new Differ();
                unbinder = new Unbinder();

                // load any extensions
                foreach (string extension in this.extensionList)
                {
                    WixExtension wixExtension = WixExtension.Load(extension);
                    unbinder.AddExtension(wixExtension);
                    binder.AddExtension(wixExtension);
                    differ.AddExtension(wixExtension);
                }

                binder.Message += new MessageEventHandler(this.messageHandler.Display);
                differ.Message += new MessageEventHandler(this.messageHandler.Display);
                unbinder.Message += new MessageEventHandler(this.messageHandler.Display);

                binder.TempFilesLocation = Environment.GetEnvironmentVariable("WIX_TEMP");
                unbinder.TempFilesLocation = Environment.GetEnvironmentVariable("WIX_TEMP");
                tempFileCollection = new TempFileCollection(Environment.GetEnvironmentVariable("WIX_TEMP"));

                binder.WixVariableResolver = new WixVariableResolver();
                differ.PreserveUnchangedRows = this.preserveUnchangedRows;
                differ.ShowPedanticMessages = this.showPedanticMessages;
                unbinder.SuppressExtractCabinets = true;
                unbinder.IsAdminImage = this.adminImage;

                if (null == this.exportBasePath)
                {
                    this.exportBasePath = tempFileCollection.BasePath;
                }

                // load and process the inputs
                Output transform;
                if (1 == this.inputFiles.Count)
                {
                    transform = Output.Load(this.inputFiles[0], false, false);
                    if (OutputType.Transform != transform.Type)
                    {
                        this.messageHandler.Display(this, WixErrors.InvalidWixTransform(this.inputFiles[0]));
                        return this.messageHandler.LastErrorNumber;
                    }
                }
                else // 2 inputs
                {
                    Output targetOutput;
                    Output updatedOutput;

                    if (this.xmlInputs)
                    {
                        // load the target database
                        if (String.Equals(Path.GetExtension(inputFiles[0]), wixPdbExtension, StringComparison.OrdinalIgnoreCase))
                        {
                            Pdb targetPdb = Pdb.Load(this.inputFiles[0], false, false);
                            targetOutput = targetPdb.Output;
                        }
                        else
                        {
                            targetOutput = Output.Load(this.inputFiles[0], false, false);
                        }

                        // load the updated database
                        if (String.Equals(Path.GetExtension(inputFiles[1]), wixPdbExtension, StringComparison.OrdinalIgnoreCase))
                        {
                            Pdb updatedPdb = Pdb.Load(this.inputFiles[1], false, false);
                            updatedOutput = updatedPdb.Output;
                        }
                        else
                        {
                            updatedOutput = Output.Load(this.inputFiles[1], false, false);
                        }

                        this.xmlOutput = true;
                    }
                    else
                    {
                        // load the target database
                        targetOutput = unbinder.Unbind(this.inputFiles[0], OutputType.Product, Path.Combine(this.exportBasePath, "targetBinaries"));

                        // load the updated database
                        updatedOutput = unbinder.Unbind(this.inputFiles[1], OutputType.Product, Path.Combine(this.exportBasePath, "updatedBinaries"));
                    }

                    // diff the target and updated databases
                    transform = differ.Diff(targetOutput, updatedOutput, this.validationFlags);

                    if (null == transform.Tables || 0 >= transform.Tables.Count)
                    {
                        throw new WixException(WixErrors.NoDifferencesInTransform(transform.SourceLineNumbers));
                    }
                }

                // output the transform
                if (null != transform)
                {
                    // If either the user selected xml output or gave xml input, save as xml output.
                    // With xml inputs, many funtions of the binder have not been performed on the inputs (ie. file sequencing). This results in bad IDT files which cannot be put in a transform.
                    if (this.xmlOutput)
                    {
                        transform.Save(this.outputFile, null, null, tempFileCollection.BasePath);
                    }
                    else
                    {
                        binder.Bind(transform, this.outputFile);
                    }
                }
            }
            catch (WixException we)
            {
                if (we is WixInvalidIdtException)
                {
                    // make sure the IDT files stay around
                    this.tidy = false;
                }

                this.messageHandler.Display(this, we.Error);
            }
            catch (Exception e)
            {
                // make sure the files stay around for debugging
                this.tidy = false;

                this.messageHandler.Display(this, WixErrors.UnexpectedException(e.Message, e.GetType().ToString(), e.StackTrace));
                if (e is NullReferenceException || e is SEHException)
                {
                    throw;
                }
            }
            finally
            {
                if (null != binder)
                {
                    if (this.tidy)
                    {
                        if (!binder.DeleteTempFiles())
                        {
                            Console.WriteLine(TorchStrings.WAR_FailedToDeleteTempDir, binder.TempFilesLocation);
                        }
                    }
                    else
                    {
                        Console.WriteLine(TorchStrings.INF_BinderTempDirLocatedAt, binder.TempFilesLocation);
                    }
                }

                if (null != unbinder)
                {
                    if (this.tidy)
                    {
                        if (!unbinder.DeleteTempFiles())
                        {
                            Console.WriteLine(TorchStrings.WAR_FailedToDeleteTempDir, binder.TempFilesLocation);
                        }
                    }
                    else
                    {
                        Console.WriteLine(TorchStrings.INF_UnbinderTempDirLocatedAt, binder.TempFilesLocation);
                    }
                }

                if (null != tempFileCollection)
                {
                    if (this.tidy)
                    {
                        try
                        {
                            Directory.Delete(tempFileCollection.BasePath, true);
                        }
                        catch (DirectoryNotFoundException)
                        {
                            // if the path doesn't exist, then there is nothing for us to worry about
                        }
                        catch
                        {
                            Console.WriteLine(TorchStrings.WAR_FailedToDeleteTempDir, tempFileCollection.BasePath);
                        }
                    }
                    else
                    {
                        Console.WriteLine(TorchStrings.INF_TorchTempDirLocatedAt, tempFileCollection.BasePath);
                    }
                }
            }

            return this.messageHandler.LastErrorNumber;
        }
Exemple #7
0
        /// <summary>
        /// Extracts files from a merge module and creates corresponding ComponentGroup WiX authoring.
        /// </summary>
        private void MeltModule()
        {
            Decompiler decompiler = null;
            Unbinder   unbinder   = null;
            Melter     melter     = null;

            try
            {
                // create the decompiler, unbinder, and melter
                decompiler = new Decompiler();
                unbinder   = new Unbinder();
                melter     = new Melter(decompiler, id);

                // read the configuration file (melt.exe.config)
                AppCommon.ReadConfiguration(this.extensionList);

                // load all extensions
                ExtensionManager extensionManager = new ExtensionManager();
                foreach (string extension in this.extensionList)
                {
                    extensionManager.Load(extension);
                }

                foreach (IDecompilerExtension extension in extensionManager.Create <IDecompilerExtension>())
                {
                    decompiler.AddExtension(extension);
                }

                foreach (IUnbinderExtension extension in extensionManager.Create <IUnbinderExtension>())
                {
                    unbinder.AddExtension(extension);
                }

                // set options
                decompiler.TempFilesLocation = Environment.GetEnvironmentVariable("WIX_TEMP");

                unbinder.TempFilesLocation        = Environment.GetEnvironmentVariable("WIX_TEMP");
                unbinder.SuppressDemodularization = true;

                // print friendly message saying what file is being decompiled
                Console.WriteLine(Path.GetFileName(this.inputFile));

                // unbind
                Output output = unbinder.Unbind(this.inputFile, this.outputType, this.exportBasePath);

                if (null != output)
                {
                    Wix.Wix wix = melter.Melt(output);
                    if (null != wix)
                    {
                        XmlTextWriter writer = null;

                        try
                        {
                            writer = new XmlTextWriter(this.outputFile, System.Text.Encoding.UTF8);

                            writer.Indentation = 4;
                            writer.IndentChar  = ' ';
                            writer.QuoteChar   = '"';
                            writer.Formatting  = Formatting.Indented;

                            writer.WriteStartDocument();
                            wix.OutputXml(writer);
                            writer.WriteEndDocument();
                        }
                        finally
                        {
                            if (null != writer)
                            {
                                writer.Close();
                            }
                        }
                    }
                }
            }
            finally
            {
                if (null != decompiler)
                {
                    if (this.tidy)
                    {
                        if (!decompiler.DeleteTempFiles())
                        {
                            Console.WriteLine(MeltStrings.WAR_FailedToDeleteTempDir, decompiler.TempFilesLocation);
                        }
                    }
                    else
                    {
                        Console.WriteLine(MeltStrings.INF_TempDirLocatedAt, decompiler.TempFilesLocation);
                    }
                }

                if (null != unbinder)
                {
                    if (this.tidy)
                    {
                        if (!unbinder.DeleteTempFiles())
                        {
                            Console.WriteLine(MeltStrings.WAR_FailedToDeleteTempDir, unbinder.TempFilesLocation);
                        }
                    }
                    else
                    {
                        Console.WriteLine(MeltStrings.INF_TempDirLocatedAt, unbinder.TempFilesLocation);
                    }
                }
            }
        }
Exemple #8
0
        /// <summary>
        /// Main running method for the application.
        /// </summary>
        /// <param name="args">Commandline arguments to the application.</param>
        /// <returns>Returns the application error code.</returns>
        private int Run(string[] args)
        {
            Decompiler decompiler = null;
            Mutator mutator = null;
            Unbinder unbinder = null;

            try
            {
                // parse the command line
                this.ParseCommandLine(args);

                // exit if there was an error parsing the command line (otherwise the logo appears after error messages)
                if (this.messageHandler.EncounteredError)
                {
                    return this.messageHandler.LastErrorNumber;
                }

                if (null == this.inputFile)
                {
                    this.showHelp = true;
                }
                else if (null == this.outputFile)
                {
                    if (null == this.outputDirectory)
                    {
                        this.outputFile = Path.ChangeExtension(Path.GetFileName(this.inputFile), ".wxs");
                    }
                    else
                    {
                        this.outputFile = Path.Combine(this.outputDirectory, Path.ChangeExtension(Path.GetFileName(this.inputFile), ".wxs"));
                    }
                }

                if (this.showLogo)
                {
                    AppCommon.DisplayToolHeader();
                }

                if (this.showHelp)
                {
                    Console.WriteLine(DarkStrings.HelpMessage);
                    AppCommon.DisplayToolFooter();
                    return this.messageHandler.LastErrorNumber;
                }

                foreach (string parameter in this.invalidArgs)
                {
                    this.messageHandler.Display(this, WixWarnings.UnsupportedCommandLineArgument(parameter));
                }
                this.invalidArgs = null;

                // create the decompiler and mutator
                decompiler = new Decompiler();
                mutator = new Mutator();
                mutator.Core = new HarvesterCore(new MessageEventHandler(this.messageHandler.Display));
                unbinder = new Unbinder();

                // read the configuration file (dark.exe.config)
                AppCommon.ReadConfiguration(this.extensionList);

                // load any extensions
                foreach (string extension in this.extensionList)
                {
                    WixExtension wixExtension = WixExtension.Load(extension);

                    decompiler.AddExtension(wixExtension);
                    unbinder.AddExtension(wixExtension);
                }

                // set options
                decompiler.SuppressCustomTables = this.suppressCustomTables;
                decompiler.SuppressDroppingEmptyTables = this.suppressDroppingEmptyTables;
                decompiler.SuppressRelativeActionSequencing = this.suppressRelativeActionSequencing;
                decompiler.SuppressUI = this.suppressUI;
                decompiler.TempFilesLocation = Environment.GetEnvironmentVariable("WIX_TEMP");
                if (!String.IsNullOrEmpty(this.exportBasePath))
                {
                    decompiler.ExportFilePath = this.exportBasePath;
                }

                unbinder.TempFilesLocation = Environment.GetEnvironmentVariable("WIX_TEMP");

                decompiler.Message += new MessageEventHandler(this.messageHandler.Display);
                unbinder.Message += new MessageEventHandler(this.messageHandler.Display);

                // print friendly message saying what file is being decompiled
                Console.WriteLine(Path.GetFileName(this.inputFile));

                // unbind
                // TODO: passing a bundle to the decompiler without the /x parameter specified stumbles here
                //        as the exportBasePath will be null. Need a design decision whether to throw an 
                //        message below or throw a message here
                Output output = unbinder.Unbind(this.inputFile, this.outputType, this.exportBasePath);
                
                if (null != output)
                {
                    if (OutputType.Patch == this.outputType || OutputType.Transform == this.outputType || this.outputXml)
                    {
                        output.Save(this.outputFile, null, new WixVariableResolver(), null);
                    }
                    else // decompile
                    {
                        Wix.Wix wix = decompiler.Decompile(output);

                        // output
                        if (null != wix)
                        {
                            XmlTextWriter writer = null;

                            // mutate the Wix document
                            if (!mutator.Mutate(wix))
                            {
                                return this.messageHandler.LastErrorNumber;
                            }

                            try
                            {
                                Directory.CreateDirectory(Path.GetDirectoryName(Path.GetFullPath(this.outputFile)));

                                writer = new XmlTextWriter(this.outputFile, System.Text.Encoding.UTF8);

                                writer.Indentation = 4;
                                writer.IndentChar = ' ';
                                writer.QuoteChar = '"';
                                writer.Formatting = Formatting.Indented;

                                writer.WriteStartDocument();
                                wix.OutputXml(writer);
                                writer.WriteEndDocument();
                            }
                            catch (Exception e)
                            {
                                this.messageHandler.Display(this, WixErrors.FileWriteError(this.outputFile, e.Message));
                                return this.messageHandler.LastErrorNumber;
                            }
                            finally
                            {
                                if (null != writer)
                                {
                                    writer.Close();
                                }
                            }
                        }
                    }
                }
            }
            catch (WixException we)
            {
                this.messageHandler.Display(this, we.Error);
            }
            catch (Exception e)
            {
                this.messageHandler.Display(this, WixErrors.UnexpectedException(e.Message, e.GetType().ToString(), e.StackTrace));
                if (e is NullReferenceException || e is SEHException)
                {
                    throw;
                }
            }
            finally
            {
                if (null != decompiler)
                {
                    if (this.tidy)
                    {
                        if (!decompiler.DeleteTempFiles())
                        {
                            Console.WriteLine(DarkStrings.WAR_FailedToDeleteTempDir, decompiler.TempFilesLocation);
                        }
                    }
                    else
                    {
                        Console.WriteLine(DarkStrings.INF_TempDirLocatedAt, decompiler.TempFilesLocation);
                    }
                }

                if (null != unbinder)
                {
                    if (this.tidy)
                    {
                        if (!unbinder.DeleteTempFiles())
                        {
                            Console.WriteLine(DarkStrings.WAR_FailedToDeleteTempDir, unbinder.TempFilesLocation);
                        }
                    }
                    else
                    {
                        Console.WriteLine(DarkStrings.INF_TempDirLocatedAt, unbinder.TempFilesLocation);
                    }
                }
            }

            return this.messageHandler.LastErrorNumber;
        }
Exemple #9
0
        /// <summary>
        /// Compare two result files.
        /// </summary>
        /// <param name="expectedResult">The expected result file.</param>
        /// <param name="actualResult">The actual result file.</param>
        /// <returns>Any differences found.</returns>
        public static ArrayList CompareResults(string expectedResult, string actualResult)
        {
            ArrayList differences = new ArrayList();
            Output    targetOutput;
            Output    updatedOutput;

            OutputType outputType;
            string     extension = Path.GetExtension(expectedResult);

            if (String.Compare(extension, ".msi", true, CultureInfo.InvariantCulture) == 0)
            {
                outputType = OutputType.Product;
            }
            else if (String.Compare(extension, ".msm", true, CultureInfo.InvariantCulture) == 0)
            {
                outputType = OutputType.Module;
            }
            else if (String.Compare(extension, ".msp", true, CultureInfo.InvariantCulture) == 0)
            {
                outputType = OutputType.Patch;
            }
            else if (String.Compare(extension, ".mst", true, CultureInfo.InvariantCulture) == 0)
            {
                outputType = OutputType.Transform;
            }
            else if (String.Compare(extension, ".pcp", true, CultureInfo.InvariantCulture) == 0)
            {
                outputType = OutputType.PatchCreation;
            }
            else if (String.Compare(extension, ".wixout", true, CultureInfo.InvariantCulture) == 0)
            {
                outputType = OutputType.Unknown;
            }
            else
            {
                throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Cannot determine the type of msi database file based on file extension '{0}'.", extension));
            }

            if (outputType != OutputType.Unknown)
            {
                Unbinder unbinder = new Unbinder();
                unbinder.SuppressDemodularization = true;

                targetOutput  = unbinder.Unbind(expectedResult, outputType, null);
                updatedOutput = unbinder.Unbind(actualResult, outputType, null);
            }
            else
            {
                targetOutput  = Output.Load(expectedResult, false, false);
                updatedOutput = Output.Load(actualResult, false, false);
            }

            Differ differ = new Differ();

            differ.SuppressKeepingSpecialRows = true;
            Output transform = differ.Diff(targetOutput, updatedOutput);

            foreach (Table table in transform.Tables)
            {
                switch (table.Operation)
                {
                case TableOperation.Add:
                    differences.Add(String.Format(CultureInfo.InvariantCulture, "The {0} table has been added.", table.Name));
                    break;

                case TableOperation.Drop:
                    differences.Add(String.Format(CultureInfo.InvariantCulture, "The {0} table has been dropped.", table.Name));
                    continue;
                }

                // index the target rows for better error messages
                Hashtable targetRows  = new Hashtable();
                Table     targetTable = targetOutput.Tables[table.Name];
                if (null != targetTable)
                {
                    foreach (Row row in targetTable.Rows)
                    {
                        string primaryKey = row.GetPrimaryKey('/');

                        // only index rows with primary keys since these are the ones that can be modified
                        if (null != primaryKey)
                        {
                            targetRows.Add(primaryKey, row);
                        }
                    }
                }

                foreach (Row row in table.Rows)
                {
                    switch (row.Operation)
                    {
                    case RowOperation.Add:
                        differences.Add(String.Format(CultureInfo.InvariantCulture, "The {0} table, row '{1}' has been added.", table.Name, row.ToString()));
                        break;

                    case RowOperation.Delete:
                        differences.Add(String.Format(CultureInfo.InvariantCulture, "The {0} table, row '{1}' has been deleted.", table.Name, row.ToString()));
                        break;

                    case RowOperation.Modify:
                        if (("_SummaryInformation" != table.Name || (9 != (int)row[0] && 12 != (int)row[0] && 13 != (int)row[0] && 18 != (int)row[0])) &&
                            ("Property" != table.Name || "ProductCode" != (string)row[0]))
                        {
                            string primaryKey = row.GetPrimaryKey('/');
                            Row    targetRow  = (Row)targetRows[primaryKey];

                            differences.Add(String.Format(CultureInfo.InvariantCulture, "The {0} table, row '{1}' has changed to '{2}'.", table.Name, targetRow.ToString(), row.ToString()));
                        }
                        break;

                    default:
                        throw new InvalidOperationException("Unknown diff row.");
                    }
                }
            }

            // add a description of the files being compared
            if (0 < differences.Count)
            {
                differences.Insert(0, "Differences found while comparing:");
                differences.Insert(1, expectedResult);
                differences.Insert(2, actualResult);
            }

            return(differences);
        }
Exemple #10
0
        /// <summary>
        /// Main running method for the application.
        /// </summary>
        /// <param name="args">Commandline arguments to the application.</param>
        /// <returns>Returns the application error code.</returns>
        private int Run(string[] args)
        {
            Decompiler decompiler = null;
            Mutator    mutator    = null;
            Unbinder   unbinder   = null;

            try
            {
                // parse the command line
                this.ParseCommandLine(args);

                // exit if there was an error parsing the command line (otherwise the logo appears after error messages)
                if (this.messageHandler.EncounteredError)
                {
                    return(this.messageHandler.LastErrorNumber);
                }

                if (null == this.inputFile || null == this.outputFile)
                {
                    this.showHelp = true;
                }

                if (this.showLogo)
                {
                    Assembly darkAssembly = Assembly.GetExecutingAssembly();

                    Console.WriteLine("Microsoft (R) Windows Installer Xml Decompiler Version {0}", darkAssembly.GetName().Version.ToString());
                    Console.WriteLine("Copyright (C) Microsoft Corporation 2003. All rights reserved.\n");
                    Console.WriteLine();
                }

                if (this.showHelp)
                {
                    Console.WriteLine(" usage: dark.exe [-?] [-nologo] database.msi source.wxs");
                    Console.WriteLine();
                    Console.WriteLine("   -ext       extension assembly or \"class, assembly\"");
                    Console.WriteLine("   -nologo    skip printing dark logo information");
                    Console.WriteLine("   -notidy    do not delete temporary files (useful for debugging)");
                    Console.WriteLine("   -sdet      suppress dropping empty tables (adds EnsureTable as appropriate)");
                    Console.WriteLine("   -sras      suppress relative action sequencing (use explicit sequence numbers)");
                    Console.WriteLine("   -sui       suppress decompiling UI-related tables");
                    Console.WriteLine("   -sw<N>     suppress warning with specific message ID");
                    Console.WriteLine("   -v         verbose output");
                    Console.WriteLine("   -wx        treat warnings as errors");
                    Console.WriteLine("   -x <path>  export binaries from cabinets and embedded binaries to the provided path");
                    Console.WriteLine("   -xo        output xml instead of WiX source code (mandatory for transforms and patches)");
                    Console.WriteLine("   -?         this help information");
                    Console.WriteLine();
                    Console.WriteLine("Environment variables:");
                    Console.WriteLine("   WIX_TEMP   overrides the temporary directory used for cab extraction, binary extraction, ...");
                    Console.WriteLine();
                    Console.WriteLine("Common extensions:");
                    Console.WriteLine("   .wxi    - Windows installer Xml Include file");
                    Console.WriteLine("   .wxl    - Windows installer Xml Localization file");
                    Console.WriteLine("   .wxs    - Windows installer Xml Source file");
                    Console.WriteLine("   .wixlib - Windows installer Xml Library file (in XML format)");
                    Console.WriteLine("   .wixobj - Windows installer Xml Object file (in XML format)");
                    Console.WriteLine("   .wixout - Windows installer Xml Output file (in XML format)");
                    Console.WriteLine();
                    Console.WriteLine("   .msi - Windows installer Product Database");
                    Console.WriteLine("   .msm - Windows installer Merge Module");
                    Console.WriteLine("   .msp - Windows installer Patch");
                    Console.WriteLine("   .mst - Windows installer Transform");
                    Console.WriteLine("   .pcp - Windows installer Patch Creation Package");
                    Console.WriteLine();
                    Console.WriteLine("For more information see: http://wix.sourceforge.net");

                    return(this.messageHandler.LastErrorNumber);
                }

                // create the decompiler and mutator
                decompiler = new Decompiler();
                mutator    = new Mutator();
                unbinder   = new Unbinder();

                // read the configuration file (dark.exe.config)
                AppCommon.ReadConfiguration(this.extensionList);

                // load any extensions
                foreach (string extension in this.extensionList)
                {
                    WixExtension wixExtension = WixExtension.Load(extension);

                    decompiler.AddExtension(wixExtension);
                    unbinder.AddExtension(wixExtension);
                }

                // set options
                decompiler.SuppressDroppingEmptyTables      = this.suppressDroppingEmptyTables;
                decompiler.SuppressRelativeActionSequencing = this.suppressRelativeActionSequencing;
                decompiler.SuppressUI        = this.suppressUI;
                decompiler.TempFilesLocation = Environment.GetEnvironmentVariable("WIX_TEMP");

                unbinder.TempFilesLocation = Environment.GetEnvironmentVariable("WIX_TEMP");

                decompiler.Message += new MessageEventHandler(this.messageHandler.Display);
                mutator.Message    += new MessageEventHandler(this.messageHandler.Display);
                unbinder.Message   += new MessageEventHandler(this.messageHandler.Display);

                // print friendly message saying what file is being decompiled
                Console.WriteLine(Path.GetFileName(this.inputFile));

                // unbind
                Output output = unbinder.Unbind(this.inputFile, this.outputType, this.exportBasePath);

                if (null != output)
                {
                    if (OutputType.Patch == this.outputType || OutputType.Transform == this.outputType || this.outputXml)
                    {
                        output.Save(this.outputFile, null, new WixVariableResolver(), null);
                    }
                    else // decompile
                    {
                        Wix.Wix wix = decompiler.Decompile(output);

                        // output
                        if (null != wix)
                        {
                            XmlTextWriter writer = null;

                            // mutate the Wix document
                            if (!mutator.Mutate(wix))
                            {
                                return(this.messageHandler.LastErrorNumber);
                            }

                            try
                            {
                                writer = new XmlTextWriter(this.outputFile, System.Text.Encoding.UTF8);

                                writer.Indentation = 4;
                                writer.IndentChar  = ' ';
                                writer.QuoteChar   = '"';
                                writer.Formatting  = Formatting.Indented;

                                writer.WriteStartDocument();
                                wix.OutputXml(writer);
                                writer.WriteEndDocument();
                            }
                            finally
                            {
                                if (null != writer)
                                {
                                    writer.Close();
                                }
                            }
                        }
                    }
                }
            }
            catch (WixException we)
            {
                this.messageHandler.Display(this, we.Error);
            }
            catch (Exception e)
            {
                this.messageHandler.Display(this, WixErrors.UnexpectedException(e.Message, e.GetType().ToString(), e.StackTrace));
                if (e is NullReferenceException || e is SEHException)
                {
                    throw;
                }
            }
            finally
            {
                if (null != decompiler)
                {
                    if (this.tidy)
                    {
                        if (!decompiler.DeleteTempFiles())
                        {
                            Console.WriteLine("Warning, failed to delete temporary directory: {0}", decompiler.TempFilesLocation);
                        }
                    }
                    else
                    {
                        Console.WriteLine("Temporary directory located at '{0}'.", decompiler.TempFilesLocation);
                    }
                }

                if (null != unbinder)
                {
                    if (this.tidy)
                    {
                        if (!unbinder.DeleteTempFiles())
                        {
                            Console.WriteLine("Warning, failed to delete temporary directory: {0}", unbinder.TempFilesLocation);
                        }
                    }
                    else
                    {
                        Console.WriteLine("Temporary directory located at '{0}'.", unbinder.TempFilesLocation);
                    }
                }
            }

            return(this.messageHandler.LastErrorNumber);
        }
Exemple #11
0
        /// <summary>
        /// Extracts files from a merge module and creates corresponding ComponentGroup WiX authoring.
        /// </summary>
        private void MeltModule()
        {
            Decompiler decompiler = null;
            Unbinder unbinder = null;
            Melter melter = null;

            try
            {
                // create the decompiler, unbinder, and melter
                decompiler = new Decompiler();
                unbinder = new Unbinder();
                melter = new Melter(decompiler, id);

                // read the configuration file (melt.exe.config)
                AppCommon.ReadConfiguration(this.extensionList);

                // load any extensions
                foreach (string extension in this.extensionList)
                {
                    WixExtension wixExtension = WixExtension.Load(extension);

                    decompiler.AddExtension(wixExtension);
                    unbinder.AddExtension(wixExtension);
                }

                // set options
                decompiler.TempFilesLocation = Environment.GetEnvironmentVariable("WIX_TEMP");

                unbinder.TempFilesLocation = Environment.GetEnvironmentVariable("WIX_TEMP");
                unbinder.SuppressDemodularization = true;

                decompiler.Message += new MessageEventHandler(this.messageHandler.Display);
                unbinder.Message += new MessageEventHandler(this.messageHandler.Display);
                melter.Message += new MessageEventHandler(this.messageHandler.Display);

                // print friendly message saying what file is being decompiled
                Console.WriteLine(Path.GetFileName(this.inputFile));

                // unbind
                Output output = unbinder.Unbind(this.inputFile, this.outputType, this.exportBasePath);

                if (null != output)
                {
                    Wix.Wix wix = melter.Melt(output);
                    if (null != wix)
                    {
                        XmlTextWriter writer = null;

                        try
                        {
                            writer = new XmlTextWriter(this.outputFile, System.Text.Encoding.UTF8);

                            writer.Indentation = 4;
                            writer.IndentChar = ' ';
                            writer.QuoteChar = '"';
                            writer.Formatting = Formatting.Indented;

                            writer.WriteStartDocument();
                            wix.OutputXml(writer);
                            writer.WriteEndDocument();
                        }
                        finally
                        {
                            if (null != writer)
                            {
                                writer.Close();
                            }
                        }
                    }
                }
            }
            finally
            {
                if (null != decompiler)
                {
                    if (this.tidy)
                    {
                        if (!decompiler.DeleteTempFiles())
                        {
                            Console.WriteLine(MeltStrings.WAR_FailedToDeleteTempDir, decompiler.TempFilesLocation);
                        }
                    }
                    else
                    {
                        Console.WriteLine(MeltStrings.INF_TempDirLocatedAt, decompiler.TempFilesLocation);
                    }
                }

                if (null != unbinder)
                {
                    if (this.tidy)
                    {
                        if (!unbinder.DeleteTempFiles())
                        {
                            Console.WriteLine(MeltStrings.WAR_FailedToDeleteTempDir, unbinder.TempFilesLocation);
                        }
                    }
                    else
                    {
                        Console.WriteLine(MeltStrings.INF_TempDirLocatedAt, unbinder.TempFilesLocation);
                    }
                }
            }
        }
Exemple #12
0
        /// <summary>
        /// Main running method for the application.
        /// </summary>
        /// <param name="args">Commandline arguments to the application.</param>
        /// <returns>Returns the application error code.</returns>
        private int Run(string[] args)
        {
            Microsoft.Tools.WindowsInstallerXml.Binder binder = null;
            Differ   differ   = null;
            Unbinder unbinder = null;

            TempFileCollection tempFileCollection = null;

            try
            {
                // parse the command line
                this.ParseCommandLine(args);

                // exit if there was an error parsing the command line (otherwise the logo appears after error messages)
                if (this.messageHandler.EncounteredError)
                {
                    return(this.messageHandler.LastErrorNumber);
                }

                // validate the inputs
                if (1 == this.inputFiles.Count)
                {
                    // Validate that if its a single input, it is a wixout to be converted to an mst.
                    if (0 != String.Compare(Path.GetExtension(this.inputFiles[0]), ".wixout", true, CultureInfo.InvariantCulture))
                    {
                        this.showHelp = true;
                    }
                }
                else if (2 == this.inputFiles.Count)
                {
                    string expectedExtension = ".msi";
                    if (this.xmlInputs)
                    {
                        expectedExtension = ".wixout";
                    }

                    // Validate that all inputs have the correct extension
                    foreach (string inputFile in inputFiles)
                    {
                        if (0 != String.Compare(Path.GetExtension(inputFile), expectedExtension, true, CultureInfo.InvariantCulture))
                        {
                            this.messageHandler.Display(this, WixErrors.UnexpectedFileExtension(this.inputFiles[0], expectedExtension));
                            this.showHelp = true;
                        }
                    }
                }
                else
                {
                    this.showHelp = true;
                }

                if (null == this.outputFile)
                {
                    this.showHelp = true;
                }

                if (this.showLogo)
                {
                    Assembly torchAssembly = Assembly.GetExecutingAssembly();

                    Console.WriteLine("Microsoft (R) Windows Installer Xml Transform Builder Version {0}", torchAssembly.GetName().Version.ToString());
                    Console.WriteLine("Copyright (C) Microsoft Corporation 2003. All rights reserved.\n");
                    Console.WriteLine();
                }

                if (this.showHelp)
                {
                    Console.WriteLine(" usage: torch.exe [-?] [options] targetInput updatedInput -out outputFile");
                    Console.WriteLine();
                    Console.WriteLine("   -nologo    skip printing logo information");
                    Console.WriteLine("   -notidy    do not delete temporary files (useful for debugging)");
                    Console.WriteLine("   -p         preserve unmodified content in the output");
                    Console.WriteLine("   -sw<N>     suppress warning with specific message ID");
                    Console.WriteLine("   -v         verbose output");
                    Console.WriteLine("   -wx        treat warnings as errors");
                    Console.WriteLine("   -xi        input xml instead of MSI format");
                    Console.WriteLine("   -xo        output xml instead of MST format (set by default if -xi is present");
                    Console.WriteLine("   -?         this help information");
                    Console.WriteLine();
                    Console.WriteLine("Environment variables:");
                    Console.WriteLine("   WIX_TEMP   overrides the temporary directory used for cab extraction, binary extraction, ...");
                    Console.WriteLine();
                    Console.WriteLine("Common extensions:");
                    Console.WriteLine("   .wxi    - Windows installer Xml Include file");
                    Console.WriteLine("   .wxl    - Windows installer Xml Localization file");
                    Console.WriteLine("   .wxs    - Windows installer Xml Source file");
                    Console.WriteLine("   .wixlib - Windows installer Xml Library file (in XML format)");
                    Console.WriteLine("   .wixobj - Windows installer Xml Object file (in XML format)");
                    Console.WriteLine("   .wixout - Windows installer Xml Output file (in XML format)");
                    Console.WriteLine();
                    Console.WriteLine("   .msi - Windows installer Product Database");
                    Console.WriteLine("   .msm - Windows installer Merge Module");
                    Console.WriteLine("   .msp - Windows installer Patch");
                    Console.WriteLine("   .mst - Windows installer Transform");
                    Console.WriteLine("   .pcp - Windows installer Patch Creation Package");
                    Console.WriteLine();
                    Console.WriteLine("For more information see: http://wix.sourceforge.net");

                    return(this.messageHandler.LastErrorNumber);
                }

                binder   = new Microsoft.Tools.WindowsInstallerXml.Binder();
                differ   = new Differ();
                unbinder = new Unbinder();

                binder.Message   += new MessageEventHandler(this.messageHandler.Display);
                differ.Message   += new MessageEventHandler(this.messageHandler.Display);
                unbinder.Message += new MessageEventHandler(this.messageHandler.Display);

                binder.TempFilesLocation   = Environment.GetEnvironmentVariable("WIX_TEMP");
                unbinder.TempFilesLocation = Environment.GetEnvironmentVariable("WIX_TEMP");
                tempFileCollection         = new TempFileCollection(Environment.GetEnvironmentVariable("WIX_TEMP"));

                binder.WixVariableResolver       = new WixVariableResolver();
                differ.PreserveUnchangedRows     = this.preserveUnchangedRows;
                unbinder.SuppressExtractCabinets = true;

                // load and process the inputs
                Output transform;
                if (1 == this.inputFiles.Count)
                {
                    transform = Output.Load(this.inputFiles[0], false, false);
                    if (OutputType.Transform != transform.Type)
                    {
                        this.messageHandler.Display(this, WixErrors.InvalidWixTransform(this.inputFiles[0]));
                        return(this.messageHandler.LastErrorNumber);
                    }
                }
                else // 2 inputs
                {
                    Output targetOutput;
                    Output updatedOutput;

                    if (this.xmlInputs)
                    {
                        // load the target database
                        targetOutput = Output.Load(this.inputFiles[0], false, false);

                        // load the updated database
                        updatedOutput = Output.Load(this.inputFiles[1], false, false);
                    }
                    else
                    {
                        // load the target database
                        targetOutput = unbinder.Unbind(this.inputFiles[0], OutputType.Product, Path.Combine(tempFileCollection.BasePath, "targetBinaries"));

                        // load the updated database
                        updatedOutput = unbinder.Unbind(this.inputFiles[1], OutputType.Product, Path.Combine(tempFileCollection.BasePath, "updatedBinaries"));
                    }

                    // diff the target and updated databases
                    transform = differ.Diff(targetOutput, updatedOutput);

                    if (null == transform.Tables || 0 >= transform.Tables.Count)
                    {
                        throw new WixException(WixErrors.NoDifferencesInTransform(transform.SourceLineNumbers));
                    }
                }

                // output the transform
                if (null != transform)
                {
                    // If either the user selected xml output or gave xml input, save as xml output.
                    // With xml inputs, many funtions of the binder have not been performed on the inputs (ie. file sequencing). This results in bad IDT files which cannot be put in a transform.
                    if (this.xmlOutput || this.xmlInputs)
                    {
                        transform.Save(this.outputFile, null, null, null);
                    }
                    else
                    {
                        binder.Bind(transform, this.outputFile);
                    }
                }
            }
            catch (WixException we)
            {
                if (we is WixInvalidIdtException)
                {
                    // make sure the IDT files stay around
                    this.tidy = false;
                }

                this.messageHandler.Display(this, we.Error);
            }
            catch (Exception e)
            {
                // make sure the files stay around for debugging
                this.tidy = false;

                this.messageHandler.Display(this, WixErrors.UnexpectedException(e.Message, e.GetType().ToString(), e.StackTrace));
                if (e is NullReferenceException || e is SEHException)
                {
                    throw;
                }
            }
            finally
            {
                if (null != binder)
                {
                    if (this.tidy)
                    {
                        if (!binder.DeleteTempFiles())
                        {
                            Console.WriteLine("Warning, failed to delete temporary directory: {0}", binder.TempFilesLocation);
                        }
                    }
                    else
                    {
                        Console.WriteLine("Binder temporary directory located at '{0}'.", binder.TempFilesLocation);
                    }
                }

                if (null != unbinder)
                {
                    if (this.tidy)
                    {
                        if (!unbinder.DeleteTempFiles())
                        {
                            Console.WriteLine("Warning, failed to delete temporary directory: {0}", binder.TempFilesLocation);
                        }
                    }
                    else
                    {
                        Console.WriteLine("Unbinder temporary directory located at '{0}'.", binder.TempFilesLocation);
                    }
                }

                if (null != tempFileCollection)
                {
                    if (this.tidy)
                    {
                        try
                        {
                            Directory.Delete(tempFileCollection.BasePath, true);
                        }
                        catch
                        {
                            Console.WriteLine("Warning, failed to delete temporary directory: {0}", tempFileCollection.BasePath);
                        }
                    }
                    else
                    {
                        Console.WriteLine("Torch temporary directory located at '{0}'.", tempFileCollection.BasePath);
                    }
                }
            }

            return(this.messageHandler.LastErrorNumber);
        }