public void Execute()
        {
            var directories  = this.Section.Symbols.OfType <DirectorySymbol>().ToList();
            var directoryIds = new SortedSet <string>(directories.Select(d => d.Id.Id));

            foreach (var directory in directories)
            {
                var parentDirectoryId = directory.ParentDirectoryRef;

                if (String.IsNullOrEmpty(parentDirectoryId))
                {
                    if (directory.Id.Id != "TARGETDIR")
                    {
                        directory.ParentDirectoryRef = "TARGETDIR";
                    }
                }
                else
                {
                    this.EnsureStandardDirectoryAdded(directoryIds, parentDirectoryId, directory.SourceLineNumbers);
                }
            }

            if (!directoryIds.Contains("TARGETDIR") && WindowsInstallerStandard.TryGetStandardDirectory("TARGETDIR", out var targetDir))
            {
                directoryIds.Add(targetDir.Id.Id);
                this.Section.AddSymbol(targetDir);
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Adds the PatchFiles action to the sequence table if it does not already exist.
        /// </summary>
        /// <param name="table">The sequence table to check or modify.</param>
        /// <param name="mainTransform">The primary authoring transform.</param>
        /// <param name="pairedTransform">The secondary patch transform.</param>
        /// <param name="mainFileRow">The file row that contains information about the patched file.</param>
        private void AddPatchFilesActionToSequenceTable(SequenceTable table, Output mainTransform, Output pairedTransform, Row mainFileRow)
        {
            // Find/add PatchFiles action (also determine sequence for it).
            // Search mainTransform first, then pairedTransform (pairedTransform overrides).
            bool   hasPatchFilesAction = false;
            int    seqInstallFiles     = 0;
            int    seqDuplicateFiles   = 0;
            string tableName           = table.ToString();

            TestSequenceTableForPatchFilesAction(
                mainTransform.Tables[tableName],
                ref hasPatchFilesAction,
                ref seqInstallFiles,
                ref seqDuplicateFiles);
            TestSequenceTableForPatchFilesAction(
                pairedTransform.Tables[tableName],
                ref hasPatchFilesAction,
                ref seqInstallFiles,
                ref seqDuplicateFiles);
            if (!hasPatchFilesAction)
            {
                Table iesTable = pairedTransform.EnsureTable(this.TableDefinitions[tableName]);
                if (0 == iesTable.Rows.Count)
                {
                    iesTable.Operation = TableOperation.Add;
                }

                Row          patchAction    = iesTable.CreateRow(null);
                WixActionRow wixPatchAction = WindowsInstallerStandard.GetStandardActions()[table, "PatchFiles"];
                int          sequence       = wixPatchAction.Sequence;
                // Test for default sequence value's appropriateness
                if (seqInstallFiles >= sequence || (0 != seqDuplicateFiles && seqDuplicateFiles <= sequence))
                {
                    if (0 != seqDuplicateFiles)
                    {
                        if (seqDuplicateFiles < seqInstallFiles)
                        {
                            throw new WixException(WixErrors.InsertInvalidSequenceActionOrder(mainFileRow.SourceLineNumbers, iesTable.Name, "InstallFiles", "DuplicateFiles", wixPatchAction.Action));
                        }
                        else
                        {
                            sequence = (seqDuplicateFiles + seqInstallFiles) / 2;
                            if (seqInstallFiles == sequence || seqDuplicateFiles == sequence)
                            {
                                throw new WixException(WixErrors.InsertSequenceNoSpace(mainFileRow.SourceLineNumbers, iesTable.Name, "InstallFiles", "DuplicateFiles", wixPatchAction.Action));
                            }
                        }
                    }
                    else
                    {
                        sequence = seqInstallFiles + 1;
                    }
                }
                patchAction[0]        = wixPatchAction.Action;
                patchAction[1]        = wixPatchAction.Condition;
                patchAction[2]        = sequence;
                patchAction.Operation = RowOperation.Add;
            }
        }
Esempio n. 3
0
        public SequenceActionsCommand(IntermediateSection section)
        {
            this.Section = section;

            this.RelativeActionsForActions = new Dictionary <string, RelativeActions>();

            this.StandardActionsById = WindowsInstallerStandard.StandardActions().ToDictionary(a => a.Id.Id);
        }
Esempio n. 4
0
 /// <summary>
 /// Instantiates a standard ActionRow.
 /// </summary>
 /// <param name="sequenceTable">The sequence table of the standard action.</param>
 /// <param name="action">The name of the standard action.</param>
 /// <param name="condition">The condition of the standard action.</param>
 /// <param name="sequence">The suggested sequence number of the standard action.</param>
 private WixActionRow(SequenceTable sequenceTable, string action, string condition, int sequence) :
     base(null, WindowsInstallerStandard.GetTableDefinitions()["WixAction"])
 {
     this.SequenceTable = sequenceTable;
     this.Action        = action;
     this.Condition     = condition;
     this.Sequence      = sequence;
     this.Overridable   = true; // all standard actions are overridable by default
 }
Esempio n. 5
0
 private IEnumerable <WixActionSymbol> GetActions(SequenceTable sequence, string[] actionNames)
 {
     foreach (var action in WindowsInstallerStandard.StandardActions())
     {
         if (action.SequenceTable == sequence && actionNames.Contains(action.Action))
         {
             yield return(action);
         }
     }
 }
Esempio n. 6
0
 /// <summary>
 /// Determines if the directory Id starts with a standard directory id.
 /// </summary>
 /// <param name="directoryId">The directory id.</param>
 /// <param name="standardDirectoryId">The standard directory id.</param>
 /// <returns>true if the directory starts with a standard directory id.</returns>
 private static bool StartsWithStandardDirectoryId(string directoryId, out string standardDirectoryId)
 {
     standardDirectoryId = null;
     foreach (string id in WindowsInstallerStandard.GetStandardDirectories())
     {
         if (directoryId.StartsWith(id, StringComparison.Ordinal))
         {
             standardDirectoryId = id;
             return(true);
         }
     }
     return(false);
 }
Esempio n. 7
0
        /// <summary>
        /// Get the source path of a directory.
        /// </summary>
        /// <param name="directories">All cached directories.</param>
        /// <param name="componentIdGenSeeds">Hash table of Component GUID generation seeds indexed by directory id.</param>
        /// <param name="directory">Directory identifier.</param>
        /// <param name="canonicalize">Canonicalize the path for standard directories.</param>
        /// <returns>Source path of a directory.</returns>
        internal static string GetDirectoryPath(Hashtable directories, Hashtable componentIdGenSeeds, string directory, bool canonicalize)
        {
            if (!directories.Contains(directory))
            {
                throw new WixException(WixErrors.ExpectedDirectory(directory));
            }

            ResolvedDirectory resolvedDirectory = (ResolvedDirectory)directories[directory];

            if (null == resolvedDirectory.Path)
            {
                if (null != componentIdGenSeeds && componentIdGenSeeds.Contains(directory))
                {
                    resolvedDirectory.Path = (string)componentIdGenSeeds[directory];
                }
                else if (canonicalize && WindowsInstallerStandard.IsStandardDirectory(directory))
                {
                    // when canonicalization is on, standard directories are treated equally
                    resolvedDirectory.Path = directory;
                }
                else
                {
                    string name = resolvedDirectory.Name;

                    if (canonicalize && null != name)
                    {
                        name = name.ToLower(CultureInfo.InvariantCulture);
                    }

                    if (String.IsNullOrEmpty(resolvedDirectory.DirectoryParent))
                    {
                        resolvedDirectory.Path = name;
                    }
                    else
                    {
                        string parentPath = GetDirectoryPath(directories, componentIdGenSeeds, resolvedDirectory.DirectoryParent, canonicalize);

                        if (null != resolvedDirectory.Name)
                        {
                            resolvedDirectory.Path = Path.Combine(parentPath, name);
                        }
                        else
                        {
                            resolvedDirectory.Path = parentPath;
                        }
                    }
                }
            }

            return(resolvedDirectory.Path);
        }
Esempio n. 8
0
        private Dictionary <string, WixActionSymbol> GetRequiredStandardActions()
        {
            var overridableActionSymbols = new Dictionary <string, WixActionSymbol>();

            var requiredActionIds = this.GetRequiredActionIds();

            foreach (var actionId in requiredActionIds)
            {
                WindowsInstallerStandard.TryGetStandardAction(actionId, out var standardAction);
                overridableActionSymbols.Add(standardAction.Id.Id, standardAction);
            }

            return(overridableActionSymbols);
        }
Esempio n. 9
0
        /// <summary>
        /// Get the source path of a directory.
        /// </summary>
        /// <param name="directories">All cached directories.</param>
        /// <param name="componentIdGenSeeds">Hash table of Component GUID generation seeds indexed by directory id.</param>
        /// <param name="directory">Directory identifier.</param>
        /// <param name="canonicalize">Canonicalize the path for standard directories.</param>
        /// <returns>Source path of a directory.</returns>
        public static string GetDirectoryPath(Dictionary <string, ResolvedDirectory> directories, Dictionary <string, string> componentIdGenSeeds, string directory, bool canonicalize)
        {
            if (!directories.TryGetValue(directory, out var resolvedDirectory))
            {
                throw new WixException(ErrorMessages.ExpectedDirectory(directory));
            }

            if (null == resolvedDirectory.Path)
            {
                if (null != componentIdGenSeeds && componentIdGenSeeds.ContainsKey(directory))
                {
                    resolvedDirectory.Path = (string)componentIdGenSeeds[directory];
                }
                else if (canonicalize && WindowsInstallerStandard.IsStandardDirectory(directory))
                {
                    // when canonicalization is on, standard directories are treated equally
                    resolvedDirectory.Path = directory;
                }
                else
                {
                    string name = resolvedDirectory.Name;

                    if (canonicalize)
                    {
                        name = name?.ToLowerInvariant();
                    }

                    if (String.IsNullOrEmpty(resolvedDirectory.DirectoryParent))
                    {
                        resolvedDirectory.Path = name;
                    }
                    else
                    {
                        string parentPath = GetDirectoryPath(directories, componentIdGenSeeds, resolvedDirectory.DirectoryParent, canonicalize);

                        if (null != resolvedDirectory.Name)
                        {
                            resolvedDirectory.Path = Path.Combine(parentPath, name);
                        }
                        else
                        {
                            resolvedDirectory.Path = parentPath;
                        }
                    }
                }
            }

            return(resolvedDirectory.Path);
        }
        private string GetStandardDirectoryParent(string directoryId)
        {
            switch (directoryId)
            {
            case "TARGETDIR":
                return(null);

            case "CommonFiles6432Folder":
            case "ProgramFiles6432Folder":
            case "System6432Folder":
                return(WindowsInstallerStandard.GetPlatformSpecificDirectoryId(directoryId, this.Platform));

            default:
                return("TARGETDIR");
            }
        }
Esempio n. 11
0
        /// <summary>
        /// Get the action symbol that is the parent of the given action symbol.
        /// </summary>
        /// <param name="actionSymbol">The given action symbol.</param>
        /// <param name="requiredActionSymbols">Collection of actions which must be included.</param>
        /// <returns>Null if there is no parent. Used for loop termination.</returns>
        private WixActionSymbol GetParentActionSymbol(WixActionSymbol actionSymbol, Dictionary <string, WixActionSymbol> requiredActionSymbols)
        {
            if (null == actionSymbol.Before && null == actionSymbol.After)
            {
                return(null);
            }

            var parentActionKey = actionSymbol.SequenceTable.ToString() + "/" + (actionSymbol.After ?? actionSymbol.Before);

            if (!requiredActionSymbols.TryGetValue(parentActionKey, out var parentActionSymbol))
            {
                WindowsInstallerStandard.TryGetStandardAction(parentActionKey, out parentActionSymbol);
            }

            return(parentActionSymbol);
        }
Esempio n. 12
0
        private void SchedulePropertyExeAction(IntermediateSection section, SourceLineNumber sourceLineNumbers, Identifier name, string source, string cmdline, CustomActionSymbol caTemplate, string condition, string beforeAction, string afterAction)
        {
            const SequenceTable sequence = SequenceTable.InstallExecuteSequence;

            caTemplate.SourceType = CustomActionSourceType.Property;
            caTemplate.Source     = source;
            caTemplate.TargetType = CustomActionTargetType.Exe;
            caTemplate.Target     = cmdline;
            section.AddSymbol(caTemplate);

            section.AddSymbol(new WixActionSymbol(sourceLineNumbers, new Identifier(name.Access, sequence, name.Id))
            {
                SequenceTable = SequenceTable.InstallExecuteSequence,
                Action        = name.Id,
                Condition     = condition,
                // no explicit sequence
                Before      = beforeAction,
                After       = afterAction,
                Overridable = false,
            });

            if (null != beforeAction)
            {
                if (WindowsInstallerStandard.IsStandardAction(beforeAction))
                {
                    this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.WixAction, sequence.ToString(), beforeAction);
                }
                else
                {
                    this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.CustomAction, beforeAction);
                }
            }

            if (null != afterAction)
            {
                if (WindowsInstallerStandard.IsStandardAction(afterAction))
                {
                    this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.WixAction, sequence.ToString(), afterAction);
                }
                else
                {
                    this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.CustomAction, afterAction);
                }
            }
        }
        private void SchedulePropertyExeAction(SourceLineNumber sourceLineNumbers, Identifier name, string source, string cmdline, int extraBits, string condition, string beforeAction, string afterAction)
        {
            const string sequence = "InstallExecuteSequence";

            Row actionRow = this.Core.CreateRow(sourceLineNumbers, "CustomAction", name);

            actionRow[1] = VSCompiler.MsidbCustomActionTypeProperty | VSCompiler.MsidbCustomActionTypeExe | extraBits;
            actionRow[2] = source;
            actionRow[3] = cmdline;

            Row sequenceRow = this.Core.CreateRow(sourceLineNumbers, "WixAction");

            sequenceRow[0] = sequence;
            sequenceRow[1] = name.Id;
            sequenceRow[2] = condition;
            // no explicit sequence
            sequenceRow[4] = beforeAction;
            sequenceRow[5] = afterAction;
            sequenceRow[6] = 0; // not overridable

            if (null != beforeAction)
            {
                if (WindowsInstallerStandard.IsStandardAction(beforeAction))
                {
                    this.Core.CreateSimpleReference(sourceLineNumbers, "WixAction", sequence, beforeAction);
                }
                else
                {
                    this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", beforeAction);
                }
            }

            if (null != afterAction)
            {
                if (WindowsInstallerStandard.IsStandardAction(afterAction))
                {
                    this.Core.CreateSimpleReference(sourceLineNumbers, "WixAction", sequence, afterAction);
                }
                else
                {
                    this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", afterAction);
                }
            }
        }
        private void SchedulePropertyExeAction(IntermediateSection section, SourceLineNumber sourceLineNumbers, Identifier name, string source, string cmdline, int extraBits, string condition, string beforeAction, string afterAction)
        {
            const string sequence = "InstallExecuteSequence";

            var actionRow = this.ParseHelper.CreateRow(section, sourceLineNumbers, "CustomAction", name);

            actionRow.Set(1, VSCompiler.MsidbCustomActionTypeProperty | VSCompiler.MsidbCustomActionTypeExe | extraBits);
            actionRow.Set(2, source);
            actionRow.Set(3, cmdline);

            var sequenceRow = this.ParseHelper.CreateRow(section, sourceLineNumbers, "WixAction", new Identifier(name.Access, sequence, name.Id));

            sequenceRow.Set(0, sequence);
            sequenceRow.Set(1, name.Id);
            sequenceRow.Set(2, condition);
            // no explicit sequence
            sequenceRow.Set(4, beforeAction);
            sequenceRow.Set(5, afterAction);
            sequenceRow.Set(6, 0); // not overridable

            if (null != beforeAction)
            {
                if (WindowsInstallerStandard.IsStandardAction(beforeAction))
                {
                    this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "WixAction", sequence, beforeAction);
                }
                else
                {
                    this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "CustomAction", beforeAction);
                }
            }

            if (null != afterAction)
            {
                if (WindowsInstallerStandard.IsStandardAction(afterAction))
                {
                    this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "WixAction", sequence, afterAction);
                }
                else
                {
                    this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "CustomAction", afterAction);
                }
            }
        }
