예제 #1
0
        /// <summary>
        /// Harvest a payload.
        /// </summary>
        /// <param name="path">The path of the payload.</param>
        /// <returns>A harvested payload.</returns>
        public Wix.RemotePayload HarvestRemotePayload(string path)
        {
            if (null == path)
            {
                throw new ArgumentNullException("path");
            }

            if (!File.Exists(path))
            {
                throw new WixException(HarvesterErrors.FileNotFound(path));
            }

            Wix.RemotePayload remotePayload;

            switch (this.packageType)
            {
            case WixBundlePackageType.Exe:
                remotePayload = new Wix.ExePackagePayload();
                break;

            case WixBundlePackageType.Msu:
                remotePayload = new Wix.MsuPackagePayload();
                break;

            default:
                throw new NotImplementedException();
            }

            var payloadSymbol = new WixBundlePayloadSymbol
            {
                SourceFile = new IntermediateFieldPathValue {
                    Path = path
                },
            };

            this.payloadHarvester.HarvestStandardInformation(payloadSymbol);

            if (payloadSymbol.FileSize.HasValue)
            {
                remotePayload.Size = payloadSymbol.FileSize.Value;
            }
            remotePayload.Hash = payloadSymbol.Hash;

            if (!String.IsNullOrEmpty(payloadSymbol.Version))
            {
                remotePayload.Version = payloadSymbol.Version;
            }

            if (!String.IsNullOrEmpty(payloadSymbol.Description))
            {
                remotePayload.Description = payloadSymbol.Description;
            }

            if (!String.IsNullOrEmpty(payloadSymbol.DisplayName))
            {
                remotePayload.ProductName = payloadSymbol.DisplayName;
            }

            return(remotePayload);
        }
예제 #2
0
        private void UpdatePayloadPackagingType(WixBundlePayloadSymbol payload)
        {
            if (!payload.Packaging.HasValue || PackagingType.Unknown == payload.Packaging)
            {
                if (!payload.Compressed.HasValue)
                {
                    payload.Packaging = this.DefaultPackaging;
                }
                else if (payload.Compressed.Value)
                {
                    payload.Packaging = PackagingType.Embedded;
                }
                else
                {
                    payload.Packaging = PackagingType.External;
                }
            }

            // Embedded payloads that are not assigned a container already are placed in the default attached
            // container.
            if (PackagingType.Embedded == payload.Packaging && String.IsNullOrEmpty(payload.ContainerRef))
            {
                payload.ContainerRef = BurnConstants.BurnDefaultAttachedContainerName;
            }
        }
예제 #3
0
        private void WritePayloadInfo(XmlTextWriter writer, WixBundlePayloadSymbol payloadSymbol, string packageId)
        {
            writer.WriteStartElement("WixPayloadProperties");

            if (!String.IsNullOrEmpty(packageId))
            {
                writer.WriteAttributeString("Package", packageId);
            }

            writer.WriteAttributeString("Payload", payloadSymbol.Id.Id);

            if (!String.IsNullOrEmpty(payloadSymbol.ContainerRef))
            {
                writer.WriteAttributeString("Container", payloadSymbol.ContainerRef);
            }

            writer.WriteAttributeString("Name", payloadSymbol.Name);
            writer.WriteAttributeString("Size", payloadSymbol.FileSize.Value.ToString(CultureInfo.InvariantCulture));

            if (!String.IsNullOrEmpty(payloadSymbol.DownloadUrl))
            {
                writer.WriteAttributeString("DownloadUrl", payloadSymbol.DownloadUrl);
            }

            writer.WriteEndElement();
        }
        private void ImportExternalCabinetAsPayloads(Database db, WixBundlePayloadSymbol packagePayload, ISet <string> payloadNames)
        {
            if (db.TableExists("Media"))
            {
                using (var view = db.OpenExecuteView("SELECT `Cabinet` FROM `Media`"))
                {
                    foreach (var cabinetRecord in view.Records)
                    {
                        var cabinet = cabinetRecord.GetString(1);

                        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...
                            var cabinetName = Path.Combine(Path.GetDirectoryName(packagePayload.Name), cabinet);

                            if (!payloadNames.Contains(cabinetName))
                            {
                                var generatedId       = this.BackendHelper.GenerateIdentifier("cab", packagePayload.Id.Id, cabinet);
                                var payloadSourceFile = this.ResolveRelatedFile(packagePayload.SourceFile.Path, packagePayload.UnresolvedSourceFile, cabinet, "Cabinet", this.Facade.PackageSymbol.SourceLineNumbers);

                                this.Section.AddSymbol(new WixGroupSymbol(this.Facade.PackageSymbol.SourceLineNumbers)
                                {
                                    ParentType = ComplexReferenceParentType.Package,
                                    ParentId   = this.Facade.PackageId,
                                    ChildType  = ComplexReferenceChildType.Payload,
                                    ChildId    = generatedId
                                });

                                this.Section.AddSymbol(new WixBundlePayloadSymbol(this.Facade.PackageSymbol.SourceLineNumbers, new Identifier(AccessModifier.Section, generatedId))
                                {
                                    Name       = cabinetName,
                                    SourceFile = new IntermediateFieldPathValue {
                                        Path = payloadSourceFile
                                    },
                                    Compressed              = packagePayload.Compressed,
                                    UnresolvedSourceFile    = cabinetName,
                                    ContainerRef            = packagePayload.ContainerRef,
                                    ContentFile             = true,
                                    DownloadUrl             = packagePayload.DownloadUrl,
                                    Packaging               = packagePayload.Packaging,
                                    ParentPackagePayloadRef = packagePayload.Id.Id,
                                });
                            }
                        }
                    }
                }
            }
        }
