Пример #1
0
        private void UpdatePayloadPackagingType(WixBundlePayloadRow payload)
        {
            if (PackagingType.Unknown == payload.Packaging)
            {
                if (YesNoDefaultType.Yes == payload.Compressed)
                {
                    payload.Packaging = PackagingType.Embedded;
                }
                else if (YesNoDefaultType.No == payload.Compressed)
                {
                    payload.Packaging = PackagingType.External;
                }
                else
                {
                    payload.Packaging = this.DefaultPackaging;
                }
            }

            // Embedded payloads that are not assigned a container already are placed in the default attached
            // container.
            if (PackagingType.Embedded == payload.Packaging && String.IsNullOrEmpty(payload.Container))
            {
                payload.Container = Compiler.BurnDefaultAttachedContainerId;
            }
        }
Пример #2
0
        private void ImportExternalCabinetAsPayloads(Dtf.Database db, WixBundlePayloadRow packagePayload, ISet <string> payloadNames)
        {
            if (db.Tables.Contains("Media"))
            {
                foreach (string cabinet in db.ExecuteStringQuery("SELECT `Cabinet` FROM `Media`"))
                {
                    if (!String.IsNullOrEmpty(cabinet) && !cabinet.StartsWith("#", StringComparison.Ordinal))
                    {
                        // If we didn't find the Payload as an existing child of the package, we need to
                        // add it.  We expect the file to exist on-disk in the same relative location as
                        // the MSI expects to find it...
                        string cabinetName = Path.Combine(Path.GetDirectoryName(packagePayload.Name), cabinet);

                        if (!payloadNames.Contains(cabinetName))
                        {
                            string generatedId       = Common.GenerateIdentifier("cab", packagePayload.Id, cabinet);
                            string payloadSourceFile = FileManager.ResolveRelatedFile(packagePayload.UnresolvedSourceFile, cabinet, "Cabinet", this.Facade.Package.SourceLineNumbers, BindStage.Normal);

                            WixBundlePayloadRow payload = (WixBundlePayloadRow)this.PayloadTable.CreateRow(this.Facade.Package.SourceLineNumbers);
                            payload.Id                        = generatedId;
                            payload.Name                      = cabinetName;
                            payload.SourceFile                = payloadSourceFile;
                            payload.Compressed                = packagePayload.Compressed;
                            payload.UnresolvedSourceFile      = cabinetName;
                            payload.Package                   = packagePayload.Package;
                            payload.Container                 = packagePayload.Container;
                            payload.ContentFile               = true;
                            payload.EnableSignatureValidation = packagePayload.EnableSignatureValidation;
                            payload.Packaging                 = packagePayload.Packaging;
                            payload.ParentPackagePayload      = packagePayload.Id;
                        }
                    }
                }
            }
        }
Пример #3
0
        /// <summary>
        /// Processes the Exe packages to add properties and payloads from the Exe packages.
        /// </summary>
        public void Execute()
        {
            WixBundlePayloadRow packagePayload = this.AuthoredPayloads.Get(this.Facade.Package.PackagePayload);

            if (String.IsNullOrEmpty(this.Facade.Package.CacheId))
            {
                this.Facade.Package.CacheId = packagePayload.Hash;
            }

            this.Facade.Package.Version = packagePayload.Version;
        }
Пример #4
0
        public void Execute()
        {
            WixBundlePayloadRow packagePayload = this.AuthoredPayloads.Get(this.Facade.Package.PackagePayload);

            if (String.IsNullOrEmpty(this.Facade.Package.CacheId))
            {
                this.Facade.Package.CacheId = packagePayload.Hash;
            }

            this.Facade.Package.PerMachine = YesNoDefaultType.Yes; // MSUs are always per-machine.
        }