Esempio n. 15
0
        public string GetCanonicalDirectoryPath(Dictionary <string, IResolvedDirectory> directories, Dictionary <string, string> componentIdGenSeeds, string directory, Platform platform)
        {
            if (!directories.TryGetValue(directory, out var resolvedDirectory))
            {
                throw new WixException(ErrorMessages.ExpectedDirectory(directory));
            }

            if (null == resolvedDirectory.Path)
            {
                if (null != componentIdGenSeeds && componentIdGenSeeds.ContainsKey(directory))
                {
                    resolvedDirectory.Path = componentIdGenSeeds[directory];
                }
                else if (WindowsInstallerStandard.IsStandardDirectory(directory))
                {
                    resolvedDirectory.Path = WindowsInstallerStandard.GetPlatformSpecificDirectoryId(directory, platform);
                }
                else
                {
                    var name = resolvedDirectory.Name?.ToLowerInvariant();

                    if (String.IsNullOrEmpty(resolvedDirectory.DirectoryParent))
                    {
                        resolvedDirectory.Path = name;
                    }
                    else
                    {
                        var parentPath = this.GetCanonicalDirectoryPath(directories, componentIdGenSeeds, resolvedDirectory.DirectoryParent, platform);

                        if (null != resolvedDirectory.Name)
                        {
                            resolvedDirectory.Path = Path.Combine(parentPath, name);
                        }
                        else
                        {
                            resolvedDirectory.Path = parentPath;
                        }
                    }
                }
            }

            return(resolvedDirectory.Path);
        }