예제 #5
0
        private void WriteBurnManifestPayloadAttributes(XmlTextWriter writer, WixBundlePayloadSymbol payload, bool embeddedOnly, Dictionary <string, WixBundlePayloadSymbol> allPayloads)
        {
            Debug.Assert(!embeddedOnly || PackagingType.Embedded == payload.Packaging);

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

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

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

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

                if (BurnConstants.BurnUXContainerName != payload.ContainerRef)
                {
                    writer.WriteAttributeString("Container", payload.ContainerRef);
                }
                break;

            case PackagingType.External:
                var packageId   = payload.ParentPackagePayloadRef;
                var parentUrl   = payload.ParentPackagePayloadRef == null ? null : allPayloads[payload.ParentPackagePayloadRef].DownloadUrl;
                var resolvedUrl = this.ResolveUrl(payload.DownloadUrl, parentUrl, packageId, payload.Id.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;
            }
        }
예제 #6
0
        private void UpdatePayloadFileInformation(WixBundlePayloadSymbol payload, IntermediateFieldPathValue sourceFile)
        {
            var fileInfo = new FileInfo(sourceFile.Path);

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

                payload.Hash = BundleHashAlgorithm.Hash(fileInfo);
            }
            else
            {
                payload.FileSize = 0;
            }
        }
예제 #7
0
        private void UpdatePayloadFileInformation(WixBundlePayloadSymbol payload, string filePath)
        {
            var fileInfo = new FileInfo(filePath);

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

                payload.Hash = BundleHashAlgorithm.Hash(fileInfo);
            }
            else
            {
                payload.FileSize = 0;
            }
        }
예제 #8
0
        /// <inheritdoc />
        public bool HarvestStandardInformation(WixBundlePayloadSymbol payload)
        {
            var filePath = payload.SourceFile?.Path;

            if (String.IsNullOrEmpty(filePath))
            {
                return(false);
            }

            this.UpdatePayloadFileInformation(payload, filePath);

            this.UpdatePayloadVersionInformation(payload, filePath);

            return(true);
        }
예제 #9
0
        private void WriteBurnManifestUXPayload(XmlTextWriter writer, WixBundlePayloadSymbol payload)
        {
            Debug.Assert(PackagingType.Embedded == payload.Packaging);
            Debug.Assert(BurnConstants.BurnUXContainerName == payload.ContainerRef);

            writer.WriteStartElement("Payload");

            // TODO: The engine should be updated to not require FileSize, Hash, or Packaging for UX payloads since the values are never used.
            writer.WriteAttributeString("Id", payload.Id.Id);
            writer.WriteAttributeString("FilePath", payload.Name);
            writer.WriteAttributeString("FileSize", payload.FileSize.Value.ToString(CultureInfo.InvariantCulture));
            writer.WriteAttributeString("Hash", payload.Hash);
            writer.WriteAttributeString("Packaging", "embedded");
            writer.WriteAttributeString("SourcePath", payload.EmbeddedId);

            writer.WriteEndElement();
        }
