From 581c320e04949300d6c3bee71fb5fc1a557f9263 Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Wed, 16 Mar 2022 10:30:35 -0700 Subject: Warn when an MSI or cabinet installed by an MSI is too large Fixes 6408 --- src/api/wix/WixToolset.Data/WarningMessages.cs | 11 +++++++++++ .../Bundles/ProcessMsiPackageCommand.cs | 20 ++++++++++++++++++++ .../Bind/BindDatabaseCommand.cs | 13 +++++++++++++ .../Bind/CabinetBuilder.cs | 13 ++++++++++++- .../Bind/CabinetWorkItem.cs | 17 ++++++++--------- .../Bind/CreateCabinetsCommand.cs | 2 +- 6 files changed, 65 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/api/wix/WixToolset.Data/WarningMessages.cs b/src/api/wix/WixToolset.Data/WarningMessages.cs index f555fd93..0c026b68 100644 --- a/src/api/wix/WixToolset.Data/WarningMessages.cs +++ b/src/api/wix/WixToolset.Data/WarningMessages.cs @@ -673,6 +673,16 @@ namespace WixToolset.Data return Message(null, Ids.InvalidEnvironmentVariable, "The {0} environment variable is set to an invalid value of '{1}'. The default value '{2}' will be used instead.", environmentVariable, value, defaultValue); } + public static Message WindowsInstallerFileTooLarge(SourceLineNumber sourceLineNumbers, string path, string fileDescription) + { + if (String.IsNullOrEmpty(fileDescription)) + { + fileDescription = "MSI or cabinet"; + } + + return Message(sourceLineNumbers, Ids.WindowsInstallerFileTooLarge, "The Windows Installer does not support {0} files larger than 2GB in size. Reduce the size or number of files embedded in '{1}' or the installation will likely fail with an unexpected error.", fileDescription, path); + } + private static Message Message(SourceLineNumber sourceLineNumber, Ids id, string format, params object[] args) { return new Message(sourceLineNumber, MessageLevel.Warning, (int)id, format, args); @@ -809,6 +819,7 @@ namespace WixToolset.Data DetectConditionRecommended = 1153, CollidingModularizationTypes = 1156, InvalidEnvironmentVariable = 1157, + WindowsInstallerFileTooLarge = 1158, UnavailableBundleConditionVariable = 1159, } } diff --git a/src/wix/WixToolset.Core.Burn/Bundles/ProcessMsiPackageCommand.cs b/src/wix/WixToolset.Core.Burn/Bundles/ProcessMsiPackageCommand.cs index 327c9cc9..b950d06c 100644 --- a/src/wix/WixToolset.Core.Burn/Bundles/ProcessMsiPackageCommand.cs +++ b/src/wix/WixToolset.Core.Burn/Bundles/ProcessMsiPackageCommand.cs @@ -63,6 +63,8 @@ namespace WixToolset.Core.Burn.Bundles var compressed = false; try { + this.CheckIfWindowsInstallerFileTooLarge(packagePayload.SourceLineNumbers, sourcePath, "MSI"); + using (var db = new Database(sourcePath, OpenDatabase.ReadOnly)) { // Read data out of the msi database... @@ -397,6 +399,8 @@ namespace WixToolset.Core.Burn.Bundles Packaging = packagePayload.Packaging, ParentPackagePayloadRef = packagePayload.Id.Id, }); + + this.CheckIfWindowsInstallerFileTooLarge(this.Facade.PackageSymbol.SourceLineNumbers, payloadSourceFile, "cabinet"); } } } @@ -546,6 +550,22 @@ namespace WixToolset.Core.Burn.Bundles return resolvedPath; } + private void CheckIfWindowsInstallerFileTooLarge(SourceLineNumber sourceLineNumber, string path, string description) + { + // Best effort check to see if the file is too large for the Windows Installer. + try + { + var fi = new FileInfo(path); + if (fi.Length > Int32.MaxValue) + { + this.Messaging.Write(WarningMessages.WindowsInstallerFileTooLarge(sourceLineNumber, path, description)); + } + } + catch + { + } + } + private static string GetProperty(View view, string property) { using (var queryRecord = new Record(1)) diff --git a/src/wix/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs b/src/wix/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs index f251dcc9..69a954eb 100644 --- a/src/wix/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs +++ b/src/wix/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs @@ -513,6 +513,19 @@ namespace WixToolset.Core.WindowsInstaller.Bind trackedFiles.AddRange(command.TrackedFiles); } + // Best effort check to see if the MSI file is too large for the Windows Installer. + try + { + var fi = new FileInfo(this.OutputPath); + if (fi.Length > Int32.MaxValue) + { + this.Messaging.Write(WarningMessages.WindowsInstallerFileTooLarge(null, this.OutputPath, "MSI")); + } + } + catch + { + } + var trackedInputFiles = this.TrackInputFiles(data, trackedFiles); trackedFiles.AddRange(trackedInputFiles); diff --git a/src/wix/WixToolset.Core.WindowsInstaller/Bind/CabinetBuilder.cs b/src/wix/WixToolset.Core.WindowsInstaller/Bind/CabinetBuilder.cs index 13b079ad..49eaad42 100644 --- a/src/wix/WixToolset.Core.WindowsInstaller/Bind/CabinetBuilder.cs +++ b/src/wix/WixToolset.Core.WindowsInstaller/Bind/CabinetBuilder.cs @@ -165,7 +165,18 @@ namespace WixToolset.Core.WindowsInstaller.Bind var cab = new Cabinet(cabinetPath); cab.Compress(files, cabinetWorkItem.CompressionLevel, maxCabinetSize, cabinetWorkItem.MaxThreshold); - // TODO: Handle newCabNamesCallBackAddress from compression. + // Best effort check to see if the cabinet is too large for the Windows Installer. + try + { + var fi = new FileInfo(cabinetPath); + if (fi.Length > Int32.MaxValue) + { + this.Messaging.Write(WarningMessages.WindowsInstallerFileTooLarge(cabinetWorkItem.SourceLineNumber, cabinetPath, "cabinet")); + } + } + catch + { + } } } } diff --git a/src/wix/WixToolset.Core.WindowsInstaller/Bind/CabinetWorkItem.cs b/src/wix/WixToolset.Core.WindowsInstaller/Bind/CabinetWorkItem.cs index 1990ea78..b1a29834 100644 --- a/src/wix/WixToolset.Core.WindowsInstaller/Bind/CabinetWorkItem.cs +++ b/src/wix/WixToolset.Core.WindowsInstaller/Bind/CabinetWorkItem.cs @@ -14,22 +14,27 @@ namespace WixToolset.Core.WindowsInstaller.Bind /// /// Instantiate a new CabinetWorkItem. /// + /// Source line number that requires the cabinet creation. /// The collection of files in this cabinet. /// The cabinet file. /// Maximum threshold for each cabinet. /// The compression level of the cabinet. /// Modularization suffix used when building a Merge Module. - /// - public CabinetWorkItem(IEnumerable fileFacades, string cabinetFile, int maxThreshold, CompressionLevel compressionLevel, string modularizationSuffix /*, BinderFileManager binderFileManager*/) + public CabinetWorkItem(SourceLineNumber sourceLineNumber, string cabinetFile, IEnumerable fileFacades, int maxThreshold, CompressionLevel compressionLevel, string modularizationSuffix) { + this.SourceLineNumber = sourceLineNumber; this.CabinetFile = cabinetFile; this.CompressionLevel = compressionLevel; this.ModularizationSuffix = modularizationSuffix; this.FileFacades = fileFacades; - //this.BinderFileManager = binderFileManager; this.MaxThreshold = maxThreshold; } + /// + /// Source line that requires the cabinet creation. + /// + public SourceLineNumber SourceLineNumber { get; } + /// /// Gets the cabinet file. /// @@ -53,12 +58,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind /// The collection of files in this cabinet. public IEnumerable FileFacades { get; } - // - // Gets the binder file manager. - // - // The binder file manager. - //public BinderFileManager BinderFileManager { get; private set; } - /// /// Gets the max threshold. /// diff --git a/src/wix/WixToolset.Core.WindowsInstaller/Bind/CreateCabinetsCommand.cs b/src/wix/WixToolset.Core.WindowsInstaller/Bind/CreateCabinetsCommand.cs index 4ac248cd..2516a6fa 100644 --- a/src/wix/WixToolset.Core.WindowsInstaller/Bind/CreateCabinetsCommand.cs +++ b/src/wix/WixToolset.Core.WindowsInstaller/Bind/CreateCabinetsCommand.cs @@ -190,7 +190,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind if (CabinetBuildOption.BuildAndCopy == resolvedCabinet.BuildOption || CabinetBuildOption.BuildAndMove == resolvedCabinet.BuildOption) { // Default to the threshold for best smartcabbing (makes smallest cabinet). - cabinetWorkItem = new CabinetWorkItem(fileFacades, resolvedCabinet.Path, maxThreshold: 0, compressionLevel, this.ModularizationSuffix /*, this.FileManager*/); + cabinetWorkItem = new CabinetWorkItem(mediaSymbol.SourceLineNumbers, resolvedCabinet.Path, fileFacades, maxThreshold: 0, compressionLevel: compressionLevel, modularizationSuffix: this.ModularizationSuffix); } else // reuse the cabinet from the cabinet cache. { -- cgit v1.2.3-55-g6feb