/// <summary>
        /// Creates a new file media information from a file row.
        /// </summary>
        /// <param name="fileRow">File row.</param>
        public FileMediaInformation(FileRow fileRow)
        {
            if (null == fileRow)
            {
                throw new ArgumentNullException("fileRow");
            }

            this.containedInModule = false;

            this.fileId = fileRow.File;
            this.directoryId = fileRow.Directory;
            this.mediaId = fileRow.DiskId;
            this.source = fileRow.Source;
            this.modulePath = null;
            this.rowNumber = fileRow.Number;
            this.patchGroup = fileRow.PatchGroup;

            if (0 != (fileRow.Attributes & 0x002000))
            {
                this.fileCompression = FileCompressionValue.No;
            }
            else if (0 != (fileRow.Attributes & 0x004000))
            {
                this.fileCompression = FileCompressionValue.Yes;
            }
            else
            {
                this.fileCompression = FileCompressionValue.NotSpecified;
            }

            this.sequence = -1;
        }
Esempio n. 2
0
 /// <summary>
 /// Appends previous data from another FileRow object.
 /// </summary>
 /// <param name="src">An row to get data from.</param>
 public void AppendPreviousDataFrom(FileRow src)
 {
     AppendStringToArray(ref this.previousSource, src.previousSource[0]);
     AppendStringToArray(ref this.previousSymbols, src.previousSymbols[0]);
     AppendStringToArray(ref this.previousRetainOffsets, src.previousRetainOffsets[0]);
     AppendStringToArray(ref this.previousRetainLengths, src.previousRetainLengths[0]);
     AppendStringToArray(ref this.previousIgnoreOffsets, src.previousIgnoreOffsets[0]);
     AppendStringToArray(ref this.previousIgnoreLengths, src.previousIgnoreLengths[0]);
 }
Esempio n. 3
0
 /// <summary>
 /// Copies data from another FileRow object.
 /// </summary>
 /// <param name="src">An row to get data from.</param>
 public void CopyFrom(FileRow src)
 {
     for (int i = 0; i < src.Fields.Length; i++)
     {
         this[i] = src[i];
     }
     this.assemblyManifest         = src.assemblyManifest;
     this.assemblyType             = src.assemblyType;
     this.directory                = src.directory;
     this.diskId                   = src.diskId;
     this.fromModule               = src.fromModule;
     this.isGeneratedShortFileName = src.isGeneratedShortFileName;
     this.patchGroup               = src.patchGroup;
     this.processorArchitecture    = src.processorArchitecture;
     this.source                   = src.source;
 }
Esempio n. 4
0
        /// <summary>
        /// Creates a new row in the table.
        /// </summary>
        /// <param name="sourceLineNumbers">Original source lines for this row.</param>
        /// <returns>Row created in table.</returns>
        public Row CreateRow(SourceLineNumberCollection sourceLineNumbers)
        {
            Row row;

            switch (this.Name)
            {
            // TODO:  create strongly types rows here
            case "BBControl":
                row = new BBControlRow(sourceLineNumbers, this);
                break;

            case "Control":
                row = new ControlRow(sourceLineNumbers, this);
                break;

            case "File":
                row = new FileRow(sourceLineNumbers, this);
                break;

            case "Media":
                row = new MediaRow(sourceLineNumbers, this);
                break;

            case "Merge":
                row = new MergeRow(sourceLineNumbers, this);
                break;

            case "Property":
                row = new PropertyRow(sourceLineNumbers, this);
                break;

            case "Upgrade":
                row = new UpgradeRow(sourceLineNumbers, this);
                break;

            default:
                row = new Row(sourceLineNumbers, this);
                break;
            }

            this.rows.Add(row);
            return(row);
        }
Esempio n. 5
0
        /// <summary>
        /// Creates a new row in the table.
        /// </summary>
        /// <param name="sourceLineNumbers">Original source lines for this row.</param>
        /// <param name="add">Specifies whether to only create the row or add it to the table automatically.</param>
        /// <returns>Row created in table.</returns>
        public Row CreateRow(SourceLineNumberCollection sourceLineNumbers, bool add)
        {
            Row row;

            switch (this.Name)
            {
            case "BBControl":
                row = new BBControlRow(sourceLineNumbers, this);
                break;

            case "ChainMsiPackage":
                row = new ChainMsiPackageRow(sourceLineNumbers, this);
                break;

            case "Component":
                row = new ComponentRow(sourceLineNumbers, this);
                break;

            case "Control":
                row = new ControlRow(sourceLineNumbers, this);
                break;

            case "File":
                row = new FileRow(sourceLineNumbers, this);
                break;

            case "Media":
                row = new MediaRow(sourceLineNumbers, this);
                break;

            case "PayloadInfo":
                row = new PayloadInfoRow(sourceLineNumbers, this);
                break;

            case "Upgrade":
                row = new UpgradeRow(sourceLineNumbers, this);
                break;

            case "Variable":
                row = new VariableRow(sourceLineNumbers, this);
                break;

            case "WixAction":
                row = new WixActionRow(sourceLineNumbers, this);
                break;

            case "WixApprovedExeForElevation":
                row = new WixApprovedExeForElevationRow(sourceLineNumbers, this);
                break;

            case "WixBundle":
                row = new WixBundleRow(sourceLineNumbers, this);
                break;

            case "WixBundlePatchTargetCode":
                row = new WixBundlePatchTargetCodeRow(sourceLineNumbers, this);
                break;

            case "WixBundleUpdate":
                row = new WixBundleUpdateRow(sourceLineNumbers, this);
                break;

            case "WixCatalog":
                row = new WixCatalogRow(sourceLineNumbers, this);
                break;

            case "WixCommandLine":
                row = new WixCommandLineRow(sourceLineNumbers, this);
                break;

            case "WixComplexReference":
                row = new WixComplexReferenceRow(sourceLineNumbers, this);
                break;

            case "WixFile":
                row = new WixFileRow(sourceLineNumbers, this);
                break;

            case "WixMedia":
                row = new WixMediaRow(sourceLineNumbers, this);
                break;

            case "WixMediaTemplate":
                row = new WixMediaTemplateRow(sourceLineNumbers, this);
                break;

            case "WixMerge":
                row = new WixMergeRow(sourceLineNumbers, this);
                break;

            case "WixProperty":
                row = new WixPropertyRow(sourceLineNumbers, this);
                break;

            case "WixSimpleReference":
                row = new WixSimpleReferenceRow(sourceLineNumbers, this);
                break;

            case "WixUpdateRegistration":
                row = new WixUpdateRegistrationRow(sourceLineNumbers, this);
                break;

            case "WixVariable":
                row = new WixVariableRow(sourceLineNumbers, this);
                break;

            default:
                row = new Row(sourceLineNumbers, this);
                break;
            }

            if (add)
            {
                this.rows.Add(row);
            }

            return(row);
        }