예제 #10
0
        private void UpdatePayloadFileInformation(WixBundlePayloadSymbol payload, IntermediateFieldPathValue sourceFile)
        {
            var fileInfo = new FileInfo(sourceFile.Path);

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

                payload.Hash = BundleHashAlgorithm.Hash(fileInfo);

                // 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;

                        Native.NativeMethods.HashPublicKeyInfo(certificate.Handle, publicKeyIdentifierHash, ref publicKeyIdentifierHashSize);

                        var sb = new StringBuilder(((int)publicKeyIdentifierHashSize + 1) * 2);
                        for (var i = 0; i < publicKeyIdentifierHashSize; ++i)
                        {
                            sb.AppendFormat("{0:X2}", publicKeyIdentifierHash[i]);
                        }

                        payload.PublicKey  = sb.ToString();
                        payload.Thumbprint = certificate.Thumbprint;
                    }
                }
            }
            else
            {
                payload.FileSize = 0;
            }
        }
예제 #11
0
        private void UpdatePayloadVersionInformation(WixBundlePayloadSymbol payload, IntermediateFieldPathValue sourceFile)
        {
            var versionInfo = FileVersionInfo.GetVersionInfo(sourceFile.Path);

            if (null != versionInfo)
            {
                // Use the fixed version info block for the file since the resource text may not be a dotted quad.
                var 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;
            }
        }
예제 #12
0
        public WixBundlePayloadSymbol CreatePayloadSymbol(ComplexReferenceParentType parentType, string parentId, ComplexReferenceChildType previousType = ComplexReferenceChildType.Unknown, string previousId = null)
        {
            WixBundlePayloadSymbol symbol = null;

            if (parentType == ComplexReferenceParentType.Container && parentId == BurnConstants.BurnUXContainerName)
            {
                if (this.Compressed == YesNoDefaultType.No)
                {
                    this.Core.Write(WarningMessages.UxPayloadsOnlySupportEmbedding(this.SourceLineNumbers, this.SourceFile));
                }

                if (!String.IsNullOrEmpty(this.DownloadUrl))
                {
                    this.Core.Write(WarningMessages.DownloadUrlNotSupportedForBAPayloads(this.SourceLineNumbers, this.Id.Id));
                }

                this.Compressed  = YesNoDefaultType.Yes;
                this.DownloadUrl = null;
            }

            if (!this.Core.EncounteredError)
            {
                symbol = this.Core.AddSymbol(new WixBundlePayloadSymbol(this.SourceLineNumbers, this.Id)
                {
                    Name       = String.IsNullOrEmpty(this.Name) ? Path.GetFileName(this.SourceFile) : this.Name,
                    SourceFile = new IntermediateFieldPathValue {
                        Path = this.SourceFile
                    },
                    DownloadUrl          = this.DownloadUrl,
                    Compressed           = (this.Compressed == YesNoDefaultType.Yes) ? true : (this.Compressed == YesNoDefaultType.No) ? (bool?)false : null,
                    UnresolvedSourceFile = this.SourceFile, // duplicate of sourceFile but in a string column so it won't get resolved to a full path during binding.
                    DisplayName          = this.ProductName,
                    Description          = this.Description,
                    Hash     = this.Hash,
                    FileSize = this.Size,
                    Version  = this.Version,
                });

                this.Core.CreateGroupAndOrderingRows(this.SourceLineNumbers, parentType, parentId, ComplexReferenceChildType.Payload, symbol.Id.Id, previousType, previousId);
            }

            return(symbol);
        }
        private void ImportExternalCabinetAsPayloads(Dtf.Database db, WixBundlePayloadSymbol packagePayload, ISet <string> payloadNames)
        {
            if (db.Tables.Contains("Media"))
            {
                foreach (var 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...
                        var cabinetName = Path.Combine(Path.GetDirectoryName(packagePayload.Name), cabinet);

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

                            this.Section.AddSymbol(new WixBundlePayloadSymbol(this.Facade.PackageSymbol.SourceLineNumbers, new Identifier(AccessModifier.Private, generatedId))
                            {
                                Name       = cabinetName,
                                SourceFile = new IntermediateFieldPathValue {
                                    Path = payloadSourceFile
                                },
                                Compressed                = packagePayload.Compressed,
                                UnresolvedSourceFile      = cabinetName,
                                PackageRef                = packagePayload.PackageRef,
                                ContainerRef              = packagePayload.ContainerRef,
                                ContentFile               = true,
                                EnableSignatureValidation = packagePayload.EnableSignatureValidation,
                                Packaging = packagePayload.Packaging,
                                ParentPackagePayloadRef = packagePayload.Id.Id,
                            });
                        }
                    }
                }
            }
        }