Пример #5
0
        private static IList <SoftwareTag> CollectPackageTags(Output bundle)
        {
            List <SoftwareTag> tags = new List <SoftwareTag>();
            Table packageTable      = bundle.Tables["WixBundlePackage"];

            if (null != packageTable)
            {
                Table payloadTable = bundle.Tables["WixBundlePayload"];
                RowDictionary <WixBundlePayloadRow> payloads = new RowDictionary <WixBundlePayloadRow>(payloadTable);

                foreach (WixBundlePackageRow row in packageTable.RowsAs <WixBundlePackageRow>())
                {
                    if (WixBundlePackageType.Msi == row.Type)
                    {
                        string packagePayloadId     = row.PackagePayload;
                        WixBundlePayloadRow payload = payloads.Get(packagePayloadId);

                        using (Database db = new Database(payload.FullFileName))
                        {
                            if (db.Tables.Contains("SoftwareIdentificationTag"))
                            {
                                using (View view = db.OpenView("SELECT `Regid`, `UniqueId`, `Type` FROM `SoftwareIdentificationTag`"))
                                {
                                    view.Execute();
                                    while (true)
                                    {
                                        using (Record record = view.Fetch())
                                        {
                                            if (null == record)
                                            {
                                                break;
                                            }

                                            TagType type = String.IsNullOrEmpty(record.GetString(3)) ? TagType.Unknown : (TagType)Enum.Parse(typeof(TagType), record.GetString(3));
                                            tags.Add(new SoftwareTag()
                                            {
                                                Regid = record.GetString(1), Id = record.GetString(2), Type = type
                                            });
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            return(tags);
        }
        public void Execute()
        {
            this.GenerateBAManifestBundleTables();

            this.GenerateBAManifestMsiFeatureTables();

            this.GenerateBAManifestPackageTables();

            this.GenerateBAManifestPayloadTables();

            string baManifestPath = Path.Combine(this.TempFilesLocation, "wix-badata.xml");

            this.CreateBootstrapperApplicationManifest(baManifestPath);

            this.BootstrapperApplicationManifestPayloadRow = this.CreateBootstrapperApplicationManifestPayloadRow(baManifestPath);
        }
Пример #7
0
        private void UpdatePayloadVersionInformation(WixBundlePayloadRow payload)
        {
            FileVersionInfo versionInfo = FileVersionInfo.GetVersionInfo(payload.SourceFile);

            if (null != versionInfo)
            {
                // Use the fixed version info block for the file since the resource text may not be a dotted quad.
                Version version = new Version(versionInfo.ProductMajorPart, versionInfo.ProductMinorPart, versionInfo.ProductBuildPart, versionInfo.ProductPrivatePart);

                if (ProcessPayloadsCommand.EmptyVersion != version)
                {
                    payload.Version = version.ToString();
                }

                payload.Description = versionInfo.FileDescription;
                payload.DisplayName = versionInfo.ProductName;
            }
        }
Пример #8
0
        /// <summary>
        /// Processes the Msp packages to add properties and payloads from the Msp packages.
        /// </summary>
        public void Execute()
        {
            WixBundlePayloadRow packagePayload = this.AuthoredPayloads.Get(this.Facade.Package.PackagePayload);

            string sourcePath = packagePayload.FullFileName;

            try
            {
                // Read data out of the msp database...
                using (Dtf.SummaryInfo sumInfo = new Dtf.SummaryInfo(sourcePath, false))
                {
                    this.Facade.MspPackage.PatchCode = sumInfo.RevisionNumber.Substring(0, 38);
                }

                using (Dtf.Database db = new Dtf.Database(sourcePath))
                {
                    if (String.IsNullOrEmpty(this.Facade.Package.DisplayName))
                    {
                        this.Facade.Package.DisplayName = ProcessMspPackageCommand.GetPatchMetadataProperty(db, "DisplayName");
                    }

                    if (String.IsNullOrEmpty(this.Facade.Package.Description))
                    {
                        this.Facade.Package.Description = ProcessMspPackageCommand.GetPatchMetadataProperty(db, "Description");
                    }

                    this.Facade.MspPackage.Manufacturer = ProcessMspPackageCommand.GetPatchMetadataProperty(db, "ManufacturerName");
                }

                this.ProcessPatchXml(packagePayload, sourcePath);
            }
            catch (Dtf.InstallerException e)
            {
                Messaging.Instance.OnMessage(WixErrors.UnableToReadPackageInformation(packagePayload.SourceLineNumbers, sourcePath, e.Message));
                return;
            }

            if (String.IsNullOrEmpty(this.Facade.Package.CacheId))
            {
                this.Facade.Package.CacheId = this.Facade.MspPackage.PatchCode;
            }
        }
Пример #9
0
        private void UpdatePayloadFileInformation(WixBundlePayloadRow payload)
        {
            FileInfo fileInfo = new FileInfo(payload.SourceFile);

            if (null != fileInfo)
            {
                payload.FileSize = (int)fileInfo.Length;

                payload.Hash = Common.GetFileHash(fileInfo.FullName);

                // Try to get the certificate if the payload is a signed file and we're not suppressing signature validation.
                if (payload.EnableSignatureValidation)
                {
                    X509Certificate2 certificate = null;
                    try
                    {
                        certificate = new X509Certificate2(fileInfo.FullName);
                    }
                    catch (CryptographicException) // we don't care about non-signed files.
                    {
                    }

                    // If there is a certificate, remember its hashed public key identifier and thumbprint.
                    if (null != certificate)
                    {
                        byte[] publicKeyIdentifierHash     = new byte[128];
                        uint   publicKeyIdentifierHashSize = (uint)publicKeyIdentifierHash.Length;

                        WixToolset.Core.Native.NativeMethods.HashPublicKeyInfo(certificate.Handle, publicKeyIdentifierHash, ref publicKeyIdentifierHashSize);
                        StringBuilder sb = new StringBuilder(((int)publicKeyIdentifierHashSize + 1) * 2);
                        for (int i = 0; i < publicKeyIdentifierHashSize; ++i)
                        {
                            sb.AppendFormat("{0:X2}", publicKeyIdentifierHash[i]);
                        }

                        payload.PublicKey  = sb.ToString();
                        payload.Thumbprint = certificate.Thumbprint;
                    }
                }
            }
        }
        private WixBundlePayloadRow CreateBootstrapperApplicationManifestPayloadRow(string baManifestPath)
        {
            Table payloadTable      = this.Output.EnsureTable(this.TableDefinitions["WixBundlePayload"]);
            WixBundlePayloadRow row = (WixBundlePayloadRow)payloadTable.CreateRow(this.BundleRow.SourceLineNumbers);

            row.Id                   = Common.GenerateIdentifier("ux", "BootstrapperApplicationData.xml");
            row.Name                 = "BootstrapperApplicationData.xml";
            row.SourceFile           = baManifestPath;
            row.Compressed           = YesNoDefaultType.Yes;
            row.UnresolvedSourceFile = baManifestPath;
            row.Container            = Compiler.BurnUXContainerId;
            row.EmbeddedId           = String.Format(CultureInfo.InvariantCulture, BurnCommon.BurnUXContainerEmbeddedIdFormat, this.LastUXPayloadIndex);
            row.Packaging            = PackagingType.Embedded;

            FileInfo fileInfo = new FileInfo(row.SourceFile);

            row.FileSize = (int)fileInfo.Length;

            row.Hash = Common.GetFileHash(fileInfo.FullName);

            return(row);
        }
Пример #11
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(SourceLineNumber sourceLineNumbers, bool add = true)
        {
            Row row;

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

            case "WixBundlePackage":
                row = new WixBundlePackageRow(sourceLineNumbers, this);
                break;

            case "WixBundleExePackage":
                row = new WixBundleExePackageRow(sourceLineNumbers, this);
                break;

            case "WixBundleMsiPackage":
                row = new WixBundleMsiPackageRow(sourceLineNumbers, this);
                break;

            case "WixBundleMspPackage":
                row = new WixBundleMspPackageRow(sourceLineNumbers, this);
                break;

            case "WixBundleMsuPackage":
                row = new WixBundleMsuPackageRow(sourceLineNumbers, this);
                break;

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

            case "WixBundleContainer":
                row = new WixBundleContainerRow(sourceLineNumbers, this);
                break;

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

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

            case "WixBundleMsiFeature":
                row = new WixBundleMsiFeatureRow(sourceLineNumbers, this);
                break;

            case "WixBundleMsiProperty":
                row = new WixBundleMsiPropertyRow(sourceLineNumbers, this);
                break;

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

            case "WixBundlePayload":
                row = new WixBundlePayloadRow(sourceLineNumbers, this);
                break;

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

            case "WixRelatedBundle":
                row = new WixRelatedBundleRow(sourceLineNumbers, this);
                break;

            case "WixBundleRelatedPackage":
                row = new WixBundleRelatedPackageRow(sourceLineNumbers, this);
                break;

            case "WixBundleRollbackBoundary":
                row = new WixBundleRollbackBoundaryRow(sourceLineNumbers, this);
                break;

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

            case "WixBundleVariable":
                row = new WixBundleVariableRow(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 "WixBundlePackageExitCode":
                row = new WixBundlePackageExitCodeRow(sourceLineNumbers, this);
                break;

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

            case "WixBundleSlipstreamMsp":
                row = new WixBundleSlipstreamMspRow(sourceLineNumbers, this);
                break;

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

            case "WixBundleCatalog":
                row = new WixBundleCatalogRow(sourceLineNumbers, this);
                break;

            case "WixChain":
                row = new WixChainRow(sourceLineNumbers, this);
                break;

            case "WixChainItem":
                row = new WixChainItemRow(sourceLineNumbers, this);
                break;

            case "WixBundlePackageCommandLine":
                row = new WixBundlePackageCommandLineRow(sourceLineNumbers, this);
                break;

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

            case "WixDeltaPatchFile":
                row = new WixDeltaPatchFileRow(sourceLineNumbers, this);
                break;

            case "WixDeltaPatchSymbolPaths":
                row = new WixDeltaPatchSymbolPathsRow(sourceLineNumbers, this);
                break;

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

            case "WixGroup":
                row = new WixGroupRow(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 "WixPayloadProperties":
                row = new WixPayloadPropertiesRow(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);
        }
Пример #12
0
        private void WriteBurnManifestPayloadAttributes(XmlTextWriter writer, WixBundlePayloadRow payload, bool embeddedOnly, Dictionary <string, WixBundlePayloadRow> allPayloads)
        {
            Debug.Assert(!embeddedOnly || PackagingType.Embedded == payload.Packaging);

            writer.WriteAttributeString("Id", payload.Id);
            writer.WriteAttributeString("FilePath", payload.Name);
            writer.WriteAttributeString("FileSize", payload.FileSize.ToString(CultureInfo.InvariantCulture));
            writer.WriteAttributeString("Hash", payload.Hash);

            if (payload.LayoutOnly)
            {
                writer.WriteAttributeString("LayoutOnly", "yes");
            }

            if (!String.IsNullOrEmpty(payload.PublicKey))
            {
                writer.WriteAttributeString("CertificateRootPublicKeyIdentifier", payload.PublicKey);
            }

            if (!String.IsNullOrEmpty(payload.Thumbprint))
            {
                writer.WriteAttributeString("CertificateRootThumbprint", payload.Thumbprint);
            }

            switch (payload.Packaging)
            {
            case PackagingType.Embedded:     // this means it's in a container.
                if (!String.IsNullOrEmpty(payload.DownloadUrl))
                {
                    Messaging.Instance.OnMessage(WixWarnings.DownloadUrlNotSupportedForEmbeddedPayloads(payload.SourceLineNumbers, payload.Id));
                }

                writer.WriteAttributeString("Packaging", "embedded");
                writer.WriteAttributeString("SourcePath", payload.EmbeddedId);

                if (Compiler.BurnUXContainerId != payload.Container)
                {
                    writer.WriteAttributeString("Container", payload.Container);
                }
                break;

            case PackagingType.External:
                string packageId   = payload.ParentPackagePayload;
                string parentUrl   = payload.ParentPackagePayload == null ? null : allPayloads[payload.ParentPackagePayload].DownloadUrl;
                string resolvedUrl = this.ResolveUrl(payload.DownloadUrl, parentUrl, packageId, payload.Id, payload.Name);
                if (!String.IsNullOrEmpty(resolvedUrl))
                {
                    writer.WriteAttributeString("DownloadUrl", resolvedUrl);
                }
                else if (!String.IsNullOrEmpty(payload.DownloadUrl))
                {
                    writer.WriteAttributeString("DownloadUrl", payload.DownloadUrl);
                }

                writer.WriteAttributeString("Packaging", "external");
                writer.WriteAttributeString("SourcePath", payload.Name);
                break;
            }

            if (!String.IsNullOrEmpty(payload.Catalog))
            {
                writer.WriteAttributeString("Catalog", payload.Catalog);
            }
        }
Пример #13
0
        private void ProcessPatchXml(WixBundlePayloadRow packagePayload, string sourcePath)
        {
            HashSet <string> uniqueTargetCodes = new HashSet <string>();

            string patchXml = Dtf.Installer.ExtractPatchXmlData(sourcePath);

            XmlDocument doc = new XmlDocument();

            doc.LoadXml(patchXml);

            XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);

            nsmgr.AddNamespace("p", "http://www.microsoft.com/msi/patch_applicability.xsd");

            // Determine target ProductCodes and/or UpgradeCodes.
            foreach (XmlNode node in doc.SelectNodes("/p:MsiPatch/p:TargetProduct", nsmgr))
            {
                // If this patch targets a product code, this is the best case.
                XmlNode targetCodeElement = node.SelectSingleNode("p:TargetProductCode", nsmgr);
                WixBundlePatchTargetCodeAttributes attributes = WixBundlePatchTargetCodeAttributes.None;

                if (ProcessMspPackageCommand.TargetsCode(targetCodeElement))
                {
                    attributes = WixBundlePatchTargetCodeAttributes.TargetsProductCode;
                }
                else // maybe targets an upgrade code?
                {
                    targetCodeElement = node.SelectSingleNode("p:UpgradeCode", nsmgr);
                    if (ProcessMspPackageCommand.TargetsCode(targetCodeElement))
                    {
                        attributes = WixBundlePatchTargetCodeAttributes.TargetsUpgradeCode;
                    }
                    else // this patch targets an unknown number of products
                    {
                        this.Facade.MspPackage.Attributes |= WixBundleMspPackageAttributes.TargetUnspecified;
                    }
                }

                string targetCode = targetCodeElement.InnerText;

                if (uniqueTargetCodes.Add(targetCode))
                {
                    WixBundlePatchTargetCodeRow row = (WixBundlePatchTargetCodeRow)this.WixBundlePatchTargetCodeTable.CreateRow(packagePayload.SourceLineNumbers);
                    row.MspPackageId = packagePayload.Id;
                    row.TargetCode   = targetCode;
                    row.Attributes   = attributes;
                }
            }

            // Suppress patch sequence data for improved performance.
            XmlNode root = doc.DocumentElement;

            foreach (XmlNode node in root.SelectNodes("p:SequenceData", nsmgr))
            {
                root.RemoveChild(node);
            }

            // Save the XML as compact as possible.
            using (StringWriter writer = new StringWriter())
            {
                XmlWriterSettings settings = new XmlWriterSettings()
                {
                    Encoding        = ProcessMspPackageCommand.XmlOutputEncoding,
                    Indent          = false,
                    NewLineChars    = string.Empty,
                    NewLineHandling = NewLineHandling.Replace,
                };

                using (XmlWriter xmlWriter = XmlWriter.Create(writer, settings))
                {
                    doc.WriteTo(xmlWriter);
                }

                this.Facade.MspPackage.PatchXml = writer.ToString();
            }
        }
Пример #14
0
        public void Execute()
        {
            throw new NotImplementedException();
#if TODO
            this.FileTransfers    = Enumerable.Empty <FileTransfer>();
            this.ContentFilePaths = Enumerable.Empty <string>();

            // First look for data we expect to find... Chain, WixGroups, etc.

            // We shouldn't really get past the linker phase if there are
            // no group items... that means that there's no UX, no Chain,
            // *and* no Containers!
            Table chainPackageTable = this.GetRequiredTable("WixBundlePackage");

            Table wixGroupTable = this.GetRequiredTable("WixGroup");

            // Ensure there is one and only one row in the WixBundle table.
            // The compiler and linker behavior should have colluded to get
            // this behavior.
            WixBundleRow bundleRow = (WixBundleRow)this.GetSingleRowTable("WixBundle");

            bundleRow.PerMachine = true; // default to per-machine but the first-per user package wil flip the bundle per-user.

            // Ensure there is one and only one row in the WixBootstrapperApplication table.
            // The compiler and linker behavior should have colluded to get
            // this behavior.
            Row baRow = this.GetSingleRowTable("WixBootstrapperApplication");

            // Ensure there is one and only one row in the WixChain table.
            // The compiler and linker behavior should have colluded to get
            // this behavior.
            WixChainRow chainRow = (WixChainRow)this.GetSingleRowTable("WixChain");

            if (Messaging.Instance.EncounteredError)
            {
                return;
            }

            // If there are any fields to resolve later, create the cache to populate during bind.
            IDictionary <string, string> variableCache = null;
            if (this.DelayedFields.Any())
            {
                variableCache = new Dictionary <string, string>(StringComparer.InvariantCultureIgnoreCase);
            }

            // TODO: Although the WixSearch tables are defined in the Util extension,
            // the Bundle Binder has to know all about them. We hope to revisit all
            // of this in the 4.0 timeframe.
            IEnumerable <WixSearchInfo> orderedSearches = this.OrderSearches();

            // Extract files that come from cabinet files (this does not extract files from merge modules).
            {
                var extractEmbeddedFilesCommand = new ExtractEmbeddedFilesCommand();
                extractEmbeddedFilesCommand.FilesWithEmbeddedFiles = ExpectedEmbeddedFiles;
                extractEmbeddedFilesCommand.Execute();
            }

            // Get the explicit payloads.
            RowDictionary <WixBundlePayloadRow> payloads = new RowDictionary <WixBundlePayloadRow>(this.Output.Tables["WixBundlePayload"]);

            // Update explicitly authored payloads with their parent package and container (as appropriate)
            // to make it easier to gather the payloads later.
            foreach (WixGroupRow row in wixGroupTable.RowsAs <WixGroupRow>())
            {
                if (ComplexReferenceChildType.Payload == row.ChildType)
                {
                    WixBundlePayloadRow payload = payloads.Get(row.ChildId);

                    if (ComplexReferenceParentType.Package == row.ParentType)
                    {
                        Debug.Assert(String.IsNullOrEmpty(payload.Package));
                        payload.Package = row.ParentId;
                    }
                    else if (ComplexReferenceParentType.Container == row.ParentType)
                    {
                        Debug.Assert(String.IsNullOrEmpty(payload.Container));
                        payload.Container = row.ParentId;
                    }
                    else if (ComplexReferenceParentType.Layout == row.ParentType)
                    {
                        payload.LayoutOnly = true;
                    }
                }
            }

            List <FileTransfer> fileTransfers = new List <FileTransfer>();
            string layoutDirectory            = Path.GetDirectoryName(this.OutputPath);

            // Process the explicitly authored payloads.
            ISet <string> processedPayloads;
            {
                ProcessPayloadsCommand command = new ProcessPayloadsCommand();
                command.Payloads         = payloads.Values;
                command.DefaultPackaging = bundleRow.DefaultPackagingType;
                command.LayoutDirectory  = layoutDirectory;
                command.Execute();

                fileTransfers.AddRange(command.FileTransfers);

                processedPayloads = new HashSet <string>(payloads.Keys);
            }

            IDictionary <string, PackageFacade> facades;
            {
                GetPackageFacadesCommand command = new GetPackageFacadesCommand();
                command.PackageTable    = chainPackageTable;
                command.ExePackageTable = this.Output.Tables["WixBundleExePackage"];
                command.MsiPackageTable = this.Output.Tables["WixBundleMsiPackage"];
                command.MspPackageTable = this.Output.Tables["WixBundleMspPackage"];
                command.MsuPackageTable = this.Output.Tables["WixBundleMsuPackage"];
                command.Execute();

                facades = command.PackageFacades;
            }

            // Process each package facade. Note this is likely to add payloads and other rows to tables so
            // note that any indexes created above may be out of date now.
            foreach (PackageFacade facade in facades.Values)
            {
                switch (facade.Package.Type)
                {
                case WixBundlePackageType.Exe:
                {
                    ProcessExePackageCommand command = new ProcessExePackageCommand();
                    command.AuthoredPayloads = payloads;
                    command.Facade           = facade;
                    command.Execute();

                    // ? variableCache.Add(String.Concat("packageManufacturer.", facade.Package.WixChainItemId), facade.ExePackage.Manufacturer);
                }
                break;

                case WixBundlePackageType.Msi:
                {
                    var command = new ProcessMsiPackageCommand();
                    command.AuthoredPayloads    = payloads;
                    command.Facade              = facade;
                    command.BackendExtensions   = this.BackendExtensions;
                    command.MsiFeatureTable     = this.Output.EnsureTable(this.TableDefinitions["WixBundleMsiFeature"]);
                    command.MsiPropertyTable    = this.Output.EnsureTable(this.TableDefinitions["WixBundleMsiProperty"]);
                    command.PayloadTable        = this.Output.Tables["WixBundlePayload"];
                    command.RelatedPackageTable = this.Output.EnsureTable(this.TableDefinitions["WixBundleRelatedPackage"]);
                    command.Execute();

                    if (null != variableCache)
                    {
                        variableCache.Add(String.Concat("packageLanguage.", facade.Package.WixChainItemId), facade.MsiPackage.ProductLanguage.ToString());

                        if (null != facade.MsiPackage.Manufacturer)
                        {
                            variableCache.Add(String.Concat("packageManufacturer.", facade.Package.WixChainItemId), facade.MsiPackage.Manufacturer);
                        }
                    }
                }
                break;

                case WixBundlePackageType.Msp:
                {
                    ProcessMspPackageCommand command = new ProcessMspPackageCommand();
                    command.AuthoredPayloads = payloads;
                    command.Facade           = facade;
                    command.WixBundlePatchTargetCodeTable = this.Output.EnsureTable(this.TableDefinitions["WixBundlePatchTargetCode"]);
                    command.Execute();
                }
                break;

                case WixBundlePackageType.Msu:
                {
                    ProcessMsuPackageCommand command = new ProcessMsuPackageCommand();
                    command.Facade = facade;
                    command.Execute();
                }
                break;
                }

                if (null != variableCache)
                {
                    BindBundleCommand.PopulatePackageVariableCache(facade.Package, variableCache);
                }
            }

            // Reindex the payloads now that all the payloads (minus the manifest payloads that will be created later)
            // are present.
            payloads = new RowDictionary <WixBundlePayloadRow>(this.Output.Tables["WixBundlePayload"]);

            // Process the payloads that were added by processing the packages.
            {
                ProcessPayloadsCommand command = new ProcessPayloadsCommand();
                command.Payloads         = payloads.Values.Where(r => !processedPayloads.Contains(r.Id)).ToList();
                command.DefaultPackaging = bundleRow.DefaultPackagingType;
                command.LayoutDirectory  = layoutDirectory;
                command.Execute();

                fileTransfers.AddRange(command.FileTransfers);

                processedPayloads = null;
            }

            // Set the package metadata from the payloads now that we have the complete payload information.
            ILookup <string, WixBundlePayloadRow> payloadsByPackage = payloads.Values.ToLookup(p => p.Package);

            {
                foreach (PackageFacade facade in facades.Values)
                {
                    facade.Package.Size = 0;

                    IEnumerable <WixBundlePayloadRow> packagePayloads = payloadsByPackage[facade.Package.WixChainItemId];

                    foreach (WixBundlePayloadRow payload in packagePayloads)
                    {
                        facade.Package.Size += payload.FileSize;
                    }

                    if (!facade.Package.InstallSize.HasValue)
                    {
                        facade.Package.InstallSize = facade.Package.Size;
                    }

                    WixBundlePayloadRow packagePayload = payloads[facade.Package.PackagePayload];

                    if (String.IsNullOrEmpty(facade.Package.Description))
                    {
                        facade.Package.Description = packagePayload.Description;
                    }

                    if (String.IsNullOrEmpty(facade.Package.DisplayName))
                    {
                        facade.Package.DisplayName = packagePayload.DisplayName;
                    }
                }
            }


            // Give the UX payloads their embedded IDs...
            int uxPayloadIndex = 0;
            {
                foreach (WixBundlePayloadRow payload in payloads.Values.Where(p => Compiler.BurnUXContainerId == p.Container))
                {
                    // In theory, UX payloads could be embedded in the UX CAB, external to the bundle EXE, or even
                    // downloaded. The current engine requires the UX to be fully present before any downloading starts,
                    // so that rules out downloading. Also, the burn engine does not currently copy external UX payloads
                    // into the temporary UX directory correctly, so we don't allow external either.
                    if (PackagingType.Embedded != payload.Packaging)
                    {
                        Messaging.Instance.OnMessage(WixWarnings.UxPayloadsOnlySupportEmbedding(payload.SourceLineNumbers, payload.FullFileName));
                        payload.Packaging = PackagingType.Embedded;
                    }

                    payload.EmbeddedId = String.Format(CultureInfo.InvariantCulture, BurnCommon.BurnUXContainerEmbeddedIdFormat, uxPayloadIndex);
                    ++uxPayloadIndex;
                }

                if (0 == uxPayloadIndex)
                {
                    // If we didn't get any UX payloads, it's an error!
                    throw new WixException(WixErrors.MissingBundleInformation("BootstrapperApplication"));
                }

                // Give the embedded payloads without an embedded id yet an embedded id.
                int payloadIndex = 0;
                foreach (WixBundlePayloadRow payload in payloads.Values)
                {
                    Debug.Assert(PackagingType.Unknown != payload.Packaging);

                    if (PackagingType.Embedded == payload.Packaging && String.IsNullOrEmpty(payload.EmbeddedId))
                    {
                        payload.EmbeddedId = String.Format(CultureInfo.InvariantCulture, BurnCommon.BurnAttachedContainerEmbeddedIdFormat, payloadIndex);
                        ++payloadIndex;
                    }
                }
            }

            // Determine patches to automatically slipstream.
            {
                AutomaticallySlipstreamPatchesCommand command = new AutomaticallySlipstreamPatchesCommand();
                command.PackageFacades                = facades.Values;
                command.SlipstreamMspTable            = this.Output.EnsureTable(this.TableDefinitions["WixBundleSlipstreamMsp"]);
                command.WixBundlePatchTargetCodeTable = this.Output.EnsureTable(this.TableDefinitions["WixBundlePatchTargetCode"]);
                command.Execute();
            }

            // If catalog files exist, non-embedded payloads should validate with the catalogs.
            IEnumerable <WixBundleCatalogRow> catalogs = this.Output.Tables["WixBundleCatalog"].RowsAs <WixBundleCatalogRow>();

            if (catalogs.Any())
            {
                VerifyPayloadsWithCatalogCommand command = new VerifyPayloadsWithCatalogCommand();
                command.Catalogs = catalogs;
                command.Payloads = payloads.Values;
                command.Execute();
            }

            if (Messaging.Instance.EncounteredError)
            {
                return;
            }

            IEnumerable <PackageFacade> orderedFacades;
            IEnumerable <WixBundleRollbackBoundaryRow> boundaries;
            {
                OrderPackagesAndRollbackBoundariesCommand command = new OrderPackagesAndRollbackBoundariesCommand();
                command.Boundaries     = new RowDictionary <WixBundleRollbackBoundaryRow>(this.Output.Tables["WixBundleRollbackBoundary"]);
                command.PackageFacades = facades;
                command.WixGroupTable  = wixGroupTable;
                command.Execute();

                orderedFacades = command.OrderedPackageFacades;
                boundaries     = command.UsedRollbackBoundaries;
            }

            // Resolve any delayed fields before generating the manifest.
            if (this.DelayedFields.Any())
            {
                var resolveDelayedFieldsCommand = new ResolveDelayedFieldsCommand();
                resolveDelayedFieldsCommand.OutputType         = this.Output.Type;
                resolveDelayedFieldsCommand.DelayedFields      = this.DelayedFields;
                resolveDelayedFieldsCommand.ModularizationGuid = null;
                resolveDelayedFieldsCommand.VariableCache      = variableCache;
                resolveDelayedFieldsCommand.Execute();
            }

            // Set the overridable bundle provider key.
            this.SetBundleProviderKey(this.Output, bundleRow);

            // Import or generate dependency providers for packages in the manifest.
            this.ProcessDependencyProviders(this.Output, facades);

            // Update the bundle per-machine/per-user scope based on the chained packages.
            this.ResolveBundleInstallScope(bundleRow, orderedFacades);

            // Generate the core-defined BA manifest tables...
            {
                CreateBootstrapperApplicationManifestCommand command = new CreateBootstrapperApplicationManifestCommand();
                command.BundleRow          = bundleRow;
                command.ChainPackages      = orderedFacades;
                command.LastUXPayloadIndex = uxPayloadIndex;
                command.MsiFeatures        = this.Output.Tables["WixBundleMsiFeature"].RowsAs <WixBundleMsiFeatureRow>();
                command.Output             = this.Output;
                command.Payloads           = payloads;
                command.TableDefinitions   = this.TableDefinitions;
                command.TempFilesLocation  = this.IntermediateFolder;
                command.Execute();

                WixBundlePayloadRow baManifestPayload = command.BootstrapperApplicationManifestPayloadRow;
                payloads.Add(baManifestPayload);
            }

            //foreach (BinderExtension extension in this.Extensions)
            //{
            //    extension.PostBind(this.Context);
            //}

            // Create all the containers except the UX container first so the manifest (that goes in the UX container)
            // can contain all size and hash information about the non-UX containers.
            RowDictionary <WixBundleContainerRow> containers = new RowDictionary <WixBundleContainerRow>(this.Output.Tables["WixBundleContainer"]);

            ILookup <string, WixBundlePayloadRow> payloadsByContainer = payloads.Values.ToLookup(p => p.Container);

            int attachedContainerIndex = 1; // count starts at one because UX container is "0".

            IEnumerable <WixBundlePayloadRow> uxContainerPayloads = Enumerable.Empty <WixBundlePayloadRow>();

            foreach (WixBundleContainerRow container in containers.Values)
            {
                IEnumerable <WixBundlePayloadRow> containerPayloads = payloadsByContainer[container.Id];

                if (!containerPayloads.Any())
                {
                    if (container.Id != Compiler.BurnDefaultAttachedContainerId)
                    {
                        // TODO: display warning that we're ignoring container that ended up with no paylods in it.
                    }
                }
                else if (Compiler.BurnUXContainerId == container.Id)
                {
                    container.WorkingPath            = Path.Combine(this.IntermediateFolder, container.Name);
                    container.AttachedContainerIndex = 0;

                    // Gather the list of UX payloads but ensure the BootstrapperApplication Payload is the first
                    // in the list since that is the Payload that Burn attempts to load.
                    List <WixBundlePayloadRow> uxPayloads = new List <WixBundlePayloadRow>();

                    string baPayloadId = baRow.FieldAsString(0);

                    foreach (WixBundlePayloadRow uxPayload in containerPayloads)
                    {
                        if (uxPayload.Id == baPayloadId)
                        {
                            uxPayloads.Insert(0, uxPayload);
                        }
                        else
                        {
                            uxPayloads.Add(uxPayload);
                        }
                    }

                    uxContainerPayloads = uxPayloads;
                }
                else
                {
                    container.WorkingPath = Path.Combine(this.IntermediateFolder, container.Name);

                    // Add detached containers to the list of file transfers.
                    if (ContainerType.Detached == container.Type)
                    {
                        FileTransfer transfer;
                        if (FileTransfer.TryCreate(container.WorkingPath, Path.Combine(layoutDirectory, container.Name), true, "Container", container.SourceLineNumbers, out transfer))
                        {
                            transfer.Built = true;
                            fileTransfers.Add(transfer);
                        }
                    }
                    else // update the attached container index.
                    {
                        Debug.Assert(ContainerType.Attached == container.Type);

                        container.AttachedContainerIndex = attachedContainerIndex;
                        ++attachedContainerIndex;
                    }

                    this.CreateContainer(container, containerPayloads, null);
                }
            }

            // Create the bundle manifest then UX container.
            string manifestPath = Path.Combine(this.IntermediateFolder, "bundle-manifest.xml");
            {
                var command = new CreateBurnManifestCommand();
                command.BackendExtensions = this.BackendExtensions;
                command.Output            = this.Output;

                command.BundleInfo          = bundleRow;
                command.Chain               = chainRow;
                command.Containers          = containers;
                command.Catalogs            = catalogs;
                command.ExecutableName      = Path.GetFileName(this.OutputPath);
                command.OrderedPackages     = orderedFacades;
                command.OutputPath          = manifestPath;
                command.RollbackBoundaries  = boundaries;
                command.OrderedSearches     = orderedSearches;
                command.Payloads            = payloads;
                command.UXContainerPayloads = uxContainerPayloads;
                command.Execute();
            }

            WixBundleContainerRow uxContainer = containers[Compiler.BurnUXContainerId];
            this.CreateContainer(uxContainer, uxContainerPayloads, manifestPath);

            // Copy the burn.exe to a writable location then mark it to be moved to its final build location. Note
            // that today, the x64 Burn uses the x86 stub.
            string stubPlatform = (Platform.X64 == bundleRow.Platform) ? "x86" : bundleRow.Platform.ToString();

            string stubFile       = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), stubPlatform, "burn.exe");
            string bundleTempPath = Path.Combine(this.IntermediateFolder, Path.GetFileName(this.OutputPath));

            Messaging.Instance.OnMessage(WixVerboses.GeneratingBundle(bundleTempPath, stubFile));

            string bundleFilename = Path.GetFileName(this.OutputPath);
            if ("setup.exe".Equals(bundleFilename, StringComparison.OrdinalIgnoreCase))
            {
                Messaging.Instance.OnMessage(WixErrors.InsecureBundleFilename(bundleFilename));
            }

            FileTransfer bundleTransfer;
            if (FileTransfer.TryCreate(bundleTempPath, this.OutputPath, true, "Bundle", bundleRow.SourceLineNumbers, out bundleTransfer))
            {
                bundleTransfer.Built = true;
                fileTransfers.Add(bundleTransfer);
            }

            File.Copy(stubFile, bundleTempPath, true);
            File.SetAttributes(bundleTempPath, FileAttributes.Normal);

            this.UpdateBurnResources(bundleTempPath, this.OutputPath, bundleRow);

            // Update the .wixburn section to point to at the UX and attached container(s) then attach the containers
            // if they should be attached.
            using (BurnWriter writer = BurnWriter.Open(bundleTempPath))
            {
                FileInfo burnStubFile = new FileInfo(bundleTempPath);
                writer.InitializeBundleSectionData(burnStubFile.Length, bundleRow.BundleId);

                // Always attach the UX container first
                writer.AppendContainer(uxContainer.WorkingPath, BurnWriter.Container.UX);

                // Now append all other attached containers
                foreach (WixBundleContainerRow container in containers.Values)
                {
                    if (ContainerType.Attached == container.Type)
                    {
                        // The container was only created if it had payloads.
                        if (!String.IsNullOrEmpty(container.WorkingPath) && Compiler.BurnUXContainerId != container.Id)
                        {
                            writer.AppendContainer(container.WorkingPath, BurnWriter.Container.Attached);
                        }
                    }
                }
            }

            if (null != this.PdbFile)
            {
                Pdb pdb = new Pdb();
                pdb.Output = Output;
                pdb.Save(this.PdbFile);
            }

            this.FileTransfers    = fileTransfers;
            this.ContentFilePaths = payloads.Values.Where(p => p.ContentFile).Select(p => p.FullFileName).ToList();
        }
Пример #15
0
        private long ImportExternalFileAsPayloadsAndReturnInstallSize(Dtf.Database db, WixBundlePayloadRow packagePayload, bool longNamesInImage, bool compressed, ISet <string> payloadNames)
        {
            long size = 0;

            if (db.Tables.Contains("Component") && db.Tables.Contains("Directory") && db.Tables.Contains("File"))
            {
                Hashtable directories = new Hashtable();

                // Load up the directory hash table so we will be able to resolve source paths
                // for files in the MSI database.
                using (Dtf.View view = db.OpenView("SELECT `Directory`, `Directory_Parent`, `DefaultDir` FROM `Directory`"))
                {
                    view.Execute();
                    while (true)
                    {
                        using (Dtf.Record record = view.Fetch())
                        {
                            if (null == record)
                            {
                                break;
                            }

                            string sourceName = Installer.GetName(record.GetString(3), true, longNamesInImage);
                            directories.Add(record.GetString(1), new ResolvedDirectory(record.GetString(2), sourceName));
                        }
                    }
                }

                // Resolve the source paths to external files and add each file size to the total
                // install size of the package.
                using (Dtf.View view = db.OpenView("SELECT `Directory_`, `File`, `FileName`, `File`.`Attributes`, `FileSize` FROM `Component`, `File` WHERE `Component`.`Component`=`File`.`Component_`"))
                {
                    view.Execute();
                    while (true)
                    {
                        using (Dtf.Record record = view.Fetch())
                        {
                            if (null == record)
                            {
                                break;
                            }

                            // Skip adding the loose files as payloads if it was suppressed.
                            if (!this.Facade.MsiPackage.SuppressLooseFilePayloadGeneration)
                            {
                                // If the file is explicitly uncompressed or the MSI is uncompressed and the file is not
                                // explicitly marked compressed then this is an external file.
                                if (MsiInterop.MsidbFileAttributesNoncompressed == (record.GetInteger(4) & MsiInterop.MsidbFileAttributesNoncompressed) ||
                                    (!compressed && 0 == (record.GetInteger(4) & MsiInterop.MsidbFileAttributesCompressed)))
                                {
                                    string fileSourcePath = Binder.GetFileSourcePath(directories, record.GetString(1), record.GetString(3), compressed, longNamesInImage);
                                    string name           = Path.Combine(Path.GetDirectoryName(packagePayload.Name), fileSourcePath);

                                    if (!payloadNames.Contains(name))
                                    {
                                        string generatedId       = Common.GenerateIdentifier("f", packagePayload.Id, record.GetString(2));
                                        string payloadSourceFile = FileManager.ResolveRelatedFile(packagePayload.UnresolvedSourceFile, fileSourcePath, "File", this.Facade.Package.SourceLineNumbers, BindStage.Normal);

                                        WixBundlePayloadRow payload = (WixBundlePayloadRow)this.PayloadTable.CreateRow(this.Facade.Package.SourceLineNumbers);
                                        payload.Id                        = generatedId;
                                        payload.Name                      = name;
                                        payload.SourceFile                = payloadSourceFile;
                                        payload.Compressed                = packagePayload.Compressed;
                                        payload.UnresolvedSourceFile      = name;
                                        payload.Package                   = packagePayload.Package;
                                        payload.Container                 = packagePayload.Container;
                                        payload.ContentFile               = true;
                                        payload.EnableSignatureValidation = packagePayload.EnableSignatureValidation;
                                        payload.Packaging                 = packagePayload.Packaging;
                                        payload.ParentPackagePayload      = packagePayload.Id;
                                    }
                                }
                            }

                            size += record.GetInteger(5);
                        }
                    }
                }
            }

            return(size);
        }
Пример #16
0
        /// <summary>
        /// Processes the MSI packages to add properties and payloads from the MSI packages.
        /// </summary>
        public void Execute()
        {
            WixBundlePayloadRow packagePayload = this.AuthoredPayloads.Get(this.Facade.Package.PackagePayload);

            string sourcePath       = packagePayload.FullFileName;
            bool   longNamesInImage = false;
            bool   compressed       = false;
            bool   x64 = false;

            try
            {
                // Read data out of the msi database...
                using (Dtf.SummaryInfo sumInfo = new Dtf.SummaryInfo(sourcePath, false))
                {
                    // 1 is the Word Count summary information stream bit that means
                    // the MSI uses short file names when set. We care about long file
                    // names so check when the bit is not set.
                    longNamesInImage = 0 == (sumInfo.WordCount & 1);

                    // 2 is the Word Count summary information stream bit that means
                    // files are compressed in the MSI by default when the bit is set.
                    compressed = 2 == (sumInfo.WordCount & 2);

                    x64 = (sumInfo.Template.Contains("x64") || sumInfo.Template.Contains("Intel64"));

                    // 8 is the Word Count summary information stream bit that means
                    // "Elevated privileges are not required to install this package."
                    // in MSI 4.5 and below, if this bit is 0, elevation is required.
                    this.Facade.Package.PerMachine = (0 == (sumInfo.WordCount & 8)) ? YesNoDefaultType.Yes : YesNoDefaultType.No;
                    this.Facade.Package.x64        = x64 ? YesNoType.Yes : YesNoType.No;
                }

                using (Dtf.Database db = new Dtf.Database(sourcePath))
                {
                    this.Facade.MsiPackage.ProductCode     = ProcessMsiPackageCommand.GetProperty(db, "ProductCode");
                    this.Facade.MsiPackage.UpgradeCode     = ProcessMsiPackageCommand.GetProperty(db, "UpgradeCode");
                    this.Facade.MsiPackage.Manufacturer    = ProcessMsiPackageCommand.GetProperty(db, "Manufacturer");
                    this.Facade.MsiPackage.ProductLanguage = Convert.ToInt32(ProcessMsiPackageCommand.GetProperty(db, "ProductLanguage"), CultureInfo.InvariantCulture);
                    this.Facade.MsiPackage.ProductVersion  = ProcessMsiPackageCommand.GetProperty(db, "ProductVersion");

                    if (!Common.IsValidModuleOrBundleVersion(this.Facade.MsiPackage.ProductVersion))
                    {
                        // not a proper .NET version (e.g., five fields); can we get a valid four-part version number?
                        string   version      = null;
                        string[] versionParts = this.Facade.MsiPackage.ProductVersion.Split('.');
                        int      count        = versionParts.Length;
                        if (0 < count)
                        {
                            version = versionParts[0];
                            for (int i = 1; i < 4 && i < count; ++i)
                            {
                                version = String.Concat(version, ".", versionParts[i]);
                            }
                        }

                        if (!String.IsNullOrEmpty(version) && Common.IsValidModuleOrBundleVersion(version))
                        {
                            Messaging.Instance.OnMessage(WixWarnings.VersionTruncated(this.Facade.Package.SourceLineNumbers, this.Facade.MsiPackage.ProductVersion, sourcePath, version));
                            this.Facade.MsiPackage.ProductVersion = version;
                        }
                        else
                        {
                            Messaging.Instance.OnMessage(WixErrors.InvalidProductVersion(this.Facade.Package.SourceLineNumbers, this.Facade.MsiPackage.ProductVersion, sourcePath));
                        }
                    }

                    if (String.IsNullOrEmpty(this.Facade.Package.CacheId))
                    {
                        this.Facade.Package.CacheId = String.Format("{0}v{1}", this.Facade.MsiPackage.ProductCode, this.Facade.MsiPackage.ProductVersion);
                    }

                    if (String.IsNullOrEmpty(this.Facade.Package.DisplayName))
                    {
                        this.Facade.Package.DisplayName = ProcessMsiPackageCommand.GetProperty(db, "ProductName");
                    }

                    if (String.IsNullOrEmpty(this.Facade.Package.Description))
                    {
                        this.Facade.Package.Description = ProcessMsiPackageCommand.GetProperty(db, "ARPCOMMENTS");
                    }

                    ISet <string> payloadNames = this.GetPayloadTargetNames();

                    ISet <string> msiPropertyNames = this.GetMsiPropertyNames();

                    this.SetPerMachineAppropriately(db, sourcePath);

                    // Ensure the MSI package is appropriately marked visible or not.
                    this.SetPackageVisibility(db, msiPropertyNames);

                    // Unless the MSI or setup code overrides the default, set MSIFASTINSTALL for best performance.
                    if (!msiPropertyNames.Contains("MSIFASTINSTALL") && !ProcessMsiPackageCommand.HasProperty(db, "MSIFASTINSTALL"))
                    {
                        this.AddMsiProperty("MSIFASTINSTALL", "7");
                    }

                    this.CreateRelatedPackages(db);

                    // If feature selection is enabled, represent the Feature table in the manifest.
                    if (this.Facade.MsiPackage.EnableFeatureSelection)
                    {
                        this.CreateMsiFeatures(db);
                    }

                    // Add all external cabinets as package payloads.
                    this.ImportExternalCabinetAsPayloads(db, packagePayload, payloadNames);

                    // Add all external files as package payloads and calculate the total install size as the rollup of
                    // File table's sizes.
                    this.Facade.Package.InstallSize = this.ImportExternalFileAsPayloadsAndReturnInstallSize(db, packagePayload, longNamesInImage, compressed, payloadNames);

                    // Add all dependency providers from the MSI.
                    this.ImportDependencyProviders(db);
                }
            }
            catch (Dtf.InstallerException e)
            {
                Messaging.Instance.OnMessage(WixErrors.UnableToReadPackageInformation(this.Facade.Package.SourceLineNumbers, sourcePath, e.Message));
            }
        }
        private void GenerateBAManifestPackageTables()
        {
            Table wixPackagePropertiesTable = this.Output.EnsureTable(this.TableDefinitions["WixPackageProperties"]);

            foreach (PackageFacade package in this.ChainPackages)
            {
                WixBundlePayloadRow packagePayload = this.Payloads[package.Package.PackagePayload];

                Row row = wixPackagePropertiesTable.CreateRow(package.Package.SourceLineNumbers);
                row[0]  = package.Package.WixChainItemId;
                row[1]  = (YesNoType.Yes == package.Package.Vital) ? "yes" : "no";
                row[2]  = package.Package.DisplayName;
                row[3]  = package.Package.Description;
                row[4]  = package.Package.Size.ToString(CultureInfo.InvariantCulture);              // TODO: DownloadSize (compressed) (what does this mean when it's embedded?)
                row[5]  = package.Package.Size.ToString(CultureInfo.InvariantCulture);              // Package.Size (uncompressed)
                row[6]  = package.Package.InstallSize.Value.ToString(CultureInfo.InvariantCulture); // InstallSize (required disk space)
                row[7]  = package.Package.Type.ToString(CultureInfo.InvariantCulture);
                row[8]  = package.Package.Permanent ? "yes" : "no";
                row[9]  = package.Package.LogPathVariable;
                row[10] = package.Package.RollbackLogPathVariable;
                row[11] = (PackagingType.Embedded == packagePayload.Packaging) ? "yes" : "no";

                if (WixBundlePackageType.Msi == package.Package.Type)
                {
                    row[12] = package.MsiPackage.DisplayInternalUI ? "yes" : "no";

                    if (!String.IsNullOrEmpty(package.MsiPackage.ProductCode))
                    {
                        row[13] = package.MsiPackage.ProductCode;
                    }

                    if (!String.IsNullOrEmpty(package.MsiPackage.UpgradeCode))
                    {
                        row[14] = package.MsiPackage.UpgradeCode;
                    }
                }
                else if (WixBundlePackageType.Msp == package.Package.Type)
                {
                    row[12] = package.MspPackage.DisplayInternalUI ? "yes" : "no";

                    if (!String.IsNullOrEmpty(package.MspPackage.PatchCode))
                    {
                        row[13] = package.MspPackage.PatchCode;
                    }
                }

                if (!String.IsNullOrEmpty(package.Package.Version))
                {
                    row[15] = package.Package.Version;
                }

                if (!String.IsNullOrEmpty(package.Package.InstallCondition))
                {
                    row[16] = package.Package.InstallCondition;
                }

                switch (package.Package.Cache)
                {
                case YesNoAlwaysType.No:
                    row[17] = "no";
                    break;

                case YesNoAlwaysType.Yes:
                    row[17] = "yes";
                    break;

                case YesNoAlwaysType.Always:
                    row[17] = "always";
                    break;
                }
            }
        }