Esempio n. 16
0
        /// <summary>
        /// Sequence an action before or after a standard action.
        /// </summary>
        /// <param name="actionSymbol">The action symbol to be sequenced.</param>
        /// <param name="requiredActionSymbols">Collection of actions which must be included.</param>
        private void SequenceActionSymbol(WixActionSymbol actionSymbol, Dictionary <string, WixActionSymbol> requiredActionSymbols)
        {
            var after = false;

            if (actionSymbol.After != null)
            {
                after = true;
            }
            else if (actionSymbol.Before == null)
            {
                throw new InvalidOperationException("Found an action with no Sequence, Before, or After column set.");
            }

            var parentActionName = (after ? actionSymbol.After : actionSymbol.Before);
            var parentActionKey  = actionSymbol.SequenceTable.ToString() + "/" + parentActionName;

            if (!requiredActionSymbols.TryGetValue(parentActionKey, out var parentActionSymbol))
            {
                // If the missing parent action is a standard action (with a suggested sequence number), add it.
                if (WindowsInstallerStandard.TryGetStandardAction(parentActionKey, out parentActionSymbol))
                {
                    // Create a clone to avoid modifying the static copy of the object.
                    // TODO: consider this: parentActionSymbol = parentActionSymbol.Clone();

                    requiredActionSymbols.Add(parentActionSymbol.Id.Id, parentActionSymbol);
                }
                else
                {
                    throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, "Found an action with a non-existent {0} action: {1}.", (after ? "After" : "Before"), parentActionName));
                }
            }
            else if (actionSymbol == parentActionSymbol || this.ContainsChildActionSymbol(actionSymbol, parentActionSymbol)) // cycle detected
            {
                throw new WixException(ErrorMessages.ActionCircularDependency(actionSymbol.SourceLineNumbers, actionSymbol.SequenceTable.ToString(), actionSymbol.Action, parentActionSymbol.Action));
            }

            // Add this action to the appropriate list of dependent action symbols.
            var relativeActions = this.GetRelativeActions(parentActionSymbol);
            var relatedSymbols  = (after ? relativeActions.NextActions : relativeActions.PreviousActions);

            relatedSymbols.Add(actionSymbol);
        }
        private void EnsureStandardDirectoryAdded(ISet <string> directoryIds, string directoryId, SourceLineNumber sourceLineNumbers)
        {
            if (!directoryIds.Contains(directoryId) && WindowsInstallerStandard.TryGetStandardDirectory(directoryId, out var standardDirectory))
            {
                var parentDirectoryId = this.GetStandardDirectoryParent(directoryId);

                var directory = new DirectorySymbol(sourceLineNumbers, standardDirectory.Id)
                {
                    Name = standardDirectory.Name,
                    ParentDirectoryRef = parentDirectoryId,
                };

                directoryIds.Add(directory.Id.Id);
                this.Section.AddSymbol(directory);

                if (!String.IsNullOrEmpty(parentDirectoryId))
                {
                    this.EnsureStandardDirectoryAdded(directoryIds, parentDirectoryId, sourceLineNumbers);
                }
            }
        }