Esempio n. 6
0
File: Table.cs Progetto: zooba/wix3
        /// <summary>
        /// Creates a new row in the table.
        /// </summary>
        /// <param name="sourceLineNumbers">Original source lines for this row.</param>
        /// <param name="add">Specifies whether to only create the row or add it to the table automatically.</param>
        /// <returns>Row created in table.</returns>
        public Row CreateRow(SourceLineNumberCollection sourceLineNumbers, bool add)
        {
            Row row;

            switch (this.Name)
            {
                case "BBControl":
                    row = new BBControlRow(sourceLineNumbers, this);
                    break;
                case "ChainMsiPackage":
                    row = new ChainMsiPackageRow(sourceLineNumbers, this);
                    break;
                case "Component":
                    row = new ComponentRow(sourceLineNumbers, this);
                    break;
                case "Control":
                    row = new ControlRow(sourceLineNumbers, this);
                    break;
                case "File":
                    row = new FileRow(sourceLineNumbers, this);
                    break;
                case "Media":
                    row = new MediaRow(sourceLineNumbers, this);
                    break;
                case "PayloadInfo":
                    row = new PayloadInfoRow(sourceLineNumbers, this);
                    break;
                case "Upgrade":
                    row = new UpgradeRow(sourceLineNumbers, this);
                    break;
                case "Variable":
                    row = new VariableRow(sourceLineNumbers, this);
                    break;
                case "WixAction":
                    row = new WixActionRow(sourceLineNumbers, this);
                    break;
                case "WixApprovedExeForElevation":
                    row = new WixApprovedExeForElevationRow(sourceLineNumbers, this);
                    break;
                case "WixBundle":
                    row = new WixBundleRow(sourceLineNumbers, this);
                    break;
                case "WixBundlePatchTargetCode":
                    row = new WixBundlePatchTargetCodeRow(sourceLineNumbers, this);
                    break;
                case "WixBundleUpdate":
                    row = new WixBundleUpdateRow(sourceLineNumbers, this);
                    break;
                case "WixCatalog":
                    row = new WixCatalogRow(sourceLineNumbers, this);
                    break;
                case "WixCommandLine":
                    row = new WixCommandLineRow(sourceLineNumbers, this);
                    break;
                case "WixComplexReference":
                    row = new WixComplexReferenceRow(sourceLineNumbers, this);
                    break;
                case "WixFile":
                    row = new WixFileRow(sourceLineNumbers, this);
                    break;
                case "WixMedia":
                    row = new WixMediaRow(sourceLineNumbers, this);
                    break;
                case "WixMediaTemplate":
                    row = new WixMediaTemplateRow(sourceLineNumbers, this);
                    break;
                case "WixMerge":
                    row = new WixMergeRow(sourceLineNumbers, this);
                    break;
                case "WixProperty":
                    row = new WixPropertyRow(sourceLineNumbers, this);
                    break;
                case "WixSimpleReference":
                    row = new WixSimpleReferenceRow(sourceLineNumbers, this);
                    break;
                case "WixUpdateRegistration":
                    row = new WixUpdateRegistrationRow(sourceLineNumbers, this);
                    break;
                case "WixVariable":
                    row = new WixVariableRow(sourceLineNumbers, this);
                    break;

                default:
                    row = new Row(sourceLineNumbers, this);
                    break;
            }

            if (add)
            {
                this.rows.Add(row);
            }

            return row;
        }
Esempio n. 7
0
        /// <summary>
        /// Creates a new row in the table.
        /// </summary>
        /// <param name="sourceLineNumbers">Original source lines for this row.</param>
        /// <returns>Row created in table.</returns>
        public Row CreateRow(SourceLineNumberCollection sourceLineNumbers)
        {
            Row row;

            switch (this.Name)
            {
            case "BBControl":
                row = new BBControlRow(sourceLineNumbers, this);
                break;

            case "Control":
                row = new ControlRow(sourceLineNumbers, this);
                break;

            case "File":
                row = new FileRow(sourceLineNumbers, this);
                break;

            case "Media":
                row = new MediaRow(sourceLineNumbers, this);
                break;

            case "Upgrade":
                row = new UpgradeRow(sourceLineNumbers, this);
                break;

            case "WixAction":
                row = new WixActionRow(sourceLineNumbers, this);
                break;

            case "WixComplexReference":
                row = new WixComplexReferenceRow(sourceLineNumbers, this);
                break;

            case "WixFile":
                row = new WixFileRow(sourceLineNumbers, this);
                break;

            case "WixMedia":
                row = new WixMediaRow(sourceLineNumbers, this);
                break;

            case "WixMerge":
                row = new WixMergeRow(sourceLineNumbers, this);
                break;

            case "WixProperty":
                row = new WixPropertyRow(sourceLineNumbers, this);
                break;

            case "WixSimpleReference":
                row = new WixSimpleReferenceRow(sourceLineNumbers, this);
                break;

            case "WixVariable":
                row = new WixVariableRow(sourceLineNumbers, this);
                break;

            default:
                row = new Row(sourceLineNumbers, this);
                break;
            }

            this.rows.Add(row);

            return(row);
        }
