From 9bdf3730cd43e1af8a4ea9be6cf2fba77fcff2d2 Mon Sep 17 00:00:00 2001 From: Sean Hall Date: Thu, 1 Jul 2021 09:30:10 -0500 Subject: Add bundle option for command line variables to always be uppercase. Fixes #3777 --- .../WixToolset.Mba.Core/IOverridableVariables.cs | 20 +++++++++++ src/api/burn/WixToolset.Mba.Core/MbaCommand.cs | 6 ++-- .../WixToolset.Mba.Core/OverridableVariables.cs | 30 ++++++++++++++++ src/api/burn/balutil/balinfo.cpp | 40 ++++++++++++++++++++++ src/api/burn/balutil/inc/balinfo.h | 7 ++++ .../WixToolsetTest.Mba.Core.csproj | 1 + .../wix/WixToolset.Data/Symbols/WixBundleSymbol.cs | 14 ++++++++ 7 files changed, 116 insertions(+), 2 deletions(-) (limited to 'src/api') diff --git a/src/api/burn/WixToolset.Mba.Core/IOverridableVariables.cs b/src/api/burn/WixToolset.Mba.Core/IOverridableVariables.cs index 3944913b..1ffe50e4 100644 --- a/src/api/burn/WixToolset.Mba.Core/IOverridableVariables.cs +++ b/src/api/burn/WixToolset.Mba.Core/IOverridableVariables.cs @@ -4,11 +4,31 @@ namespace WixToolset.Mba.Core { using System.Collections.Generic; + /// + /// The case sensitivity of variables from the command line. + /// + public enum VariableCommandLineType + { + /// + /// Similar to Windows Installer, all variable names specified on the command line are automatically converted to upper case. + /// + UpperCase, + /// + /// All variable names specified on the command line must match the case specified when building the bundle. + /// + CaseSensitive, + } + /// /// Overridable variable information from the BA manifest. /// public interface IOverridableVariables { + /// + /// The of the bundle. + /// + VariableCommandLineType CommandLineType { get; } + /// /// Variable Dictionary of variable name to . /// diff --git a/src/api/burn/WixToolset.Mba.Core/MbaCommand.cs b/src/api/burn/WixToolset.Mba.Core/MbaCommand.cs index e7e49607..424cde63 100644 --- a/src/api/burn/WixToolset.Mba.Core/MbaCommand.cs +++ b/src/api/burn/WixToolset.Mba.Core/MbaCommand.cs @@ -19,9 +19,11 @@ namespace WixToolset.Mba.Core { foreach (var kvp in this.Variables) { - if (!overridableVariables.Variables.TryGetValue(kvp.Key, out var overridableVariable)) + var key = overridableVariables.CommandLineType == VariableCommandLineType.UpperCase ? kvp.Key.ToUpperInvariant() : kvp.Key; + + if (!overridableVariables.Variables.TryGetValue(key, out var overridableVariable)) { - engine.Log(LogLevel.Error, string.Format("Ignoring attempt to set non-overridable variable: '{0}'.", kvp.Key)); + engine.Log(LogLevel.Error, string.Format("Ignoring attempt to set non-overridable variable: '{0}'.", key)); } else { diff --git a/src/api/burn/WixToolset.Mba.Core/OverridableVariables.cs b/src/api/burn/WixToolset.Mba.Core/OverridableVariables.cs index 855ce9a9..148acb34 100644 --- a/src/api/burn/WixToolset.Mba.Core/OverridableVariables.cs +++ b/src/api/burn/WixToolset.Mba.Core/OverridableVariables.cs @@ -12,6 +12,9 @@ namespace WixToolset.Mba.Core /// public class OverridableVariablesInfo : IOverridableVariables { + /// + public VariableCommandLineType CommandLineType { get; internal set; } + /// public IDictionary Variables { get; internal set; } @@ -26,9 +29,36 @@ namespace WixToolset.Mba.Core { XmlNamespaceManager namespaceManager = new XmlNamespaceManager(root.NameTable); namespaceManager.AddNamespace("p", BootstrapperApplicationData.XMLNamespace); + XPathNavigator commandLineNode = root.SelectSingleNode("/p:BootstrapperApplicationData/p:CommandLine", namespaceManager); XPathNodeIterator nodes = root.Select("/p:BootstrapperApplicationData/p:WixStdbaOverridableVariable", namespaceManager); var overridableVariables = new OverridableVariablesInfo(); + + if (commandLineNode == null) + { + throw new Exception("Failed to select command line information."); + } + + string variablesValue = BootstrapperApplicationData.GetAttribute(commandLineNode, "Variables"); + + if (variablesValue == null) + { + throw new Exception("Failed to get command line variable type."); + } + + if (variablesValue.Equals("upperCase", StringComparison.InvariantCulture)) + { + overridableVariables.CommandLineType = VariableCommandLineType.UpperCase; + } + else if (variablesValue.Equals("caseSensitive", StringComparison.InvariantCulture)) + { + overridableVariables.CommandLineType = VariableCommandLineType.CaseSensitive; + } + else + { + throw new Exception(string.Format("Unknown command line variable type: '{0}'", variablesValue)); + } + overridableVariables.Variables = new Dictionary(); foreach (XPathNavigator node in nodes) diff --git a/src/api/burn/balutil/balinfo.cpp b/src/api/burn/balutil/balinfo.cpp index 5927ef72..f71784a5 100644 --- a/src/api/burn/balutil/balinfo.cpp +++ b/src/api/burn/balutil/balinfo.cpp @@ -292,6 +292,7 @@ DAPI_(HRESULT) BalSetOverridableVariablesFromEngine( ) { HRESULT hr = S_OK; + LPWSTR sczKey = NULL; BAL_INFO_OVERRIDABLE_VARIABLE* pOverridableVariable = NULL; for (DWORD i = 0; i < pCommand->cVariables; ++i) @@ -299,6 +300,14 @@ DAPI_(HRESULT) BalSetOverridableVariablesFromEngine( LPCWSTR wzVariableName = pCommand->rgVariableNames[i]; LPCWSTR wzVariableValue = pCommand->rgVariableValues[i]; + if (BAL_INFO_VARIABLE_COMMAND_LINE_TYPE_UPPER_CASE == pOverridableVariables->commandLineType) + { + hr = StrAllocStringToUpperInvariant(&sczKey, wzVariableName, 0); + ExitOnFailure(hr, "Failed to upper case variable name."); + + wzVariableName = sczKey; + } + hr = DictGetValue(pOverridableVariables->sdVariables, wzVariableName, reinterpret_cast(&pOverridableVariable)); if (E_NOTFOUND == hr) { @@ -313,6 +322,8 @@ DAPI_(HRESULT) BalSetOverridableVariablesFromEngine( } LExit: + ReleaseStr(sczKey); + return hr; } @@ -527,10 +538,37 @@ static HRESULT ParseOverridableVariablesFromXml( ) { HRESULT hr = S_OK; + IXMLDOMNode* pCommandLineNode = NULL; + LPWSTR scz = NULL; IXMLDOMNode* pNode = NULL; IXMLDOMNodeList* pNodes = NULL; BAL_INFO_OVERRIDABLE_VARIABLE* pOverridableVariable = NULL; + hr = XmlSelectSingleNode(pixdManifest, L"/BootstrapperApplicationData/CommandLine", &pCommandLineNode); + if (S_FALSE == hr) + { + hr = E_NOTFOUND; + } + ExitOnFailure(hr, "Failed to select command line information."); + + // @Variables + hr = XmlGetAttributeEx(pCommandLineNode, L"Variables", &scz); + ExitOnFailure(hr, "Failed to get command line variable type."); + + if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"upperCase", -1)) + { + pOverridableVariables->commandLineType = BAL_INFO_VARIABLE_COMMAND_LINE_TYPE_UPPER_CASE; + } + else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"caseSensitive", -1)) + { + pOverridableVariables->commandLineType = BAL_INFO_VARIABLE_COMMAND_LINE_TYPE_CASE_SENSITIVE; + } + else + { + hr = E_INVALIDARG; + ExitOnFailure(hr, "Invalid value for CommandLine/@Variables: %ls", scz); + } + // Get the list of variables users can override on the command line. hr = XmlSelectNodes(pixdManifest, L"/BootstrapperApplicationData/WixStdbaOverridableVariable", &pNodes); if (S_FALSE == hr) @@ -570,6 +608,8 @@ static HRESULT ParseOverridableVariablesFromXml( } LExit: + ReleaseStr(scz); + ReleaseObject(pCommandLineNode); ReleaseObject(pNode); ReleaseObject(pNodes); return hr; diff --git a/src/api/burn/balutil/inc/balinfo.h b/src/api/burn/balutil/inc/balinfo.h index 0fce35ec..07a1cbb7 100644 --- a/src/api/burn/balutil/inc/balinfo.h +++ b/src/api/burn/balutil/inc/balinfo.h @@ -18,6 +18,12 @@ typedef enum BAL_INFO_PACKAGE_TYPE BAL_INFO_PACKAGE_TYPE_BUNDLE_PATCH, } BAL_INFO_PACKAGE_TYPE; +typedef enum _BAL_INFO_VARIABLE_COMMAND_LINE_TYPE +{ + BAL_INFO_VARIABLE_COMMAND_LINE_TYPE_UPPER_CASE, + BAL_INFO_VARIABLE_COMMAND_LINE_TYPE_CASE_SENSITIVE, +} BAL_INFO_VARIABLE_COMMAND_LINE_TYPE; + typedef struct _BAL_INFO_PACKAGE { @@ -58,6 +64,7 @@ typedef struct _BAL_INFO_OVERRIDABLE_VARIABLES BAL_INFO_OVERRIDABLE_VARIABLE* rgVariables; DWORD cVariables; STRINGDICT_HANDLE sdVariables; + BAL_INFO_VARIABLE_COMMAND_LINE_TYPE commandLineType; } BAL_INFO_OVERRIDABLE_VARIABLES; diff --git a/src/api/burn/test/WixToolsetTest.Mba.Core/WixToolsetTest.Mba.Core.csproj b/src/api/burn/test/WixToolsetTest.Mba.Core/WixToolsetTest.Mba.Core.csproj index bdb6a829..8d68546f 100644 --- a/src/api/burn/test/WixToolsetTest.Mba.Core/WixToolsetTest.Mba.Core.csproj +++ b/src/api/burn/test/WixToolsetTest.Mba.Core/WixToolsetTest.Mba.Core.csproj @@ -14,6 +14,7 @@ + diff --git a/src/api/wix/WixToolset.Data/Symbols/WixBundleSymbol.cs b/src/api/wix/WixToolset.Data/Symbols/WixBundleSymbol.cs index 9724cbd7..de5646d3 100644 --- a/src/api/wix/WixToolset.Data/Symbols/WixBundleSymbol.cs +++ b/src/api/wix/WixToolset.Data/Symbols/WixBundleSymbol.cs @@ -33,6 +33,7 @@ namespace WixToolset.Data new IntermediateFieldDefinition(nameof(WixBundleSymbolFields.BundleId), IntermediateFieldType.String), new IntermediateFieldDefinition(nameof(WixBundleSymbolFields.ProviderKey), IntermediateFieldType.String), new IntermediateFieldDefinition(nameof(WixBundleSymbolFields.InProgressName), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixBundleSymbolFields.CommandLineVariables), IntermediateFieldType.String), }, typeof(WixBundleSymbol)); } @@ -67,6 +68,7 @@ namespace WixToolset.Data.Symbols BundleId, ProviderKey, InProgressName, + CommandLineVariables, } [Flags] @@ -79,6 +81,12 @@ namespace WixToolset.Data.Symbols PerMachine = 0x8, } + public enum WixBundleCommandLineVariables + { + UpperCase, + CaseSensitive, + } + public class WixBundleSymbol : IntermediateSymbol { public WixBundleSymbol() : base(SymbolDefinitions.WixBundle, null, null) @@ -229,6 +237,12 @@ namespace WixToolset.Data.Symbols set => this.Set((int)WixBundleSymbolFields.InProgressName, value); } + public WixBundleCommandLineVariables CommandLineVariables + { + get => (WixBundleCommandLineVariables)this.Fields[(int)WixBundleSymbolFields.CommandLineVariables].AsNumber(); + set => this.Set((int)WixBundleSymbolFields.CommandLineVariables, (int)value); + } + public PackagingType DefaultPackagingType => (this.Compressed.HasValue && !this.Compressed.Value) ? PackagingType.External : PackagingType.Embedded; public bool DisableModify => (this.Attributes & WixBundleAttributes.DisableModify) == WixBundleAttributes.DisableModify; -- cgit v1.2.3-55-g6feb