private string ResolveMedia(MediaSymbol media, string mediaLayoutDirectory, string layoutDirectory) { string layout = null; foreach (var extension in this.BackendExtensions) { layout = extension.ResolveMedia(media, mediaLayoutDirectory, layoutDirectory); if (!String.IsNullOrEmpty(layout)) { break; } } // If no binder file manager resolved the layout, do the default behavior. if (String.IsNullOrEmpty(layout)) { if (String.IsNullOrEmpty(mediaLayoutDirectory)) { layout = layoutDirectory; } else if (Path.IsPathRooted(mediaLayoutDirectory)) { layout = mediaLayoutDirectory; } else { layout = Path.Combine(layoutDirectory, mediaLayoutDirectory); } } return(layout); }
/// <summary> /// Assign files to cabinets based on MediaTemplate authoring. /// </summary> /// <param name="fileFacades">FileRowCollection</param> private void AutoAssignFiles(List <MediaSymbol> mediaTable, Dictionary <MediaSymbol, List <FileFacade> > filesByCabinetMedia, List <FileFacade> uncompressedFiles) { const int MaxCabIndex = 999; ulong currentPreCabSize = 0; ulong maxPreCabSizeInBytes; var maxPreCabSizeInMB = 0; var currentCabIndex = 0; MediaSymbol currentMediaRow = null; var mediaTemplateTable = this.Section.Symbols.OfType <WixMediaTemplateSymbol>(); // Remove all previous media symbols since they will be replaced with // media template. foreach (var mediaSymbol in mediaTable) { this.Section.Symbols.Remove(mediaSymbol); } // Auto assign files to cabinets based on maximum uncompressed media size var mediaTemplateRow = mediaTemplateTable.Single(); if (!String.IsNullOrEmpty(mediaTemplateRow.CabinetTemplate)) { this.CabinetNameTemplate = mediaTemplateRow.CabinetTemplate; } var mumsString = Environment.GetEnvironmentVariable("WIX_MUMS"); try { // Override authored mums value if environment variable is authored. if (!String.IsNullOrEmpty(mumsString)) { maxPreCabSizeInMB = Int32.Parse(mumsString); } else { maxPreCabSizeInMB = mediaTemplateRow.MaximumUncompressedMediaSize ?? DefaultMaximumUncompressedMediaSize; } maxPreCabSizeInBytes = (ulong)maxPreCabSizeInMB * 1024 * 1024; } catch (FormatException) { throw new WixException(ErrorMessages.IllegalEnvironmentVariable("WIX_MUMS", mumsString)); } catch (OverflowException) { throw new WixException(ErrorMessages.MaximumUncompressedMediaSizeTooLarge(null, maxPreCabSizeInMB)); } var mediaSymbolsByDiskId = new Dictionary <int, MediaSymbol>(); foreach (var facade in this.FileFacades) { // When building a product, if the current file is not to be compressed or if // the package set not to be compressed, don't cab it. if (SectionType.Product == this.Section.Type && (facade.Uncompressed || !this.FilesCompressed)) { uncompressedFiles.Add(facade); continue; } if (currentCabIndex == MaxCabIndex) { // Associate current file with last cab (irrespective of the size) and cab index is not incremented anymore. } else { // Update current cab size. currentPreCabSize += (ulong)facade.FileSize; // Overflow due to current file if (currentPreCabSize > maxPreCabSizeInBytes) { currentMediaRow = this.AddMediaSymbol(mediaTemplateRow, ++currentCabIndex); mediaSymbolsByDiskId.Add(currentMediaRow.DiskId, currentMediaRow); filesByCabinetMedia.Add(currentMediaRow, new List <FileFacade>()); // Now files larger than MaxUncompressedMediaSize will be the only file in its cabinet so as to respect MaxUncompressedMediaSize currentPreCabSize = (ulong)facade.FileSize; } else // file fits in the current cab. { if (currentMediaRow == null) { // Create new cab and MediaRow currentMediaRow = this.AddMediaSymbol(mediaTemplateRow, ++currentCabIndex); mediaSymbolsByDiskId.Add(currentMediaRow.DiskId, currentMediaRow); filesByCabinetMedia.Add(currentMediaRow, new List <FileFacade>()); } } } // Associate current file with current cab. var cabinetFiles = filesByCabinetMedia[currentMediaRow]; facade.DiskId = currentCabIndex; cabinetFiles.Add(facade); } // If there are uncompressed files and no MediaRow, create a default one. if (uncompressedFiles.Count > 0 && !this.Section.Symbols.OfType <MediaSymbol>().Any()) { var defaultMediaRow = this.Section.AddSymbol(new MediaSymbol(null, new Identifier(AccessModifier.Private, 1)) { DiskId = 1, }); mediaSymbolsByDiskId.Add(1, defaultMediaRow); } }
private static IntermediateSymbol GenerateSymbolFromRow(Wix3.Row row, Dictionary <int, Wix3.WixMediaRow> wixMediaByDiskId, Dictionary <string, Wix3.Row> componentsById, Dictionary <string, Wix3.Row> fontsById, Dictionary <string, Wix3.Row> bindPathsById, Dictionary <string, Wix3.Row> selfRegById, Dictionary <string, Wix3.Row> wixFileById, Dictionary <string, Wix3.Row> wixDirectoryById) { var name = row.Table.Name; switch (name) { case "_SummaryInformation": return(DefaultSymbolFromRow(typeof(SummaryInformationSymbol), row, columnZeroIsId: false)); case "ActionText": return(DefaultSymbolFromRow(typeof(ActionTextSymbol), row, columnZeroIsId: false)); case "AppId": return(DefaultSymbolFromRow(typeof(AppIdSymbol), row, columnZeroIsId: false)); case "AppSearch": return(DefaultSymbolFromRow(typeof(AppSearchSymbol), row, columnZeroIsId: false)); case "Billboard": return(DefaultSymbolFromRow(typeof(BillboardSymbol), row, columnZeroIsId: true)); case "Binary": return(DefaultSymbolFromRow(typeof(BinarySymbol), row, columnZeroIsId: true)); case "BindPath": return(null); case "CCPSearch": return(DefaultSymbolFromRow(typeof(CCPSearchSymbol), row, columnZeroIsId: true)); case "Class": return(DefaultSymbolFromRow(typeof(ClassSymbol), row, columnZeroIsId: false)); case "CompLocator": return(DefaultSymbolFromRow(typeof(CompLocatorSymbol), row, columnZeroIsId: false)); case "Component": { var attributes = FieldAsNullableInt(row, 3); var location = ComponentLocation.LocalOnly; if ((attributes & WindowsInstallerConstants.MsidbComponentAttributesSourceOnly) == WindowsInstallerConstants.MsidbComponentAttributesSourceOnly) { location = ComponentLocation.SourceOnly; } else if ((attributes & WindowsInstallerConstants.MsidbComponentAttributesOptional) == WindowsInstallerConstants.MsidbComponentAttributesOptional) { location = ComponentLocation.Either; } var keyPath = FieldAsString(row, 5); var keyPathType = String.IsNullOrEmpty(keyPath) ? ComponentKeyPathType.Directory : ComponentKeyPathType.File; if ((attributes & WindowsInstallerConstants.MsidbComponentAttributesRegistryKeyPath) == WindowsInstallerConstants.MsidbComponentAttributesRegistryKeyPath) { keyPathType = ComponentKeyPathType.Registry; } else if ((attributes & WindowsInstallerConstants.MsidbComponentAttributesODBCDataSource) == WindowsInstallerConstants.MsidbComponentAttributesODBCDataSource) { keyPathType = ComponentKeyPathType.OdbcDataSource; } return(new ComponentSymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0))) { ComponentId = FieldAsString(row, 1), DirectoryRef = FieldAsString(row, 2), Condition = FieldAsString(row, 4), KeyPath = keyPath, Location = location, DisableRegistryReflection = (attributes & WindowsInstallerConstants.MsidbComponentAttributesDisableRegistryReflection) == WindowsInstallerConstants.MsidbComponentAttributesDisableRegistryReflection, NeverOverwrite = (attributes & WindowsInstallerConstants.MsidbComponentAttributesNeverOverwrite) == WindowsInstallerConstants.MsidbComponentAttributesNeverOverwrite, Permanent = (attributes & WindowsInstallerConstants.MsidbComponentAttributesPermanent) == WindowsInstallerConstants.MsidbComponentAttributesPermanent, SharedDllRefCount = (attributes & WindowsInstallerConstants.MsidbComponentAttributesSharedDllRefCount) == WindowsInstallerConstants.MsidbComponentAttributesSharedDllRefCount, Shared = (attributes & WindowsInstallerConstants.MsidbComponentAttributesShared) == WindowsInstallerConstants.MsidbComponentAttributesShared, Transitive = (attributes & WindowsInstallerConstants.MsidbComponentAttributesTransitive) == WindowsInstallerConstants.MsidbComponentAttributesTransitive, UninstallWhenSuperseded = (attributes & WindowsInstallerConstants.MsidbComponentAttributesUninstallOnSupersedence) == WindowsInstallerConstants.MsidbComponentAttributesUninstallOnSupersedence, Win64 = (attributes & WindowsInstallerConstants.MsidbComponentAttributes64bit) == WindowsInstallerConstants.MsidbComponentAttributes64bit, KeyPathType = keyPathType, }); } case "Condition": return(DefaultSymbolFromRow(typeof(ConditionSymbol), row, columnZeroIsId: false)); case "CreateFolder": return(DefaultSymbolFromRow(typeof(CreateFolderSymbol), row, columnZeroIsId: false)); case "CustomAction": { var caType = FieldAsInt(row, 1); var executionType = DetermineCustomActionExecutionType(caType); var sourceType = DetermineCustomActionSourceType(caType); var targetType = DetermineCustomActionTargetType(caType); return(new CustomActionSymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0))) { ExecutionType = executionType, SourceType = sourceType, Source = FieldAsString(row, 2), TargetType = targetType, Target = FieldAsString(row, 3), Win64 = (caType & WindowsInstallerConstants.MsidbCustomActionType64BitScript) == WindowsInstallerConstants.MsidbCustomActionType64BitScript, TSAware = (caType & WindowsInstallerConstants.MsidbCustomActionTypeTSAware) == WindowsInstallerConstants.MsidbCustomActionTypeTSAware, Impersonate = (caType & WindowsInstallerConstants.MsidbCustomActionTypeNoImpersonate) != WindowsInstallerConstants.MsidbCustomActionTypeNoImpersonate, IgnoreResult = (caType & WindowsInstallerConstants.MsidbCustomActionTypeContinue) == WindowsInstallerConstants.MsidbCustomActionTypeContinue, Hidden = (caType & WindowsInstallerConstants.MsidbCustomActionTypeHideTarget) == WindowsInstallerConstants.MsidbCustomActionTypeHideTarget, Async = (caType & WindowsInstallerConstants.MsidbCustomActionTypeAsync) == WindowsInstallerConstants.MsidbCustomActionTypeAsync, }); } case "Directory": { var id = FieldAsString(row, 0); var splits = SplitDefaultDir(FieldAsString(row, 2)); var symbol = new DirectorySymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, id)) { ParentDirectoryRef = FieldAsString(row, 1), Name = splits[0], ShortName = splits[1], SourceName = splits[2], SourceShortName = splits[3] }; if (wixDirectoryById.TryGetValue(id, out var wixDirectoryRow)) { symbol.ComponentGuidGenerationSeed = FieldAsString(wixDirectoryRow, 1); } return(symbol); } case "DrLocator": return(DefaultSymbolFromRow(typeof(DrLocatorSymbol), row, columnZeroIsId: false)); case "DuplicateFile": { var splitName = FieldAsString(row, 3)?.Split('|'); var symbol = new DuplicateFileSymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0))) { ComponentRef = FieldAsString(row, 1), FileRef = FieldAsString(row, 2), DestinationName = splitName == null ? null : splitName.Length > 1 ? splitName[1] : splitName[0], DestinationShortName = splitName == null ? null : splitName.Length > 1 ? splitName[0] : null, DestinationFolder = FieldAsString(row, 4) }; return(symbol); } case "Error": return(DefaultSymbolFromRow(typeof(ErrorSymbol), row, columnZeroIsId: false)); case "Extension": return(DefaultSymbolFromRow(typeof(ExtensionSymbol), row, columnZeroIsId: false)); case "Feature": { var attributes = FieldAsInt(row, 7); var installDefault = FeatureInstallDefault.Local; if ((attributes & WindowsInstallerConstants.MsidbFeatureAttributesFollowParent) == WindowsInstallerConstants.MsidbFeatureAttributesFollowParent) { installDefault = FeatureInstallDefault.FollowParent; } else if ((attributes & WindowsInstallerConstants.MsidbFeatureAttributesFavorSource) == WindowsInstallerConstants.MsidbFeatureAttributesFavorSource) { installDefault = FeatureInstallDefault.Source; } return(new FeatureSymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0))) { ParentFeatureRef = FieldAsString(row, 1), Title = FieldAsString(row, 2), Description = FieldAsString(row, 3), Display = FieldAsInt(row, 4), // BUGBUGBUG: FieldAsNullableInt(row, 4), Level = FieldAsInt(row, 5), DirectoryRef = FieldAsString(row, 6), DisallowAbsent = (attributes & WindowsInstallerConstants.MsidbFeatureAttributesUIDisallowAbsent) == WindowsInstallerConstants.MsidbFeatureAttributesUIDisallowAbsent, DisallowAdvertise = (attributes & WindowsInstallerConstants.MsidbFeatureAttributesDisallowAdvertise) == WindowsInstallerConstants.MsidbFeatureAttributesDisallowAdvertise, InstallDefault = installDefault, TypicalDefault = (attributes & WindowsInstallerConstants.MsidbFeatureAttributesFavorAdvertise) == WindowsInstallerConstants.MsidbFeatureAttributesFavorAdvertise ? FeatureTypicalDefault.Advertise : FeatureTypicalDefault.Install, }); } case "FeatureComponents": return(DefaultSymbolFromRow(typeof(FeatureComponentsSymbol), row, columnZeroIsId: false)); case "File": { var attributes = FieldAsNullableInt(row, 6); FileSymbolAttributes symbolAttributes = 0; symbolAttributes |= (attributes & WindowsInstallerConstants.MsidbFileAttributesReadOnly) == WindowsInstallerConstants.MsidbFileAttributesReadOnly ? FileSymbolAttributes.ReadOnly : 0; symbolAttributes |= (attributes & WindowsInstallerConstants.MsidbFileAttributesHidden) == WindowsInstallerConstants.MsidbFileAttributesHidden ? FileSymbolAttributes.Hidden : 0; symbolAttributes |= (attributes & WindowsInstallerConstants.MsidbFileAttributesSystem) == WindowsInstallerConstants.MsidbFileAttributesSystem ? FileSymbolAttributes.System : 0; symbolAttributes |= (attributes & WindowsInstallerConstants.MsidbFileAttributesVital) == WindowsInstallerConstants.MsidbFileAttributesVital ? FileSymbolAttributes.Vital : 0; symbolAttributes |= (attributes & WindowsInstallerConstants.MsidbFileAttributesChecksum) == WindowsInstallerConstants.MsidbFileAttributesChecksum ? FileSymbolAttributes.Checksum : 0; symbolAttributes |= (attributes & WindowsInstallerConstants.MsidbFileAttributesNoncompressed) == WindowsInstallerConstants.MsidbFileAttributesNoncompressed ? FileSymbolAttributes.Uncompressed : 0; symbolAttributes |= (attributes & WindowsInstallerConstants.MsidbFileAttributesCompressed) == WindowsInstallerConstants.MsidbFileAttributesCompressed ? FileSymbolAttributes.Compressed : 0; var id = FieldAsString(row, 0); var splitName = FieldAsString(row, 2).Split('|'); var symbol = new FileSymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, id)) { ComponentRef = FieldAsString(row, 1), Name = splitName.Length > 1 ? splitName[1] : splitName[0], ShortName = splitName.Length > 1 ? splitName[0] : null, FileSize = FieldAsInt(row, 3), Version = FieldAsString(row, 4), Language = FieldAsString(row, 5), Attributes = symbolAttributes }; if (bindPathsById.TryGetValue(id, out var bindPathRow)) { symbol.BindPath = FieldAsString(bindPathRow, 1) ?? String.Empty; } if (fontsById.TryGetValue(id, out var fontRow)) { symbol.FontTitle = FieldAsString(fontRow, 1) ?? String.Empty; } if (selfRegById.TryGetValue(id, out var selfRegRow)) { symbol.SelfRegCost = FieldAsNullableInt(selfRegRow, 1) ?? 0; } if (wixFileById.TryGetValue(id, out var wixFileRow)) { symbol.DirectoryRef = FieldAsString(wixFileRow, 4); symbol.DiskId = FieldAsNullableInt(wixFileRow, 5) ?? 0; symbol.Source = new IntermediateFieldPathValue { Path = FieldAsString(wixFileRow, 6) }; symbol.PatchGroup = FieldAsInt(wixFileRow, 8); symbol.PatchAttributes = (PatchAttributeType)FieldAsInt(wixFileRow, 10); } return(symbol); } case "Font": return(null); case "Icon": return(DefaultSymbolFromRow(typeof(IconSymbol), row, columnZeroIsId: true)); case "IniFile": { var splitName = FieldAsString(row, 1).Split('|'); var action = FieldAsInt(row, 6); var symbol = new IniFileSymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0))) { FileName = splitName.Length > 1 ? splitName[1] : splitName[0], ShortFileName = splitName.Length > 1 ? splitName[0] : null, DirProperty = FieldAsString(row, 2), Section = FieldAsString(row, 3), Key = FieldAsString(row, 4), Value = FieldAsString(row, 5), Action = action == 3 ? IniFileActionType.AddTag : action == 1 ? IniFileActionType.CreateLine : IniFileActionType.AddLine, ComponentRef = FieldAsString(row, 7), }; return(symbol); } case "IniLocator": { var splitName = FieldAsString(row, 1).Split('|'); var symbol = new IniLocatorSymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0))) { FileName = splitName.Length > 1 ? splitName[1] : splitName[0], ShortFileName = splitName.Length > 1 ? splitName[0] : null, Section = FieldAsString(row, 2), Key = FieldAsString(row, 3), Field = FieldAsInt(row, 4), Type = FieldAsInt(row, 5), }; return(symbol); } case "LockPermissions": return(DefaultSymbolFromRow(typeof(LockPermissionsSymbol), row, columnZeroIsId: false)); case "Media": { var diskId = FieldAsInt(row, 0); var symbol = new MediaSymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, diskId)) { DiskId = diskId, LastSequence = FieldAsNullableInt(row, 1), DiskPrompt = FieldAsString(row, 2), Cabinet = FieldAsString(row, 3), VolumeLabel = FieldAsString(row, 4), Source = FieldAsString(row, 5) }; if (wixMediaByDiskId.TryGetValue(diskId, out var wixMediaRow)) { var compressionLevel = FieldAsString(wixMediaRow, 1); symbol.CompressionLevel = String.IsNullOrEmpty(compressionLevel) ? null : (CompressionLevel?)Enum.Parse(typeof(CompressionLevel), compressionLevel, true); symbol.Layout = wixMediaRow.Layout; } return(symbol); } case "MIME": return(DefaultSymbolFromRow(typeof(MIMESymbol), row, columnZeroIsId: false)); case "ModuleIgnoreTable": return(DefaultSymbolFromRow(typeof(ModuleIgnoreTableSymbol), row, columnZeroIsId: true)); case "MoveFile": return(DefaultSymbolFromRow(typeof(MoveFileSymbol), row, columnZeroIsId: true)); case "MsiAssembly": { var componentId = FieldAsString(row, 0); if (componentsById.TryGetValue(componentId, out var componentRow)) { return(new AssemblySymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(componentRow, 5))) { ComponentRef = componentId, FeatureRef = FieldAsString(row, 1), ManifestFileRef = FieldAsString(row, 2), ApplicationFileRef = FieldAsString(row, 3), Type = FieldAsNullableInt(row, 4) == 1 ? AssemblyType.Win32Assembly : AssemblyType.DotNetAssembly, }); } return(null); } case "MsiLockPermissionsEx": return(DefaultSymbolFromRow(typeof(MsiLockPermissionsExSymbol), row, columnZeroIsId: true)); case "MsiShortcutProperty": return(DefaultSymbolFromRow(typeof(MsiShortcutPropertySymbol), row, columnZeroIsId: true)); case "ODBCDataSource": return(DefaultSymbolFromRow(typeof(ODBCDataSourceSymbol), row, columnZeroIsId: true)); case "ODBCDriver": return(DefaultSymbolFromRow(typeof(ODBCDriverSymbol), row, columnZeroIsId: true)); case "ODBCTranslator": return(DefaultSymbolFromRow(typeof(ODBCTranslatorSymbol), row, columnZeroIsId: true)); case "ProgId": return(DefaultSymbolFromRow(typeof(ProgIdSymbol), row, columnZeroIsId: false)); case "Property": return(DefaultSymbolFromRow(typeof(PropertySymbol), row, columnZeroIsId: true)); case "PublishComponent": return(DefaultSymbolFromRow(typeof(PublishComponentSymbol), row, columnZeroIsId: false)); case "Registry": { var value = FieldAsString(row, 4); var valueType = RegistryValueType.String; var valueAction = RegistryValueActionType.Write; if (!String.IsNullOrEmpty(value)) { if (value.StartsWith("#x", StringComparison.Ordinal)) { valueType = RegistryValueType.Binary; value = value.Substring(2); } else if (value.StartsWith("#%", StringComparison.Ordinal)) { valueType = RegistryValueType.Expandable; value = value.Substring(2); } else if (value.StartsWith("#", StringComparison.Ordinal)) { valueType = RegistryValueType.Integer; value = value.Substring(1); } else if (value.StartsWith("[~]", StringComparison.Ordinal) && value.EndsWith("[~]", StringComparison.Ordinal)) { value = value.Substring(3, value.Length - 6); valueType = RegistryValueType.MultiString; valueAction = RegistryValueActionType.Write; } else if (value.StartsWith("[~]", StringComparison.Ordinal)) { value = value.Substring(3); valueType = RegistryValueType.MultiString; valueAction = RegistryValueActionType.Append; } else if (value.EndsWith("[~]", StringComparison.Ordinal)) { value = value.Substring(0, value.Length - 3); valueType = RegistryValueType.MultiString; valueAction = RegistryValueActionType.Prepend; } } return(new RegistrySymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0))) { Root = (RegistryRootType)FieldAsInt(row, 1), Key = FieldAsString(row, 2), Name = FieldAsString(row, 3), Value = value, ComponentRef = FieldAsString(row, 5), ValueAction = valueAction, ValueType = valueType, }); } case "RegLocator": { var type = FieldAsInt(row, 4); return(new RegLocatorSymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0))) { Root = (RegistryRootType)FieldAsInt(row, 1), Key = FieldAsString(row, 2), Name = FieldAsString(row, 3), Type = (RegLocatorType)(type & 0xF), Win64 = (type & WindowsInstallerConstants.MsidbLocatorType64bit) == WindowsInstallerConstants.MsidbLocatorType64bit }); } case "RemoveFile": { var splitName = FieldAsString(row, 2).Split('|'); var installMode = FieldAsInt(row, 4); return(new RemoveFileSymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0))) { ComponentRef = FieldAsString(row, 1), FileName = splitName.Length > 1 ? splitName[1] : splitName[0], ShortFileName = splitName.Length > 1 ? splitName[0] : null, DirPropertyRef = FieldAsString(row, 3), OnInstall = (installMode & WindowsInstallerConstants.MsidbRemoveFileInstallModeOnInstall) == WindowsInstallerConstants.MsidbRemoveFileInstallModeOnInstall ? (bool?)true : null, OnUninstall = (installMode & WindowsInstallerConstants.MsidbRemoveFileInstallModeOnRemove) == WindowsInstallerConstants.MsidbRemoveFileInstallModeOnRemove ? (bool?)true : null }); } case "RemoveRegistry": { return(new RemoveRegistrySymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0))) { Action = RemoveRegistryActionType.RemoveOnInstall, Root = (RegistryRootType)FieldAsInt(row, 1), Key = FieldAsString(row, 2), Name = FieldAsString(row, 3), ComponentRef = FieldAsString(row, 4), }); } case "ReserveCost": return(DefaultSymbolFromRow(typeof(ReserveCostSymbol), row, columnZeroIsId: true)); case "SelfReg": return(null); case "ServiceControl": { var events = FieldAsInt(row, 2); var wait = FieldAsNullableInt(row, 4); return(new ServiceControlSymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0))) { Name = FieldAsString(row, 1), Arguments = FieldAsString(row, 3), Wait = !wait.HasValue || wait.Value == 1, ComponentRef = FieldAsString(row, 5), InstallRemove = (events & WindowsInstallerConstants.MsidbServiceControlEventDelete) == WindowsInstallerConstants.MsidbServiceControlEventDelete, UninstallRemove = (events & WindowsInstallerConstants.MsidbServiceControlEventUninstallDelete) == WindowsInstallerConstants.MsidbServiceControlEventUninstallDelete, InstallStart = (events & WindowsInstallerConstants.MsidbServiceControlEventStart) == WindowsInstallerConstants.MsidbServiceControlEventStart, UninstallStart = (events & WindowsInstallerConstants.MsidbServiceControlEventUninstallStart) == WindowsInstallerConstants.MsidbServiceControlEventUninstallStart, InstallStop = (events & WindowsInstallerConstants.MsidbServiceControlEventStop) == WindowsInstallerConstants.MsidbServiceControlEventStop, UninstallStop = (events & WindowsInstallerConstants.MsidbServiceControlEventUninstallStop) == WindowsInstallerConstants.MsidbServiceControlEventUninstallStop, }); } case "ServiceInstall": return(DefaultSymbolFromRow(typeof(ServiceInstallSymbol), row, columnZeroIsId: true)); case "Shortcut": { var splitName = FieldAsString(row, 2).Split('|'); return(new ShortcutSymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0))) { DirectoryRef = FieldAsString(row, 1), Name = splitName.Length > 1 ? splitName[1] : splitName[0], ShortName = splitName.Length > 1 ? splitName[0] : null, ComponentRef = FieldAsString(row, 3), Target = FieldAsString(row, 4), Arguments = FieldAsString(row, 5), Description = FieldAsString(row, 6), Hotkey = FieldAsNullableInt(row, 7), IconRef = FieldAsString(row, 8), IconIndex = FieldAsNullableInt(row, 9), Show = (ShortcutShowType?)FieldAsNullableInt(row, 10), WorkingDirectory = FieldAsString(row, 11), DisplayResourceDll = FieldAsString(row, 12), DisplayResourceId = FieldAsNullableInt(row, 13), DescriptionResourceDll = FieldAsString(row, 14), DescriptionResourceId = FieldAsNullableInt(row, 15), }); } case "Signature": return(DefaultSymbolFromRow(typeof(SignatureSymbol), row, columnZeroIsId: true)); case "UIText": return(DefaultSymbolFromRow(typeof(UITextSymbol), row, columnZeroIsId: true)); case "Upgrade": { var attributes = FieldAsInt(row, 4); return(new UpgradeSymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0))) { UpgradeCode = FieldAsString(row, 0), VersionMin = FieldAsString(row, 1), VersionMax = FieldAsString(row, 2), Language = FieldAsString(row, 3), Remove = FieldAsString(row, 5), ActionProperty = FieldAsString(row, 6), MigrateFeatures = (attributes & WindowsInstallerConstants.MsidbUpgradeAttributesMigrateFeatures) == WindowsInstallerConstants.MsidbUpgradeAttributesMigrateFeatures, OnlyDetect = (attributes & WindowsInstallerConstants.MsidbUpgradeAttributesOnlyDetect) == WindowsInstallerConstants.MsidbUpgradeAttributesOnlyDetect, IgnoreRemoveFailures = (attributes & WindowsInstallerConstants.MsidbUpgradeAttributesIgnoreRemoveFailure) == WindowsInstallerConstants.MsidbUpgradeAttributesIgnoreRemoveFailure, VersionMinInclusive = (attributes & WindowsInstallerConstants.MsidbUpgradeAttributesVersionMinInclusive) == WindowsInstallerConstants.MsidbUpgradeAttributesVersionMinInclusive, VersionMaxInclusive = (attributes & WindowsInstallerConstants.MsidbUpgradeAttributesVersionMaxInclusive) == WindowsInstallerConstants.MsidbUpgradeAttributesVersionMaxInclusive, ExcludeLanguages = (attributes & WindowsInstallerConstants.MsidbUpgradeAttributesLanguagesExclusive) == WindowsInstallerConstants.MsidbUpgradeAttributesLanguagesExclusive, }); } case "Verb": return(DefaultSymbolFromRow(typeof(VerbSymbol), row, columnZeroIsId: false)); case "WixAction": { var sequenceTable = FieldAsString(row, 0); return(new WixActionSymbol(SourceLineNumber4(row.SourceLineNumbers)) { SequenceTable = (SequenceTable)Enum.Parse(typeof(SequenceTable), sequenceTable == "AdvtExecuteSequence" ? nameof(SequenceTable.AdvertiseExecuteSequence) : sequenceTable), Action = FieldAsString(row, 1), Condition = FieldAsString(row, 2), Sequence = FieldAsNullableInt(row, 3), Before = FieldAsString(row, 4), After = FieldAsString(row, 5), Overridable = FieldAsNullableInt(row, 6) != 0, }); } case "WixBootstrapperApplication": return(DefaultSymbolFromRow(typeof(WixBootstrapperApplicationSymbol), row, columnZeroIsId: true)); case "WixBundleContainer": return(DefaultSymbolFromRow(typeof(WixBundleContainerSymbol), row, columnZeroIsId: true)); case "WixBundleVariable": return(DefaultSymbolFromRow(typeof(WixBundleVariableSymbol), row, columnZeroIsId: true)); case "WixChainItem": return(DefaultSymbolFromRow(typeof(WixChainItemSymbol), row, columnZeroIsId: true)); case "WixCustomTable": return(DefaultSymbolFromRow(typeof(WixCustomTableSymbol), row, columnZeroIsId: true)); case "WixDirectory": return(null); case "WixFile": return(null); case "WixInstanceTransforms": return(DefaultSymbolFromRow(typeof(WixInstanceTransformsSymbol), row, columnZeroIsId: true)); case "WixMedia": return(null); case "WixMerge": return(DefaultSymbolFromRow(typeof(WixMergeSymbol), row, columnZeroIsId: true)); case "WixPatchBaseline": return(DefaultSymbolFromRow(typeof(WixPatchBaselineSymbol), row, columnZeroIsId: true)); case "WixProperty": { var attributes = FieldAsInt(row, 1); return(new WixPropertySymbol(SourceLineNumber4(row.SourceLineNumbers)) { PropertyRef = FieldAsString(row, 0), Admin = (attributes & 0x1) == 0x1, Hidden = (attributes & 0x2) == 0x2, Secure = (attributes & 0x4) == 0x4, }); } case "WixSuppressModularization": return(DefaultSymbolFromRow(typeof(WixSuppressModularizationSymbol), row, columnZeroIsId: true)); case "WixUI": return(DefaultSymbolFromRow(typeof(WixUISymbol), row, columnZeroIsId: true)); case "WixVariable": return(DefaultSymbolFromRow(typeof(WixVariableSymbol), row, columnZeroIsId: true)); default: return(GenericSymbolFromCustomRow(row, columnZeroIsId: false)); } }
/// <summary> /// See <see cref="IWindowsInstallerBackendBinderExtension.PreBackendBind(IBindContext)"/> /// </summary> public virtual string ResolveMedia(MediaSymbol mediaRow, string mediaLayoutDirectory, string layoutDirectory) => null;
public void Execute() { var mediaRows = this.Section.Symbols.OfType <MediaSymbol>().ToDictionary(t => t.DiskId); // Calculate sequence numbers and media disk id layout for all file media information objects. if (SectionType.Module == this.Section.Type) { var lastSequence = 0; foreach (var facade in this.FileFacades) { facade.Sequence = ++lastSequence; } } else { var lastSequence = 0; MediaSymbol mediaSymbol = null; var patchGroups = new Dictionary <int, List <FileFacade> >(); // sequence the non-patch-added files foreach (var facade in this.FileFacades) { if (null == mediaSymbol) { mediaSymbol = mediaRows[facade.DiskId]; if (SectionType.Patch == this.Section.Type) { // patch Media cannot start at zero lastSequence = mediaSymbol.LastSequence ?? 1; } } else if (mediaSymbol.DiskId != facade.DiskId) { mediaSymbol.LastSequence = lastSequence; mediaSymbol = mediaRows[facade.DiskId]; } if (facade.PatchGroup.HasValue) { if (patchGroups.TryGetValue(facade.PatchGroup.Value, out var patchGroup)) { patchGroup = new List <FileFacade>(); patchGroups.Add(facade.PatchGroup.Value, patchGroup); } patchGroup.Add(facade); } else if (!facade.FromModule) { facade.Sequence = ++lastSequence; } } if (null != mediaSymbol) { mediaSymbol.LastSequence = lastSequence; mediaSymbol = null; } // sequence the patch-added files foreach (var patchGroup in patchGroups.Values) { foreach (var facade in patchGroup) { if (null == mediaSymbol) { mediaSymbol = mediaRows[facade.DiskId]; } else if (mediaSymbol.DiskId != facade.DiskId) { mediaSymbol.LastSequence = lastSequence; mediaSymbol = mediaRows[facade.DiskId]; } facade.Sequence = ++lastSequence; } } if (null != mediaSymbol) { mediaSymbol.LastSequence = lastSequence; } } }
/// <summary> /// Creates a work item to create a cabinet. /// </summary> /// <param name="output">Output for the current database.</param> /// <param name="cabinetDir">Directory to create cabinet in.</param> /// <param name="mediaSymbol">Media symbol containing information about the cabinet.</param> /// <param name="fileFacades">Collection of files in this cabinet.</param> /// <returns>created CabinetWorkItem object</returns> private CabinetWorkItem CreateCabinetWorkItem(WindowsInstallerData output, string cabinetDir, MediaSymbol mediaSymbol, CompressionLevel compressionLevel, IEnumerable <FileFacade> fileFacades) { CabinetWorkItem cabinetWorkItem = null; var tempCabinetFileX = Path.Combine(this.IntermediateFolder, mediaSymbol.Cabinet); // check for an empty cabinet if (!fileFacades.Any()) { // Remove the leading '#' from the embedded cabinet name to make the warning easier to understand var cabinetName = mediaSymbol.Cabinet.TrimStart('#'); // If building a patch, remind them to run -p for torch. if (OutputType.Patch == output.Type) { this.Messaging.Write(WarningMessages.EmptyCabinet(mediaSymbol.SourceLineNumbers, cabinetName, true)); } else { this.Messaging.Write(WarningMessages.EmptyCabinet(mediaSymbol.SourceLineNumbers, cabinetName)); } } var cabinetResolver = new CabinetResolver(this.ServiceProvider, this.CabCachePath, this.BackendExtensions); var resolvedCabinet = cabinetResolver.ResolveCabinet(tempCabinetFileX, fileFacades); // create a cabinet work item if it's not being skipped 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*/); } else // reuse the cabinet from the cabinet cache. { this.Messaging.Write(VerboseMessages.ReusingCabCache(mediaSymbol.SourceLineNumbers, mediaSymbol.Cabinet, resolvedCabinet.Path)); try { // Ensure the cached cabinet timestamp is current to prevent perpetual incremental builds. The // problematic scenario goes like this. Imagine two cabinets in the cache. Update a file that // goes into one of the cabinets. One cabinet will get rebuilt, the other will be copied from // the cache. Now the file (an input) has a newer timestamp than the reused cabient (an output) // causing the project to look like it perpetually needs a rebuild until all of the reused // cabinets get newer timestamps. File.SetLastWriteTime(resolvedCabinet.Path, DateTime.Now); } catch (Exception e) { this.Messaging.Write(WarningMessages.CannotUpdateCabCache(mediaSymbol.SourceLineNumbers, resolvedCabinet.Path, e.Message)); } } var trackResolvedCabinet = this.BackendHelper.TrackFile(resolvedCabinet.Path, TrackedFileType.Intermediate, mediaSymbol.SourceLineNumbers); this.trackedFiles.Add(trackResolvedCabinet); if (mediaSymbol.Cabinet.StartsWith("#", StringComparison.Ordinal)) { var streamsTable = output.EnsureTable(this.TableDefinitions["_Streams"]); var streamRow = streamsTable.CreateRow(mediaSymbol.SourceLineNumbers); streamRow[0] = mediaSymbol.Cabinet.Substring(1); streamRow[1] = resolvedCabinet.Path; } else { var trackDestination = this.BackendHelper.TrackFile(Path.Combine(cabinetDir, mediaSymbol.Cabinet), TrackedFileType.Final, mediaSymbol.SourceLineNumbers); this.trackedFiles.Add(trackDestination); var transfer = this.BackendHelper.CreateFileTransfer(resolvedCabinet.Path, trackDestination.Path, resolvedCabinet.BuildOption == CabinetBuildOption.BuildAndMove, mediaSymbol.SourceLineNumbers); this.fileTransfers.Add(transfer); } return(cabinetWorkItem); }