Esempio n. 18
0
        /// <summary>
        /// Sequence an action before or after a standard action.
        /// </summary>
        /// <param name="actionSymbol">The action symbol to be sequenced.</param>
        /// <param name="requiredActionSymbols">Collection of actions which must be included.</param>
        /// <param name="firstReference">A dictionary used for detecting cyclic references among action symbols.</param>
        private void SequenceActionSymbol(WixActionSymbol actionSymbol, Dictionary <string, WixActionSymbol> requiredActionSymbols, Dictionary <WixActionSymbol, WixActionSymbol> firstReference)
        {
            var after = false;

            if (actionSymbol.After != null)
            {
                after = true;
            }
            else if (actionSymbol.Before == null)
            {
                throw new WixException($"Found action '{actionSymbol.Id.Id}' at {actionSymbol.SourceLineNumbers}' with no Sequence, Before, or After column set. The compiler should have prevented this.");
            }

            var parentActionName = (after ? actionSymbol.After : actionSymbol.Before);
            var parentActionKey  = actionSymbol.SequenceTable.ToString() + "/" + parentActionName;

            if (!requiredActionSymbols.TryGetValue(parentActionKey, out var parentActionSymbol))
            {
                // If the missing parent action is a standard action (with a suggested sequence number), add it.
                if (WindowsInstallerStandard.TryGetStandardAction(parentActionKey, out parentActionSymbol))
                {
                    // Create a clone to avoid modifying the static copy of the object.
                    // TODO: consider this: parentActionSymbol = parentActionSymbol.Clone();

                    requiredActionSymbols.Add(parentActionSymbol.Id.Id, parentActionSymbol);
                }
                else
                {
                    throw new WixException($"Found action {actionSymbol.Id.Id} with a non-existent {(after ? "After" : "Before")} action '{parentActionName}'. The linker should have prevented this.");
                }
            }

            this.CheckForCircularActionReference(actionSymbol, requiredActionSymbols, firstReference);

            // Add this action to the appropriate list of dependent action symbols.
            var relativeActions = this.GetRelativeActions(parentActionSymbol);
            var relatedSymbols  = (after ? relativeActions.NextActions : relativeActions.PreviousActions);

            relatedSymbols.Add(actionSymbol);
        }