예제 #14
0
        private void WriteBurnManifestPayloadAttributes(XmlTextWriter writer, WixBundlePayloadSymbol payload, bool embeddedOnly, Dictionary <string, WixBundlePayloadSymbol> allPayloads)
        {
            Debug.Assert(!embeddedOnly || PackagingType.Embedded == payload.Packaging);

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

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

            switch (payload.Packaging)
            {
            case PackagingType.Embedded:     // this means it's in a container.
                writer.WriteAttributeString("Packaging", "embedded");
                writer.WriteAttributeString("SourcePath", payload.EmbeddedId);

                if (BurnConstants.BurnUXContainerName != payload.ContainerRef)
                {
                    writer.WriteAttributeString("Container", payload.ContainerRef);
                }
                break;

            case PackagingType.External:
                if (!String.IsNullOrEmpty(payload.DownloadUrl))
                {
                    writer.WriteAttributeString("DownloadUrl", payload.DownloadUrl);
                }

                writer.WriteAttributeString("Packaging", "external");
                writer.WriteAttributeString("SourcePath", payload.Name);
                break;
            }
        }
        private void ProcessPatchXml(WixBundlePayloadSymbol packagePayload, WixBundleMspPackageSymbol mspPackage, string sourcePath)
        {
            var uniqueTargetCodes = new HashSet <string>();

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

            var doc = new XmlDocument();

            doc.LoadXml(patchXml);

            var 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.
                var targetCodeElement = node.SelectSingleNode("p:TargetProductCode", nsmgr);
                var 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
                    {
                        mspPackage.Attributes |= WixBundleMspPackageAttributes.TargetUnspecified;
                    }
                }

                var targetCode = targetCodeElement.InnerText;

                if (uniqueTargetCodes.Add(targetCode))
                {
                    this.Section.AddSymbol(new WixBundlePatchTargetCodeSymbol(packagePayload.SourceLineNumbers)
                    {
                        PackageRef = packagePayload.Id.Id,
                        TargetCode = targetCode,
                        Attributes = attributes
                    });
                }
            }

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

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

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

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

                mspPackage.PatchXml = writer.ToString();
            }
        }
예제 #16
0
        private long ImportExternalFileAsPayloadsAndReturnInstallSize(Dtf.Database db, WixBundlePayloadSymbol packagePayload, bool longNamesInImage, bool compressed, ISet <string> payloadNames)
        {
            long size = 0;

            if (db.Tables.Contains("Component") && db.Tables.Contains("Directory") && db.Tables.Contains("File"))
            {
                var directories = new Dictionary <string, IResolvedDirectory>();

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

                            var sourceName = Common.GetName(record.GetString(3), true, longNamesInImage);

                            var resolvedDirectory = this.BackendHelper.CreateResolvedDirectory(record.GetString(2), sourceName);

                            directories.Add(record.GetString(1), resolvedDirectory);
                        }
                    }
                }

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

                            // 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.
                            var compressionBit = record.GetInteger(4);
                            if (WindowsInstallerConstants.MsidbFileAttributesNoncompressed == (compressionBit & WindowsInstallerConstants.MsidbFileAttributesNoncompressed) ||
                                (!compressed && 0 == (compressionBit & WindowsInstallerConstants.MsidbFileAttributesCompressed)))
                            {
                                string fileSourcePath = this.PathResolver.GetFileSourcePath(directories, record.GetString(1), record.GetString(3), compressed, longNamesInImage);
                                var    name           = Path.Combine(Path.GetDirectoryName(packagePayload.Name), fileSourcePath);

                                if (!payloadNames.Contains(name))
                                {
                                    var generatedId       = Common.GenerateIdentifier("f", packagePayload.Id.Id, record.GetString(2));
                                    var payloadSourceFile = this.ResolveRelatedFile(packagePayload.SourceFile.Path, packagePayload.UnresolvedSourceFile, fileSourcePath, "File", this.Facade.PackageSymbol.SourceLineNumbers);

                                    this.Section.AddSymbol(new WixBundlePayloadSymbol(this.Facade.PackageSymbol.SourceLineNumbers, new Identifier(AccessModifier.Section, generatedId))
                                    {
                                        Name       = name,
                                        SourceFile = new IntermediateFieldPathValue {
                                            Path = payloadSourceFile
                                        },
                                        Compressed              = packagePayload.Compressed,
                                        UnresolvedSourceFile    = name,
                                        PackageRef              = packagePayload.PackageRef,
                                        ContainerRef            = packagePayload.ContainerRef,
                                        ContentFile             = true,
                                        Packaging               = packagePayload.Packaging,
                                        ParentPackagePayloadRef = packagePayload.Id.Id,
                                    });
                                }
                            }

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

            return(size);
        }