Esempio n. 8
0
File: Binder.cs Progetto: zooba/wix3
        private void UpdateFileRow(Output output, IDictionary<string, string> infoCache, string modularizationGuid, Hashtable fileRowIndex, FileRow fileRow, bool overwriteHash)
        {
            FileInfo fileInfo = null;

            if (!this.suppressFileHashAndInfo || (!this.suppressAssemblies && FileAssemblyType.NotAnAssembly != fileRow.AssemblyType))
            {
                try
                {
                    fileInfo = new FileInfo(fileRow.Source);
                }
                catch (ArgumentException)
                {
                    this.core.OnMessage(WixErrors.InvalidFileName(fileRow.SourceLineNumbers, fileRow.Source));
                    return;
                }
                catch (PathTooLongException)
                {
                    this.core.OnMessage(WixErrors.InvalidFileName(fileRow.SourceLineNumbers, fileRow.Source));
                    return;
                }
                catch (NotSupportedException)
                {
                    this.core.OnMessage(WixErrors.InvalidFileName(fileRow.SourceLineNumbers, fileRow.Source));
                    return;
                }
            }

            if (!this.suppressFileHashAndInfo)
            {
                if (fileInfo.Exists)
                {
                    string version;
                    string language;

                    using (FileStream fileStream = new FileStream(fileInfo.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        if (Int32.MaxValue < fileStream.Length)
                        {
                            throw new WixException(WixErrors.FileTooLarge(fileRow.SourceLineNumbers, fileRow.Source));
                        }

                        fileRow.FileSize = Convert.ToInt32(fileStream.Length, CultureInfo.InvariantCulture);
                    }

                    try
                    {
                        Installer.GetFileVersion(fileInfo.FullName, out version, out language);
                    }
                    catch (Win32Exception e)
                    {
                        if (0x2 == e.NativeErrorCode) // ERROR_FILE_NOT_FOUND
                        {
                            throw new WixException(WixErrors.FileNotFound(fileRow.SourceLineNumbers, fileInfo.FullName));
                        }
                        else
                        {
                            throw new WixException(WixErrors.Win32Exception(e.NativeErrorCode, e.Message));
                        }
                    }

                    // If there is no version, it is assumed there is no language because it won't matter in the versioning of the install.
                    if (0 == version.Length)   // unversioned files have their hashes added to the MsiFileHash table
                    {
                        if (null != fileRow.Version)
                        {
                            // Check if this is a companion file. If its not, it is a default version.
                            if (!fileRowIndex.ContainsKey(fileRow.Version))
                            {
                                this.core.OnMessage(WixWarnings.DefaultVersionUsedForUnversionedFile(fileRow.SourceLineNumbers, fileRow.Version, fileRow.File));
                            }
                        }
                        else
                        {
                            if (null != fileRow.Language)
                            {
                                this.core.OnMessage(WixWarnings.DefaultLanguageUsedForUnversionedFile(fileRow.SourceLineNumbers, fileRow.Language, fileRow.File));
                            }

                            int[] hash;
                            try
                            {
                                Installer.GetFileHash(fileInfo.FullName, 0, out hash);
                            }
                            catch (Win32Exception e)
                            {
                                if (0x2 == e.NativeErrorCode) // ERROR_FILE_NOT_FOUND
                                {
                                    throw new WixException(WixErrors.FileNotFound(fileRow.SourceLineNumbers, fileInfo.FullName));
                                }
                                else
                                {
                                    throw new WixException(WixErrors.Win32Exception(e.NativeErrorCode, fileInfo.FullName, e.Message));
                                }
                            }

                            if (null == fileRow.HashRow)
                            {
                                Table msiFileHashTable = output.EnsureTable(this.core.TableDefinitions["MsiFileHash"]);
                                fileRow.HashRow = msiFileHashTable.CreateRow(fileRow.SourceLineNumbers);
                            }

                            fileRow.HashRow[0] = fileRow.File;
                            fileRow.HashRow[1] = 0;
                            fileRow.HashRow[2] = hash[0];
                            fileRow.HashRow[3] = hash[1];
                            fileRow.HashRow[4] = hash[2];
                            fileRow.HashRow[5] = hash[3];
                        }
                    }
                    else // update the file row with the version and language information
                    {
                        // Check if the version field references a fileId because this would mean it has a companion file and the version should not be overwritten.
                        if (null == fileRow.Version || !fileRowIndex.ContainsKey(fileRow.Version))
                        {
                            fileRow.Version = version;
                        }

                        if (null != fileRow.Language && 0 == language.Length)
                        {
                            this.core.OnMessage(WixWarnings.DefaultLanguageUsedForVersionedFile(fileRow.SourceLineNumbers, fileRow.Language, fileRow.File));
                        }
                        else
                        {
                            fileRow.Language = language;
                        }

                        // Populate the binder variables for this file information if requested.
                        if (null != infoCache)
                        {
                            if (!String.IsNullOrEmpty(fileRow.Version))
                            {
                                string key = String.Format(CultureInfo.InvariantCulture, "fileversion.{0}", Demodularize(output, modularizationGuid, fileRow.File));
                                infoCache[key] = fileRow.Version;
                            }

                            if (!String.IsNullOrEmpty(fileRow.Language))
                            {
                                string key = String.Format(CultureInfo.InvariantCulture, "filelanguage.{0}", Demodularize(output, modularizationGuid, fileRow.File));
                                infoCache[key] = fileRow.Language;
                            }
                        }
                    }
                }
                else
                {
                    this.core.OnMessage(WixErrors.CannotFindFile(fileRow.SourceLineNumbers, fileRow.File, fileRow.FileName, fileRow.Source));
                }
            }

            // if we're not suppressing automagically grabbing assembly information and this is a
            // CLR assembly, load the assembly and get the assembly name information
            if (!this.suppressAssemblies)
            {
                if (FileAssemblyType.DotNetAssembly == fileRow.AssemblyType)
                {
                    StringDictionary assemblyNameValues = new StringDictionary();

                    CLRInterop.IReferenceIdentity referenceIdentity = null;
                    Guid referenceIdentityGuid = CLRInterop.ReferenceIdentityGuid;
                    uint result = CLRInterop.GetAssemblyIdentityFromFile(fileInfo.FullName, ref referenceIdentityGuid, out referenceIdentity);
                    if (0 == result && null != referenceIdentity)
                    {
                        string culture = referenceIdentity.GetAttribute(null, "Culture");
                        if (null != culture)
                        {
                            assemblyNameValues.Add("Culture", culture);
                        }
                        else
                        {
                            assemblyNameValues.Add("Culture", "neutral");
                        }

                        string name = referenceIdentity.GetAttribute(null, "Name");
                        if (null != name)
                        {
                            assemblyNameValues.Add("Name", name);
                        }

                        string processorArchitecture = referenceIdentity.GetAttribute(null, "ProcessorArchitecture");
                        if (null != processorArchitecture)
                        {
                            assemblyNameValues.Add("ProcessorArchitecture", processorArchitecture);
                        }

                        string publicKeyToken = referenceIdentity.GetAttribute(null, "PublicKeyToken");
                        if (null != publicKeyToken)
                        {
                            bool publicKeyIsNeutral = (String.Equals(publicKeyToken, "neutral", StringComparison.OrdinalIgnoreCase));

                            // Managed code expects "null" instead of "neutral", and
                            // this won't be installed to the GAC since it's not signed anyway.
                            assemblyNameValues.Add("publicKeyToken", publicKeyIsNeutral ? "null" : publicKeyToken.ToUpperInvariant());
                            assemblyNameValues.Add("publicKeyTokenPreservedCase", publicKeyIsNeutral ? "null" : publicKeyToken);
                        }
                        else if (fileRow.AssemblyApplication == null)
                        {
                            throw new WixException(WixErrors.GacAssemblyNoStrongName(fileRow.SourceLineNumbers, fileInfo.FullName, fileRow.Component));
                        }

                        string version = referenceIdentity.GetAttribute(null, "Version");
                        if (null != version)
                        {
                            assemblyNameValues.Add("Version", version);
                        }
                    }
                    else
                    {
                        this.core.OnMessage(WixErrors.InvalidAssemblyFile(fileRow.SourceLineNumbers, fileInfo.FullName, String.Format(CultureInfo.InvariantCulture, "HRESULT: 0x{0:x8}", result)));
                        return;
                    }

                    Table assemblyNameTable = output.EnsureTable(this.core.TableDefinitions["MsiAssemblyName"]);
                    if (assemblyNameValues.ContainsKey("name"))
                    {
                        SetMsiAssemblyName(output, assemblyNameTable, fileRow, "name", assemblyNameValues["name"], infoCache, modularizationGuid);
                    }

                    string fileVersion = null;
                    if (this.setMsiAssemblyNameFileVersion)
                    {
                        string language;

                        Installer.GetFileVersion(fileInfo.FullName, out fileVersion, out language);
                        SetMsiAssemblyName(output, assemblyNameTable, fileRow, "fileVersion", fileVersion, infoCache, modularizationGuid);
                    }

                    if (assemblyNameValues.ContainsKey("version"))
                    {
                        string assemblyVersion = assemblyNameValues["version"];

                        if (!this.exactAssemblyVersions)
                        {
                            // there is a bug in fusion that requires the assembly's "version" attribute
                            // to be equal to or longer than the "fileVersion" in length when its present;
                            // the workaround is to prepend zeroes to the last version number in the assembly version
                            if (this.setMsiAssemblyNameFileVersion && null != fileVersion && fileVersion.Length > assemblyVersion.Length)
                            {
                                string padding = new string('0', fileVersion.Length - assemblyVersion.Length);
                                string[] assemblyVersionNumbers = assemblyVersion.Split('.');

                                if (assemblyVersionNumbers.Length > 0)
                                {
                                    assemblyVersionNumbers[assemblyVersionNumbers.Length - 1] = String.Concat(padding, assemblyVersionNumbers[assemblyVersionNumbers.Length - 1]);
                                    assemblyVersion = String.Join(".", assemblyVersionNumbers);
                                }
                            }
                        }

                        SetMsiAssemblyName(output, assemblyNameTable, fileRow, "version", assemblyVersion, infoCache, modularizationGuid);
                    }

                    if (assemblyNameValues.ContainsKey("culture"))
                    {
                        SetMsiAssemblyName(output, assemblyNameTable, fileRow, "culture", assemblyNameValues["culture"], infoCache, modularizationGuid);
                    }

                    if (assemblyNameValues.ContainsKey("publicKeyToken"))
                    {
                        SetMsiAssemblyName(output, assemblyNameTable, fileRow, "publicKeyToken", assemblyNameValues["publicKeyToken"], infoCache, modularizationGuid);
                    }

                    if (null != fileRow.ProcessorArchitecture && 0 < fileRow.ProcessorArchitecture.Length)
                    {
                        SetMsiAssemblyName(output, assemblyNameTable, fileRow, "processorArchitecture", fileRow.ProcessorArchitecture, infoCache, modularizationGuid);
                    }

                    if (assemblyNameValues.ContainsKey("processorArchitecture"))
                    {
                        SetMsiAssemblyName(output, assemblyNameTable, fileRow, "processorArchitecture", assemblyNameValues["processorArchitecture"], infoCache, modularizationGuid);
                    }

                    // add the assembly name to the information cache
                    if (null != infoCache)
                    {
                        string fileId = Demodularize(output, modularizationGuid, fileRow.File);
                        string key = String.Concat("assemblyfullname.", fileId);
                        string assemblyName = String.Concat(assemblyNameValues["name"], ", version=", assemblyNameValues["version"], ", culture=", assemblyNameValues["culture"], ", publicKeyToken=", String.IsNullOrEmpty(assemblyNameValues["publicKeyToken"]) ? "null" : assemblyNameValues["publicKeyToken"]);
                        if (assemblyNameValues.ContainsKey("processorArchitecture"))
                        {
                            assemblyName = String.Concat(assemblyName, ", processorArchitecture=", assemblyNameValues["processorArchitecture"]);
                        }

                        infoCache[key] = assemblyName;

                        // Add entries with the preserved case publicKeyToken
                        string pcAssemblyNameKey = String.Concat("assemblyfullnamepreservedcase.", fileId);
                        infoCache[pcAssemblyNameKey] = (assemblyNameValues["publicKeyToken"] == assemblyNameValues["publicKeyTokenPreservedCase"]) ? assemblyName : assemblyName.Replace(assemblyNameValues["publicKeyToken"], assemblyNameValues["publicKeyTokenPreservedCase"]);

                        string pcPublicKeyTokenKey = String.Concat("assemblypublickeytokenpreservedcase.", fileId);
                        infoCache[pcPublicKeyTokenKey] = assemblyNameValues["publicKeyTokenPreservedCase"];
                    }
                }
                else if (FileAssemblyType.Win32Assembly == fileRow.AssemblyType)
                {
                    // Able to use the index because only the Source field is used and it is used only for more complete error messages.
                    FileRow fileManifestRow = (FileRow)fileRowIndex[fileRow.AssemblyManifest];

                    if (null == fileManifestRow)
                    {
                        this.core.OnMessage(WixErrors.MissingManifestForWin32Assembly(fileRow.SourceLineNumbers, fileRow.File, fileRow.AssemblyManifest));
                    }

                    string type = null;
                    string name = null;
                    string version = null;
                    string processorArchitecture = null;
                    string publicKeyToken = null;

                    // loading the dom is expensive we want more performant APIs than the DOM
                    // Navigator is cheaper than dom.  Perhaps there is a cheaper API still.
                    try
                    {
                        XPathDocument doc = new XPathDocument(fileManifestRow.Source);
                        XPathNavigator nav = doc.CreateNavigator();
                        nav.MoveToRoot();

                        // this assumes a particular schema for a win32 manifest and does not
                        // provide error checking if the file does not conform to schema.
                        // The fallback case here is that nothing is added to the MsiAssemblyName
                        // table for an out of tolerance Win32 manifest.  Perhaps warnings needed.
                        if (nav.MoveToFirstChild())
                        {
                            while (nav.NodeType != XPathNodeType.Element || nav.Name != "assembly")
                            {
                                nav.MoveToNext();
                            }

                            if (nav.MoveToFirstChild())
                            {
                                bool hasNextSibling = true;
                                while (nav.NodeType != XPathNodeType.Element || nav.Name != "assemblyIdentity" && hasNextSibling)
                                {
                                    hasNextSibling = nav.MoveToNext();
                                }
                                if (!hasNextSibling)
                                {
                                    this.core.OnMessage(WixErrors.InvalidManifestContent(fileRow.SourceLineNumbers, fileManifestRow.Source));
                                    return;
                                }

                                if (nav.MoveToAttribute("type", String.Empty))
                                {
                                    type = nav.Value;
                                    nav.MoveToParent();
                                }

                                if (nav.MoveToAttribute("name", String.Empty))
                                {
                                    name = nav.Value;
                                    nav.MoveToParent();
                                }

                                if (nav.MoveToAttribute("version", String.Empty))
                                {
                                    version = nav.Value;
                                    nav.MoveToParent();
                                }

                                if (nav.MoveToAttribute("processorArchitecture", String.Empty))
                                {
                                    processorArchitecture = nav.Value;
                                    nav.MoveToParent();
                                }

                                if (nav.MoveToAttribute("publicKeyToken", String.Empty))
                                {
                                    publicKeyToken = nav.Value;
                                    nav.MoveToParent();
                                }
                            }
                        }
                    }
                    catch (FileNotFoundException fe)
                    {
                        this.core.OnMessage(WixErrors.FileNotFound(SourceLineNumberCollection.FromFileName(fileManifestRow.Source), fe.FileName, "AssemblyManifest"));
                    }
                    catch (XmlException xe)
                    {
                        this.core.OnMessage(WixErrors.InvalidXml(SourceLineNumberCollection.FromFileName(fileManifestRow.Source), "manifest", xe.Message));
                    }

                    Table assemblyNameTable = output.EnsureTable(this.core.TableDefinitions["MsiAssemblyName"]);
                    if (null != name && 0 < name.Length)
                    {
                        SetMsiAssemblyName(output, assemblyNameTable, fileRow, "name", name, infoCache, modularizationGuid);
                    }

                    if (null != version && 0 < version.Length)
                    {
                        SetMsiAssemblyName(output, assemblyNameTable, fileRow, "version", version, infoCache, modularizationGuid);
                    }

                    if (null != type && 0 < type.Length)
                    {
                        SetMsiAssemblyName(output, assemblyNameTable, fileRow, "type", type, infoCache, modularizationGuid);
                    }

                    if (null != processorArchitecture && 0 < processorArchitecture.Length)
                    {
                        SetMsiAssemblyName(output, assemblyNameTable, fileRow, "processorArchitecture", processorArchitecture, infoCache, modularizationGuid);
                    }

                    if (null != publicKeyToken && 0 < publicKeyToken.Length)
                    {
                        SetMsiAssemblyName(output, assemblyNameTable, fileRow, "publicKeyToken", publicKeyToken, infoCache, modularizationGuid);
                    }
                }
            }
        }
Esempio n. 9
0
File: Binder.cs Progetto: zooba/wix3
        private void SetMsiAssemblyName(Output output, Table assemblyNameTable, FileRow fileRow, string name, string value, IDictionary<string, string> infoCache, string modularizationGuid)
        {
            // check for null value (this can occur when grabbing the file version from an assembly without one)
            if (null == value || 0 == value.Length)
            {
                this.core.OnMessage(WixWarnings.NullMsiAssemblyNameValue(fileRow.SourceLineNumbers, fileRow.Component, name));
            }
            else
            {
                Row assemblyNameRow = null;

                // override directly authored value
                foreach (Row row in assemblyNameTable.Rows)
                {
                    if ((string)row[0] == fileRow.Component && (string)row[1] == name)
                    {
                        assemblyNameRow = row;
                        break;
                    }
                }

                // if the assembly will be GAC'd and the name in the file table doesn't match the name in the MsiAssemblyName table, error because the install will fail.
                if ("name" == name && FileAssemblyType.DotNetAssembly == fileRow.AssemblyType && String.IsNullOrEmpty(fileRow.AssemblyApplication) && !String.Equals(Path.GetFileNameWithoutExtension(fileRow.LongFileName), value, StringComparison.OrdinalIgnoreCase))
                {
                    this.core.OnMessage(WixErrors.GACAssemblyIdentityWarning(fileRow.SourceLineNumbers, Path.GetFileNameWithoutExtension(fileRow.LongFileName), value));
                }

                if (null == assemblyNameRow)
                {
                    assemblyNameRow = assemblyNameTable.CreateRow(fileRow.SourceLineNumbers);
                    assemblyNameRow[0] = fileRow.Component;
                    assemblyNameRow[1] = name;
                    assemblyNameRow[2] = value;

                    // put the MsiAssemblyName row in the same section as the related File row
                    assemblyNameRow.SectionId = fileRow.SectionId;

                    if (null == fileRow.AssemblyNameRows)
                    {
                        fileRow.AssemblyNameRows = new RowCollection();
                    }
                    fileRow.AssemblyNameRows.Add(assemblyNameRow);
                }
                else
                {
                    assemblyNameRow[2] = value;
                }

                if (infoCache != null)
                {
                    string key = String.Format(CultureInfo.InvariantCulture, "assembly{0}.{1}", name, Demodularize(output, modularizationGuid, fileRow.File)).ToLower(CultureInfo.InvariantCulture);
                    infoCache[key] = (string)assemblyNameRow[2];
                }
            }
        }
Esempio n. 10
0
 /// <summary>
 /// Copies data from another FileRow object.
 /// </summary>
 /// <param name="src">An row to get data from.</param>
 public void CopyFrom(FileRow src)
 {
     for (int i = 0; i < src.Fields.Length; i++)
     {
         this[i] = src[i];
     }
     this.assemblyManifest = src.assemblyManifest;
     this.assemblyType = src.assemblyType;
     this.directory = src.directory;
     this.diskId = src.diskId;
     this.fromModule = src.fromModule;
     this.isGeneratedShortFileName = src.isGeneratedShortFileName;
     this.patchGroup = src.patchGroup;
     this.processorArchitecture = src.processorArchitecture;
     this.source = src.source;
     this.PreviousSource = src.PreviousSource;
     this.Operation = src.Operation;
     this.symbols = src.symbols;
     this.PreviousSymbols = src.PreviousSymbols;
     this.patchAttributes = src.patchAttributes;
     this.retainOffsets = src.retainOffsets;
     this.retainLengths = src.retainLengths;
     this.ignoreOffsets = src.ignoreOffsets;
     this.ignoreLengths = src.ignoreLengths;
     this.PreviousRetainOffsets = src.PreviousRetainOffsets;
     this.PreviousRetainLengths = src.PreviousRetainLengths;
     this.PreviousIgnoreOffsets = src.PreviousIgnoreOffsets;
     this.PreviousIgnoreLengths = src.PreviousIgnoreLengths;
 }
Esempio n. 11
0
 /// <summary>
 /// Adds a FileRow to the end of the collection.
 /// </summary>
 /// <param name="fileRow">The FileRow to be added to the end of the collection.</param>
 public void Add(FileRow fileRow)
 {
     if (this.hashedCollection != null)
     {
         this.hashedCollection.Add(fileRow.File, fileRow);
     }
     this.sortedCollection.Add(fileRow, null);
 }
Esempio n. 12
0
        public virtual void ResolvePatch(FileRow fileRow, out bool retainRangeWarning)
        {
            if (fileRow == null)
            {
                throw new ArgumentNullException("fileRow");
            }

            retainRangeWarning = false;
            if (this.deltaBinaryPatch && RowOperation.Modify == fileRow.Operation)
            {
                if (0 != (PatchAttributeType.IncludeWholeFile | fileRow.PatchAttributes))
                {
                    string deltaBase = Common.GenerateIdentifier("dlt", true, Common.GenerateGuid());
                    string deltaFile = Path.Combine(this.tempFilesLocation, String.Concat(deltaBase, ".dpf"));
                    string headerFile = Path.Combine(this.tempFilesLocation, String.Concat(deltaBase, ".phd"));
                    PatchAPI.PatchInterop.PatchSymbolFlagsType apiPatchingSymbolFlags = 0;
                    bool optimizePatchSizeForLargeFiles = false;

                    Table wixPatchIdTable = this.output.Tables["WixPatchId"];
                    if (null != wixPatchIdTable)
                    {
                        Row row = wixPatchIdTable.Rows[0];
                        if (null != row)
                        {
                            if (null != row[2])
                            {
                                optimizePatchSizeForLargeFiles = (1 == Convert.ToUInt32(row[2], CultureInfo.InvariantCulture));
                            }
                            if (null != row[3])
                            {
                                apiPatchingSymbolFlags = (PatchAPI.PatchInterop.PatchSymbolFlagsType)Convert.ToUInt32(row[3], CultureInfo.InvariantCulture);
                            }
                        }
                    }

                    if (PatchAPI.PatchInterop.CreateDelta(
                            deltaFile,
                            fileRow.Source,
                            fileRow.Symbols,
                            fileRow.RetainOffsets,
                            fileRow.PreviousSourceArray,
                            fileRow.PreviousSymbolsArray,
                            fileRow.PreviousIgnoreLengthsArray,
                            fileRow.PreviousIgnoreOffsetsArray,
                            fileRow.PreviousRetainLengthsArray,
                            fileRow.PreviousRetainOffsetsArray,
                            apiPatchingSymbolFlags,
                            optimizePatchSizeForLargeFiles,
                            out retainRangeWarning))
                    {
                        PatchAPI.PatchInterop.ExtractDeltaHeader(deltaFile, headerFile);
                        fileRow.Patch = headerFile;
                        fileRow.Source = deltaFile;
                    }
                }
            }
        }
Esempio n. 13
0
        /// <summary>
        /// Set an MsiAssemblyName row.  If it was directly authored, override the value, otherwise
        /// create a new row.
        /// </summary>
        /// <param name="assemblyNameOutputTable">MsiAssemblyName output table.</param>
        /// <param name="fileRow">FileRow containing the assembly read for the MsiAssemblyName row.</param>
        /// <param name="name">MsiAssemblyName name.</param>
        /// <param name="value">MsiAssemblyName value.</param>
        private void SetMsiAssemblyName(OutputTable assemblyNameOutputTable, FileRow fileRow, string name, string value)
        {
            // check for null value (this can occur when grabbing the file version from an assembly without one)
            if (null == value || 0 == value.Length)
            {
                this.OnMessage(WixErrors.NullMsiAssemblyNameValue(fileRow.SourceLineNumbers, fileRow.Component, name));
            }

            // override directly authored value
            foreach (OutputRow outputRow in assemblyNameOutputTable.OutputRows)
            {
                if ((string)outputRow.Row[0] == fileRow.Component && (string)outputRow.Row[1] == name)
                {
                    outputRow.Row[2] = value;
                    return;
                }
            }

            Row assemblyNameRow = new Row(assemblyNameOutputTable.TableDefinition);
            assemblyNameRow[0] = fileRow.Component;
            assemblyNameRow[1] = name;
            assemblyNameRow[2] = value;
            assemblyNameOutputTable.OutputRows.Add(new OutputRow(assemblyNameRow));
        }
Esempio n. 14
0
        /// <summary>
        /// Create the #transform for the given main transform.
        /// </summary>
        /// <param name="patchId">patch GUID from patch authoring.</param>
        /// <param name="mainTransform">transform generated by torch.</param>
        /// <param name="mediaRow">media authored into patch.</param>
        /// <param name="productCode">output string to receive ProductCode.</param>
        public Output BuildPairedTransform(string patchId, Output mainTransform, MediaRow mediaRow, ref string productCode)
        {
            Output pairedTransform = new Output(null);

            pairedTransform.Type     = OutputType.Transform;
            pairedTransform.Codepage = mainTransform.Codepage;

            // lookup productVersion property to correct summaryInformation
            string newProductVersion = null;
            Table  mainPropertyTable = mainTransform.Tables["Property"];

            if (mainPropertyTable != null)
            {
                foreach (Row row in mainPropertyTable.Rows)
                {
                    if ("ProductVersion" == (string)row[0])
                    {
                        newProductVersion = (string)row[1];
                    }
                }
            }

            // TODO: build class for manipulating SummaryInformation table
            Table mainSummaryTable = mainTransform.Tables["_SummaryInformation"];
            // add required properties
            Hashtable mainSummaryRows = new Hashtable();

            foreach (Row mainSummaryRow in mainSummaryTable.Rows)
            {
                mainSummaryRows[mainSummaryRow[0]] = mainSummaryRow;
            }
            if (!mainSummaryRows.Contains((int)SummaryInformation.Transform.ValidationFlags))
            {
                Row mainSummaryRow = mainSummaryTable.CreateRow(null);
                mainSummaryRow[0] = (int)SummaryInformation.Transform.ValidationFlags;
                mainSummaryRow[1] = "0";
            }

            // copy summary information from core transform
            Table pairedSummaryTable = pairedTransform.EnsureTable(this.tableDefinitions["_SummaryInformation"]);

            foreach (Row mainSummaryRow in mainSummaryTable.Rows)
            {
                string value = (string)mainSummaryRow[1];
                switch ((SummaryInformation.Transform)mainSummaryRow[0])
                {
                case SummaryInformation.Transform.ProductCodes:
                    string[] propertyData      = value.Split(';');
                    string   oldProductVersion = propertyData[0].Substring(38);
                    string   upgradeCode       = propertyData[2];
                    productCode = propertyData[0].Substring(0, 38);
                    if (newProductVersion == null)
                    {
                        newProductVersion = oldProductVersion;
                    }

                    // force mainTranform to old;new;upgrade and pairedTransform to new;new;upgrade
                    mainSummaryRow[1] = String.Concat(productCode, oldProductVersion, ';', productCode, newProductVersion, ';', upgradeCode);
                    value             = String.Concat(productCode, newProductVersion, ';', productCode, newProductVersion, ';', upgradeCode);
                    break;

                case SummaryInformation.Transform.ValidationFlags:
                    // TODO: ensure this row exists in mainSummaryTable!!!!
                    // TODO: author these settings in patch XML or set in torch.exe
                    int i = Convert.ToInt32(value);
                    i |= (int)SummaryInformation.TransformFlags.ErrorAddExistingRow;
                    i |= (int)SummaryInformation.TransformFlags.ErrorDeleteMissingRow;
                    i |= (int)SummaryInformation.TransformFlags.ErrorAddExistingTable;
                    i |= (int)SummaryInformation.TransformFlags.ErrorDeleteMissingTable;
                    i |= (int)SummaryInformation.TransformFlags.ErrorUpdateMissingRow;
                    i |= (int)SummaryInformation.TransformFlags.ValidateProduct;
                    mainSummaryRow[1] = value = i.ToString();
                    break;
                }
                Row pairedSummaryRow = pairedSummaryTable.CreateRow(null);
                pairedSummaryRow[0] = mainSummaryRow[0];
                pairedSummaryRow[1] = value;
            }

            if (productCode == null)
            {
                throw new InvalidOperationException("Could not determine ProductCode from transform summary information");
            }

            // copy File table
            Table mainFileTable    = mainTransform.Tables["File"];
            Table mainWixFileTable = mainTransform.Tables["WixFile"];

            if (mainFileTable != null)
            {
                FileRowCollection mainFileRows = new FileRowCollection();
                mainFileRows.AddRange(mainFileTable.Rows);

                Table pairedFileTable = pairedTransform.EnsureTable(mainFileTable.Definition);
                foreach (Row mainWixFileRow in mainWixFileTable.Rows)
                {
                    FileRow mainFileRow = mainFileRows[(string)mainWixFileRow[0]];

                    // set File.Sequence to non null to satisfy transform bind
                    mainFileRow.Sequence = 1;

                    // delete's don't need rows in the paired transform
                    if (mainFileRow.Operation == RowOperation.Delete)
                    {
                        continue;
                    }

                    FileRow pairedFileRow = (FileRow)pairedFileTable.CreateRow(null);
                    pairedFileRow.Operation = RowOperation.Modify;
                    for (int i = 0; i < mainFileRow.Fields.Length; i++)
                    {
                        object value = mainFileRow[i];
                        pairedFileRow[i] = value;
                    }

                    // override authored media for patch bind
                    // TODO: consider using File/@DiskId for patch media
                    mainFileRow.DiskId = mediaRow.DiskId;
                    mainWixFileRow[5]  = mediaRow.DiskId;
                    // suppress any change to File.Sequence to avoid bloat
                    mainFileRow.Fields[7].Modified = false;

                    // force File row to appear in the transform
                    if (RowOperation.Modify == mainFileRow.Operation)
                    {
                        mainFileRow.Operation            = RowOperation.Modify;
                        pairedFileRow.Attributes        |= MsiInterop.MsidbFileAttributesPatchAdded;
                        pairedFileRow.Fields[6].Modified = true;
                        pairedFileRow.Operation          = RowOperation.Modify;
                    }
                    else if (RowOperation.Add == mainFileRow.Operation)
                    {
                        // set msidbFileAttributesPatchAdded
                        pairedFileRow.Attributes        |= MsiInterop.MsidbFileAttributesPatchAdded;
                        pairedFileRow.Fields[6].Modified = true;
                        pairedFileRow.Operation          = RowOperation.Add;
                    }
                    else
                    {
                        pairedFileRow.Attributes         = mainFileRow.Attributes;
                        pairedFileRow.Fields[6].Modified = false;
                    }
                }
            }

            // add Media row to pairedTransform
            Table pairedMediaTable = pairedTransform.EnsureTable(this.tableDefinitions["Media"]);
            Row   pairedMediaRow   = pairedMediaTable.CreateRow(null);

            pairedMediaRow.Operation = RowOperation.Add;
            for (int i = 0; i < mediaRow.Fields.Length; i++)
            {
                pairedMediaRow[i] = mediaRow[i];
            }

            // add PatchPackage for this Media
            Table pairedPackageTable = pairedTransform.EnsureTable(this.tableDefinitions["PatchPackage"]);

            pairedPackageTable.Operation = TableOperation.Add;
            Row pairedPackageRow = pairedPackageTable.CreateRow(null);

            pairedPackageRow.Operation = RowOperation.Add;
            pairedPackageRow[0]        = patchId;
            pairedPackageRow[1]        = mediaRow.DiskId;

            // add property to both identify client patches and whether those patches are removable or not
            string patchPropertyId       = new Guid(patchId).ToString("N", CultureInfo.InvariantCulture).ToUpper();
            int    allowRemoval          = 0;
            Table  msiPatchMetadataTable = this.patch.Tables["MsiPatchMetadata"];

            if (null != msiPatchMetadataTable)
            {
                foreach (Row msiPatchMetadataRow in msiPatchMetadataTable.Rows)
                {
                    if (string.Empty == (string)msiPatchMetadataRow[0] && "AllowRemoval" == (string)msiPatchMetadataRow[1])
                    {
                        allowRemoval = Convert.ToInt32((string)msiPatchMetadataRow[2]);
                    }
                }
            }
            Table pairedPropertyTable = pairedTransform.EnsureTable(this.tableDefinitions["Property"]);

            pairedPropertyTable.Operation = TableOperation.Add;
            Row pairedPropertyRow = pairedPropertyTable.CreateRow(null);

            pairedPropertyRow.Operation = RowOperation.Add;
            pairedPropertyRow[0]        = string.Format(CultureInfo.InvariantCulture, "_{0}.AllowRemoval", patchPropertyId);
            pairedPropertyRow[1]        = allowRemoval.ToString();

            return(pairedTransform);
        }
Esempio n. 15
0
        /// <summary>
        /// Creates a new row in the table.
        /// </summary>
        /// <param name="sourceLineNumbers">Original source lines for this row.</param>
        /// <returns>Row created in table.</returns>
        public Row CreateRow(SourceLineNumberCollection sourceLineNumbers)
        {
            Row row;

            switch (this.Name)
            {
                case "BBControl":
                    row = new BBControlRow(sourceLineNumbers, this);
                    break;
                case "ChainMsiPackage":
                    row = new ChainMsiPackageRow(sourceLineNumbers, this);
                    break;
                case "Component":
                    row = new ComponentRow(sourceLineNumbers, this);
                    break;
                case "Control":
                    row = new ControlRow(sourceLineNumbers, this);
                    break;
                case "File":
                    row = new FileRow(sourceLineNumbers, this);
                    break;
                case "Media":
                    row = new MediaRow(sourceLineNumbers, this);
                    break;
                case "PayloadInfo":
                    row = new PayloadInfoRow(sourceLineNumbers, this);
                    break;
                case "Upgrade":
                    row = new UpgradeRow(sourceLineNumbers, this);
                    break;
                case "WixAction":
                    row = new WixActionRow(sourceLineNumbers, this);
                    break;
                case "WixComplexReference":
                    row = new WixComplexReferenceRow(sourceLineNumbers, this);
                    break;
                case "WixFile":
                    row = new WixFileRow(sourceLineNumbers, this);
                    break;
                case "WixMedia":
                    row = new WixMediaRow(sourceLineNumbers, this);
                    break;
                case "WixMediaTemplate":
                    row = new WixMediaTemplateRow(sourceLineNumbers, this);
                    break;
                case "WixMerge":
                    row = new WixMergeRow(sourceLineNumbers, this);
                    break;
                case "WixProperty":
                    row = new WixPropertyRow(sourceLineNumbers, this);
                    break;
                case "WixSimpleReference":
                    row = new WixSimpleReferenceRow(sourceLineNumbers, this);
                    break;
                case "WixVariable":
                    row = new WixVariableRow(sourceLineNumbers, this);
                    break;

                default:
                    row = new Row(sourceLineNumbers, this);
                    break;
            }

            this.rows.Add(row);

            return row;
        }
Esempio n. 16
0
 /// <summary>
 /// Appends previous data from another FileRow object.
 /// </summary>
 /// <param name="src">An row to get data from.</param>
 public void AppendPreviousDataFrom(FileRow src)
 {
     AppendStringToArray(ref this.previousSource, src.previousSource[0]);
     AppendStringToArray(ref this.previousSymbols, src.previousSymbols[0]);
     AppendStringToArray(ref this.previousRetainOffsets, src.previousRetainOffsets[0]);
     AppendStringToArray(ref this.previousRetainLengths, src.previousRetainLengths[0]);
     AppendStringToArray(ref this.previousIgnoreOffsets, src.previousIgnoreOffsets[0]);
     AppendStringToArray(ref this.previousIgnoreLengths, src.previousIgnoreLengths[0]);
 }
Esempio n. 17
0
File: Binder.cs Progetto: zooba/wix3
        /// <summary>
        /// Merge data from a row in the WixPatchSymbolsPaths table into an associated FileRow.
        /// </summary>
        /// <param name="row">Row from the WixPatchSymbolsPaths table.</param>
        /// <param name="fileRow">FileRow into which to set symbol information.</param>
        /// <comment>This includes PreviousData as well.</comment>
        private static void MergeSymbolPaths(Row row, FileRow fileRow)
        {
            if (null == fileRow.Symbols)
            {
                fileRow.Symbols = (string)row[2];
            }
            else
            {
                fileRow.Symbols = String.Concat(fileRow.Symbols, ";", (string)row[2]);
            }

            Field field = row.Fields[2];
            if (null != field.PreviousData)
            {
                if (null == fileRow.PreviousSymbols)
                {
                    fileRow.PreviousSymbols = field.PreviousData;
                }
                else
                {
                    fileRow.PreviousSymbols = String.Concat(fileRow.PreviousSymbols, ";", field.PreviousData);
                }
            }
        }
Esempio n. 18
0
File: Binder.cs Progetto: zooba/wix3
        /// <summary>
        /// Retrieve files and their information from merge modules.
        /// </summary>
        /// <param name="output">Internal representation of the msi database to operate upon.</param>
        /// <param name="fileRows">The indexed file rows.</param>
        private void ProcessMergeModules(Output output, FileRowCollection fileRows)
        {
            Table wixMergeTable = output.Tables["WixMerge"];
            if (null != wixMergeTable)
            {
                IMsmMerge2 merge = NativeMethods.GetMsmMerge();

                // Get the output's minimum installer version
                int outputInstallerVersion = int.MinValue;
                Table summaryInformationTable = output.Tables["_SummaryInformation"];
                if (null != summaryInformationTable)
                {
                    foreach (Row row in summaryInformationTable.Rows)
                    {
                        if (14 == (int)row[0])
                        {
                            outputInstallerVersion = Convert.ToInt32(row[1], CultureInfo.InvariantCulture);
                            break;
                        }
                    }
                }

                foreach (Row row in wixMergeTable.Rows)
                {
                    bool containsFiles = false;
                    WixMergeRow wixMergeRow = (WixMergeRow)row;

                    try
                    {
                        // read the module's File table to get its FileMediaInformation entries and gather any other information needed from the module.
                        using (Database db = new Database(wixMergeRow.SourceFile, OpenDatabase.ReadOnly))
                        {
                            if (db.TableExists("File") && db.TableExists("Component"))
                            {
                                Hashtable uniqueModuleFileIdentifiers = System.Collections.Specialized.CollectionsUtil.CreateCaseInsensitiveHashtable();

                                using (View view = db.OpenExecuteView("SELECT `File`, `Directory_` FROM `File`, `Component` WHERE `Component_`=`Component`"))
                                {
                                    // add each file row from the merge module into the file row collection (check for errors along the way)
                                    while (true)
                                    {
                                        using (Record record = view.Fetch())
                                        {
                                            if (null == record)
                                            {
                                                break;
                                            }

                                            // NOTE: this is very tricky - the merge module file rows are not added to the
                                            // file table because they should not be created via idt import.  Instead, these
                                            // rows are created by merging in the actual modules
                                            FileRow fileRow = new FileRow(null, this.core.TableDefinitions["File"]);
                                            fileRow.File = record[1];
                                            fileRow.Compressed = wixMergeRow.FileCompression;
                                            fileRow.Directory = record[2];
                                            fileRow.DiskId = wixMergeRow.DiskId;
                                            fileRow.FromModule = true;
                                            fileRow.PatchGroup = -1;
                                            fileRow.Source = String.Concat(this.TempFilesLocation, Path.DirectorySeparatorChar, "MergeId.", wixMergeRow.Number.ToString(CultureInfo.InvariantCulture.NumberFormat), Path.DirectorySeparatorChar, record[1]);

                                            FileRow collidingFileRow = fileRows[fileRow.File];
                                            FileRow collidingModuleFileRow = (FileRow)uniqueModuleFileIdentifiers[fileRow.File];

                                            if (null == collidingFileRow && null == collidingModuleFileRow)
                                            {
                                                fileRows.Add(fileRow);

                                                // keep track of file identifiers in this merge module
                                                uniqueModuleFileIdentifiers.Add(fileRow.File, fileRow);
                                            }
                                            else // collision(s) detected
                                            {
                                                // case-sensitive collision with another merge module or a user-authored file identifier
                                                if (null != collidingFileRow)
                                                {
                                                    this.core.OnMessage(WixErrors.DuplicateModuleFileIdentifier(wixMergeRow.SourceLineNumbers, wixMergeRow.Id, collidingFileRow.File));
                                                }

                                                // case-insensitive collision with another file identifier in the same merge module
                                                if (null != collidingModuleFileRow)
                                                {
                                                    this.core.OnMessage(WixErrors.DuplicateModuleCaseInsensitiveFileIdentifier(wixMergeRow.SourceLineNumbers, wixMergeRow.Id, fileRow.File, collidingModuleFileRow.File));
                                                }
                                            }

                                            containsFiles = true;
                                        }
                                    }
                                }
                            }

                            // Get the summary information to detect the Schema
                            using (SummaryInformation summaryInformation = new SummaryInformation(db))
                            {
                                string moduleInstallerVersionString = summaryInformation.GetProperty(14);

                                try
                                {
                                    int moduleInstallerVersion = Convert.ToInt32(moduleInstallerVersionString, CultureInfo.InvariantCulture);
                                    if (moduleInstallerVersion > outputInstallerVersion)
                                    {
                                        this.core.OnMessage(WixWarnings.InvalidHigherInstallerVersionInModule(wixMergeRow.SourceLineNumbers, wixMergeRow.Id, moduleInstallerVersion, outputInstallerVersion));
                                    }
                                }
                                catch (FormatException)
                                {
                                    throw new WixException(WixErrors.MissingOrInvalidModuleInstallerVersion(wixMergeRow.SourceLineNumbers, wixMergeRow.Id, wixMergeRow.SourceFile, moduleInstallerVersionString));
                                }
                            }
                        }
                    }
                    catch (FileNotFoundException)
                    {
                        throw new WixException(WixErrors.FileNotFound(wixMergeRow.SourceLineNumbers, wixMergeRow.SourceFile));
                    }
                    catch (Win32Exception)
                    {
                        throw new WixException(WixErrors.CannotOpenMergeModule(wixMergeRow.SourceLineNumbers, wixMergeRow.Id, wixMergeRow.SourceFile));
                    }

                    // if the module has files and creating layout
                    if (containsFiles && !this.suppressLayout)
                    {
                        bool moduleOpen = false;
                        short mergeLanguage;

                        try
                        {
                            mergeLanguage = Convert.ToInt16(wixMergeRow.Language, CultureInfo.InvariantCulture);
                        }
                        catch (System.FormatException)
                        {
                            this.core.OnMessage(WixErrors.InvalidMergeLanguage(wixMergeRow.SourceLineNumbers, wixMergeRow.Id, wixMergeRow.Language));
                            continue;
                        }

                        try
                        {
                            merge.OpenModule(wixMergeRow.SourceFile, mergeLanguage);
                            moduleOpen = true;

                            string safeMergeId = wixMergeRow.Number.ToString(CultureInfo.InvariantCulture.NumberFormat);

                            // extract the module cabinet, then explode all of the files to a temp directory
                            string moduleCabPath = String.Concat(this.TempFilesLocation, Path.DirectorySeparatorChar, safeMergeId, ".module.cab");
                            merge.ExtractCAB(moduleCabPath);

                            string mergeIdPath = String.Concat(this.TempFilesLocation, Path.DirectorySeparatorChar, "MergeId.", safeMergeId);
                            Directory.CreateDirectory(mergeIdPath);

                            using (WixExtractCab extractCab = new WixExtractCab())
                            {
                                try
                                {
                                    extractCab.Extract(moduleCabPath, mergeIdPath);
                                }
                                catch (FileNotFoundException)
                                {
                                    throw new WixException(WixErrors.CabFileDoesNotExist(moduleCabPath, wixMergeRow.SourceFile, mergeIdPath));
                                }
                                catch
                                {
                                    throw new WixException(WixErrors.CabExtractionFailed(moduleCabPath, wixMergeRow.SourceFile, mergeIdPath));
                                }
                            }
                        }
                        catch (COMException ce)
                        {
                            throw new WixException(WixErrors.UnableToOpenModule(wixMergeRow.SourceLineNumbers, wixMergeRow.SourceFile, ce.Message));
                        }
                        finally
                        {
                            if (moduleOpen)
                            {
                                merge.CloseModule();
                            }
                        }
                    }
                }
            }
        }
Esempio n. 19
0
        /// <summary>
        /// Creates a new row in the table.
        /// </summary>
        /// <param name="sourceLineNumbers">Original source lines for this row.</param>
        /// <returns>Row created in table.</returns>
        public Row CreateRow(SourceLineNumberCollection sourceLineNumbers)
        {
            Row row;
            switch (this.Name)
            {
                // TODO:  create strongly types rows here
                case "BBControl":
                    row = new BBControlRow(sourceLineNumbers, this);
                    break;
                case "Control":
                    row = new ControlRow(sourceLineNumbers, this);
                    break;
                case "File":
                    row = new FileRow(sourceLineNumbers, this);
                    break;
                case "Media":
                    row = new MediaRow(sourceLineNumbers, this);
                    break;
                case "Merge":
                    row = new MergeRow(sourceLineNumbers, this);
                    break;
                case "Property":
                    row = new PropertyRow(sourceLineNumbers, this);
                    break;
                case "Upgrade":
                    row = new UpgradeRow(sourceLineNumbers, this);
                    break;

                default:
                    row = new Row(sourceLineNumbers, this);
                    break;
            }

            this.rows.Add(row);
            return row;
        }