Esempio n. 19
0
        public WixActionSymbol ScheduleActionSymbol(IntermediateSection section, SourceLineNumber sourceLineNumbers, AccessModifier access, SequenceTable sequence, string actionName, string condition, string beforeAction, string afterAction, bool overridable = false)
        {
            var actionId = new Identifier(access, sequence, actionName);

            var actionSymbol = section.AddSymbol(new WixActionSymbol(sourceLineNumbers, actionId)
            {
                SequenceTable = sequence,
                Action        = actionName,
                Condition     = condition,
                Before        = beforeAction,
                After         = afterAction,
                Overridable   = overridable,
            });

            if (null != beforeAction)
            {
                if (WindowsInstallerStandard.IsStandardAction(beforeAction))
                {
                    this.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.WixAction, sequence.ToString(), beforeAction);
                }
                else
                {
                    this.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.CustomAction, beforeAction);
                }
            }

            if (null != afterAction)
            {
                if (WindowsInstallerStandard.IsStandardAction(afterAction))
                {
                    this.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.WixAction, sequence.ToString(), afterAction);
                }
                else
                {
                    this.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.CustomAction, afterAction);
                }
            }

            return(actionSymbol);
        }
Esempio n. 20
0
        public int Execute()
        {
            var intermediates = this.CompilePhase();

            var tableDefinitions = new TableDefinitionCollection(WindowsInstallerStandard.GetTableDefinitions());

            if (this.OutputType == OutputType.Library)
            {
                this.LibraryPhase(intermediates, tableDefinitions);
            }
            else
            {
                var output = this.LinkPhase(intermediates, tableDefinitions);

                if (!Messaging.Instance.EncounteredError)
                {
                    this.BindPhase(output, tableDefinitions);
                }
            }

            return(Messaging.Instance.LastErrorNumber);
        }
Esempio n. 21
0
 /// <summary>
 /// Instantiate a new Librarian class.
 /// </summary>
 public Librarian()
 {
     this.TableDefinitions = new TableDefinitionCollection(WindowsInstallerStandard.GetTableDefinitions());
 }
        /// <summary>
        /// Adds the PatchFiles action to the sequence table if it does not already exist.
        /// </summary>
        /// <param name="table">The sequence table to check or modify.</param>
        /// <param name="mainTransform">The primary authoring transform.</param>
        /// <param name="pairedTransform">The secondary patch transform.</param>
        /// <param name="mainFileRow">The file row that contains information about the patched file.</param>
        private void AddPatchFilesActionToSequenceTable(SequenceTable table, WindowsInstallerData mainTransform, WindowsInstallerData pairedTransform, Row mainFileRow)
        {
            var tableName = table.ToString();

            // Find/add PatchFiles action (also determine sequence for it).
            // Search mainTransform first, then pairedTransform (pairedTransform overrides).
            var hasPatchFilesAction    = false;
            var installFilesSequence   = 0;
            var duplicateFilesSequence = 0;

            TestSequenceTableForPatchFilesAction(
                mainTransform.Tables[tableName],
                ref hasPatchFilesAction,
                ref installFilesSequence,
                ref duplicateFilesSequence);
            TestSequenceTableForPatchFilesAction(
                pairedTransform.Tables[tableName],
                ref hasPatchFilesAction,
                ref installFilesSequence,
                ref duplicateFilesSequence);
            if (!hasPatchFilesAction)
            {
                WindowsInstallerStandard.TryGetStandardAction(tableName, "PatchFiles", out var patchFilesActionSymbol);

                var sequence = patchFilesActionSymbol.Sequence;

                // Test for default sequence value's appropriateness
                if (installFilesSequence >= sequence || (0 != duplicateFilesSequence && duplicateFilesSequence <= sequence))
                {
                    if (0 != duplicateFilesSequence)
                    {
                        if (duplicateFilesSequence < installFilesSequence)
                        {
                            throw new WixException(ErrorMessages.InsertInvalidSequenceActionOrder(mainFileRow.SourceLineNumbers, tableName, "InstallFiles", "DuplicateFiles", patchFilesActionSymbol.Action));
                        }
                        else
                        {
                            sequence = (duplicateFilesSequence + installFilesSequence) / 2;
                            if (installFilesSequence == sequence || duplicateFilesSequence == sequence)
                            {
                                throw new WixException(ErrorMessages.InsertSequenceNoSpace(mainFileRow.SourceLineNumbers, tableName, "InstallFiles", "DuplicateFiles", patchFilesActionSymbol.Action));
                            }
                        }
                    }
                    else
                    {
                        sequence = installFilesSequence + 1;
                    }
                }

                var sequenceTable = pairedTransform.EnsureTable(this.TableDefinitions[tableName]);
                if (0 == sequenceTable.Rows.Count)
                {
                    sequenceTable.Operation = TableOperation.Add;
                }

                var patchAction = sequenceTable.CreateRow(null);
                patchAction[0]        = patchFilesActionSymbol.Action;
                patchAction[1]        = patchFilesActionSymbol.Condition;
                patchAction[2]        = sequence;
                patchAction.Operation = RowOperation.Add;
            }
        }
Esempio n. 23
0
 public Inscriber()
 {
     this.tableDefinitions = new TableDefinitionCollection(WindowsInstallerStandard.GetTableDefinitions());
 }
Esempio n. 24
0
        public void Execute()
        {
            var requiredActionSymbols = new Dictionary <string, WixActionSymbol>();

            // Get the standard actions required based on symbols in the section.
            var overridableActionSymbols = this.GetRequiredStandardActions();

            // Index all the action symbols and look for collisions.
            foreach (var actionSymbol in this.Section.Symbols.OfType <WixActionSymbol>())
            {
                if (actionSymbol.Overridable) // overridable action
                {
                    if (overridableActionSymbols.TryGetValue(actionSymbol.Id.Id, out var collidingActionSymbol))
                    {
                        this.Messaging.Write(ErrorMessages.OverridableActionCollision(actionSymbol.SourceLineNumbers, actionSymbol.SequenceTable.ToString(), actionSymbol.Action));
                        if (null != collidingActionSymbol.SourceLineNumbers)
                        {
                            this.Messaging.Write(ErrorMessages.OverridableActionCollision2(collidingActionSymbol.SourceLineNumbers));
                        }
                    }
                    else
                    {
                        overridableActionSymbols.Add(actionSymbol.Id.Id, actionSymbol);
                    }
                }
                else // unsequenced or sequenced action.
                {
                    // Unsequenced action (allowed for certain standard actions).
                    if (null == actionSymbol.Before && null == actionSymbol.After && !actionSymbol.Sequence.HasValue)
                    {
                        if (WindowsInstallerStandard.TryGetStandardAction(actionSymbol.Id.Id, out var standardAction))
                        {
                            // Populate the sequence from the standard action
                            actionSymbol.Sequence = standardAction.Sequence;
                        }
                        else // not a supported unscheduled action.
                        {
                            throw new InvalidOperationException("Found an action with no Sequence, Before, or After column set.");
                        }
                    }

                    if (requiredActionSymbols.TryGetValue(actionSymbol.Id.Id, out var collidingActionSymbol))
                    {
                        this.Messaging.Write(ErrorMessages.ActionCollision(actionSymbol.SourceLineNumbers, actionSymbol.SequenceTable.ToString(), actionSymbol.Action));
                        if (null != collidingActionSymbol.SourceLineNumbers)
                        {
                            this.Messaging.Write(ErrorMessages.ActionCollision2(collidingActionSymbol.SourceLineNumbers));
                        }
                    }
                    else
                    {
                        requiredActionSymbols.Add(actionSymbol.Id.Id, actionSymbol);
                    }
                }
            }

            // Add the overridable action symbols that are not overridden to the required action symbols.
            foreach (var actionSymbol in overridableActionSymbols.Values)
            {
                if (!requiredActionSymbols.ContainsKey(actionSymbol.Id.Id))
                {
                    requiredActionSymbols.Add(actionSymbol.Id.Id, actionSymbol);
                }
            }

            // Suppress the required actions that are overridable.
            foreach (var suppressActionSymbol in this.Section.Symbols.OfType <WixSuppressActionSymbol>())
            {
                var key = suppressActionSymbol.Id.Id;

                // If there is an overridable symbol to suppress; suppress it. There is no warning if there
                // is no action to suppress because the action may be suppressed from a merge module in
                // the binder.
                if (requiredActionSymbols.TryGetValue(key, out var requiredActionSymbol))
                {
                    if (requiredActionSymbol.Overridable)
                    {
                        this.Messaging.Write(WarningMessages.SuppressAction(suppressActionSymbol.SourceLineNumbers, suppressActionSymbol.Action, suppressActionSymbol.SequenceTable.ToString()));
                        if (null != requiredActionSymbol.SourceLineNumbers)
                        {
                            this.Messaging.Write(WarningMessages.SuppressAction2(requiredActionSymbol.SourceLineNumbers));
                        }

                        requiredActionSymbols.Remove(key);
                    }
                    else // suppressing a non-overridable action symbol
                    {
                        this.Messaging.Write(ErrorMessages.SuppressNonoverridableAction(suppressActionSymbol.SourceLineNumbers, suppressActionSymbol.SequenceTable.ToString(), suppressActionSymbol.Action));
                        if (null != requiredActionSymbol.SourceLineNumbers)
                        {
                            this.Messaging.Write(ErrorMessages.SuppressNonoverridableAction2(requiredActionSymbol.SourceLineNumbers));
                        }
                    }
                }
            }

            // Build up dependency trees of the relatively scheduled actions.
            // Use ToList() to create a copy of the required action symbols so that new symbols can
            // be added while enumerating.
            foreach (var actionSymbol in requiredActionSymbols.Values.ToList())
            {
                if (!actionSymbol.Sequence.HasValue)
                {
                    // check for standard actions that don't have a sequence number in a merge module
                    if (SectionType.Module == this.Section.Type && WindowsInstallerStandard.IsStandardAction(actionSymbol.Action))
                    {
                        this.Messaging.Write(ErrorMessages.StandardActionRelativelyScheduledInModule(actionSymbol.SourceLineNumbers, actionSymbol.SequenceTable.ToString(), actionSymbol.Action));
                    }

                    this.SequenceActionSymbol(actionSymbol, requiredActionSymbols);
                }
                else if (SectionType.Module == this.Section.Type && 0 < actionSymbol.Sequence && !WindowsInstallerStandard.IsStandardAction(actionSymbol.Action)) // check for custom actions and dialogs that have a sequence number
                {
                    this.Messaging.Write(ErrorMessages.CustomActionSequencedInModule(actionSymbol.SourceLineNumbers, actionSymbol.SequenceTable.ToString(), actionSymbol.Action));
                }
            }

            // Look for standard actions with sequence restrictions that aren't necessarily scheduled based
            // on the presence of a particular table.
            if (requiredActionSymbols.ContainsKey("InstallExecuteSequence/DuplicateFiles") && !requiredActionSymbols.ContainsKey("InstallExecuteSequence/InstallFiles"))
            {
                WindowsInstallerStandard.TryGetStandardAction("InstallExecuteSequence/InstallFiles", out var standardAction);
                requiredActionSymbols.Add(standardAction.Id.Id, standardAction);
            }

            // Schedule actions.
            List <WixActionSymbol> scheduledActionSymbols;

            if (SectionType.Module == this.Section.Type)
            {
                scheduledActionSymbols = requiredActionSymbols.Values.ToList();
            }
            else
            {
                scheduledActionSymbols = this.ScheduleActions(requiredActionSymbols);
            }

            // Remove all existing WixActionSymbols from the section then add the
            // scheduled actions back to the section. Note: we add the indices in
            // reverse order to make it easy to remove them from the list later.
            var removeIndices = new List <int>();

            for (var i = this.Section.Symbols.Count - 1; i >= 0; --i)
            {
                var symbol = this.Section.Symbols[i];
                if (symbol.Definition.Type == SymbolDefinitionType.WixAction)
                {
                    removeIndices.Add(i);
                }
            }

            foreach (var removeIndex in removeIndices)
            {
                this.Section.Symbols.RemoveAt(removeIndex);
            }

            foreach (var action in scheduledActionSymbols)
            {
                this.Section.AddSymbol(action);
            }
        }
Esempio n. 25
0
 /// <summary>
 /// Constructor for binder core.
 /// </summary>
 internal BinderCore()
 {
     this.TableDefinitions = new TableDefinitionCollection(WindowsInstallerStandard.GetTableDefinitions());
 }
Esempio n. 26
0
        private string ModularizedRowFieldValue(Row row, Field field)
        {
            var fieldData = field.AsString();

            if (!(WindowsInstallerStandard.IsStandardAction(fieldData) || WindowsInstallerStandard.IsStandardProperty(fieldData)))
            {
                var modularizeType = field.Column.ModularizeType;

                // special logic for the ControlEvent table's Argument column
                // this column requires different modularization methods depending upon the value of the Event column
                if (ColumnModularizeType.ControlEventArgument == field.Column.ModularizeType)
                {
                    switch (row[2].ToString())
                    {
                    case "CheckExistingTargetPath": // redirectable property name
                    case "CheckTargetPath":
                    case "DoAction":                // custom action name
                    case "NewDialog":               // dialog name
                    case "SelectionBrowse":
                    case "SetTargetPath":
                    case "SpawnDialog":
                    case "SpawnWaitDialog":
                        if (Common.IsIdentifier(fieldData))
                        {
                            modularizeType = ColumnModularizeType.Column;
                        }
                        else
                        {
                            modularizeType = ColumnModularizeType.Property;
                        }
                        break;

                    default:     // formatted
                        modularizeType = ColumnModularizeType.Property;
                        break;
                    }
                }
                else if (ColumnModularizeType.ControlText == field.Column.ModularizeType)
                {
                    // icons are stored in the Binary table, so they get column-type modularization
                    if (("Bitmap" == row[2].ToString() || "Icon" == row[2].ToString()) && Common.IsIdentifier(fieldData))
                    {
                        modularizeType = ColumnModularizeType.Column;
                    }
                    else
                    {
                        modularizeType = ColumnModularizeType.Property;
                    }
                }

                switch (modularizeType)
                {
                case ColumnModularizeType.Column:
                    // ensure the value is an identifier (otherwise it shouldn't be modularized this way)
                    if (!Common.IsIdentifier(fieldData))
                    {
                        throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixDataStrings.EXP_CannotModularizeIllegalID, fieldData));
                    }

                    // if we're not supposed to suppress modularization of this identifier
                    if (!this.SuppressModularizationIdentifiers.Contains(fieldData))
                    {
                        fieldData = String.Concat(fieldData, ".", this.ModularizationGuid);
                    }
                    break;

                case ColumnModularizeType.Property:
                case ColumnModularizeType.Condition:
                    Regex regex;
                    if (ColumnModularizeType.Property == modularizeType)
                    {
                        regex = new Regex(@"\[(?<identifier>[#$!]?[a-zA-Z_][a-zA-Z0-9_\.]*)]", RegexOptions.Singleline | RegexOptions.ExplicitCapture);
                    }
                    else
                    {
                        Debug.Assert(ColumnModularizeType.Condition == modularizeType);

                        // This heinous looking regular expression is actually quite an elegant way
                        // to shred the entire condition into the identifiers that need to be
                        // modularized.  Let's break it down piece by piece:
                        //
                        // 1. Look for the operators: NOT, EQV, XOR, OR, AND, IMP (plus a space).  Note that the
                        //    regular expression is case insensitive so we don't have to worry about
                        //    all the permutations of these strings.
                        // 2. Look for quoted strings.  Quoted strings are just text and are ignored
                        //    outright.
                        // 3. Look for environment variables.  These look like identifiers we might
                        //    otherwise be interested in but start with a percent sign.  Like quoted
                        //    strings these enviroment variable references are ignored outright.
                        // 4. Match all identifiers that are things that need to be modularized.  Note
                        //    the special characters (!, $, ?, &) that denote Component and Feature states.
                        regex = new Regex(@"NOT\s|EQV\s|XOR\s|OR\s|AND\s|IMP\s|"".*?""|%[a-zA-Z_][a-zA-Z0-9_\.]*|(?<identifier>[!$\?&]?[a-zA-Z_][a-zA-Z0-9_\.]*)", RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);

                        // less performant version of the above with captures showing where everything lives
                        // regex = new Regex(@"(?<operator>NOT|EQV|XOR|OR|AND|IMP)|(?<string>"".*?"")|(?<environment>%[a-zA-Z_][a-zA-Z0-9_\.]*)|(?<identifier>[!$\?&]?[a-zA-Z_][a-zA-Z0-9_\.]*)",RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);
                    }

                    var matches = regex.Matches(fieldData);

                    var sb = new StringBuilder(fieldData);

                    // Notice how this code walks backward through the list
                    // because it modifies the string as we through it.
                    for (var i = matches.Count - 1; 0 <= i; i--)
                    {
                        var group = matches[i].Groups["identifier"];
                        if (group.Success)
                        {
                            var identifier = group.Value;
                            if (!WindowsInstallerStandard.IsStandardProperty(identifier) && !this.SuppressModularizationIdentifiers.Contains(identifier))
                            {
                                sb.Insert(group.Index + group.Length, '.');
                                sb.Insert(group.Index + group.Length + 1, this.ModularizationGuid);
                            }
                        }
                    }

                    fieldData = sb.ToString();
                    break;

                case ColumnModularizeType.CompanionFile:
                    // if we're not supposed to ignore this identifier and the value does not start with
                    // a digit, we must have a companion file so modularize it
                    if (!this.SuppressModularizationIdentifiers.Contains(fieldData) &&
                        0 < fieldData.Length && !Char.IsDigit(fieldData, 0))
                    {
                        fieldData = String.Concat(fieldData, ".", this.ModularizationGuid);
                    }
                    break;

                case ColumnModularizeType.Icon:
                    if (!this.SuppressModularizationIdentifiers.Contains(fieldData))
                    {
                        var start = fieldData.LastIndexOf(".", StringComparison.Ordinal);
                        if (-1 == start)
                        {
                            fieldData = String.Concat(fieldData, ".", this.ModularizationGuid);
                        }
                        else
                        {
                            fieldData = String.Concat(fieldData.Substring(0, start), ".", this.ModularizationGuid, fieldData.Substring(start));
                        }
                    }
                    break;

                case ColumnModularizeType.SemicolonDelimited:
                    var keys = fieldData.Split(';');
                    for (var i = 0; i < keys.Length; ++i)
                    {
                        if (!String.IsNullOrEmpty(keys[i]))
                        {
                            keys[i] = String.Concat(keys[i], ".", this.ModularizationGuid);
                        }
                    }

                    fieldData = String.Join(";", keys);
                    break;
                }
            }

            return(fieldData);
        }