diff options
Diffstat (limited to 'src/api')
-rw-r--r-- | src/api/burn/WixToolset.Mba.Core/BootstrapperCommand.cs | 52 | ||||
-rw-r--r-- | src/api/burn/WixToolset.Mba.Core/BundleInfo.cs | 5 | ||||
-rw-r--r-- | src/api/burn/WixToolset.Mba.Core/IBootstrapperCommand.cs | 16 | ||||
-rw-r--r-- | src/api/burn/WixToolset.Mba.Core/IBundleInfo.cs | 5 | ||||
-rw-r--r-- | src/api/burn/WixToolset.Mba.Core/IMbaCommand.cs | 30 | ||||
-rw-r--r-- | src/api/burn/WixToolset.Mba.Core/IOverridableVariableInfo.cs | 15 | ||||
-rw-r--r-- | src/api/burn/WixToolset.Mba.Core/IOverridableVariables.cs | 17 | ||||
-rw-r--r-- | src/api/burn/WixToolset.Mba.Core/MbaCommand.cs | 33 | ||||
-rw-r--r-- | src/api/burn/WixToolset.Mba.Core/OverridableVariableInfo.cs | 15 | ||||
-rw-r--r-- | src/api/burn/WixToolset.Mba.Core/OverridableVariables.cs | 51 | ||||
-rw-r--r-- | src/api/burn/balutil/balinfo.cpp | 203 | ||||
-rw-r--r-- | src/api/burn/balutil/inc/balinfo.h | 55 | ||||
-rw-r--r-- | src/api/burn/balutil/precomp.h | 1 | ||||
-rw-r--r-- | src/api/burn/test/WixToolsetTest.Mba.Core/BaseBootstrapperApplicationFactoryFixture.cs | 13 |
14 files changed, 500 insertions, 11 deletions
diff --git a/src/api/burn/WixToolset.Mba.Core/BootstrapperCommand.cs b/src/api/burn/WixToolset.Mba.Core/BootstrapperCommand.cs index 65dde0f4..345e0448 100644 --- a/src/api/burn/WixToolset.Mba.Core/BootstrapperCommand.cs +++ b/src/api/burn/WixToolset.Mba.Core/BootstrapperCommand.cs | |||
@@ -3,6 +3,7 @@ | |||
3 | namespace WixToolset.Mba.Core | 3 | namespace WixToolset.Mba.Core |
4 | { | 4 | { |
5 | using System; | 5 | using System; |
6 | using System.Collections.Generic; | ||
6 | using System.ComponentModel; | 7 | using System.ComponentModel; |
7 | using System.Runtime.InteropServices; | 8 | using System.Runtime.InteropServices; |
8 | 9 | ||
@@ -11,8 +12,6 @@ namespace WixToolset.Mba.Core | |||
11 | /// </summary> | 12 | /// </summary> |
12 | public sealed class BootstrapperCommand : IBootstrapperCommand | 13 | public sealed class BootstrapperCommand : IBootstrapperCommand |
13 | { | 14 | { |
14 | private readonly string commandLine; | ||
15 | |||
16 | /// <summary> | 15 | /// <summary> |
17 | /// | 16 | /// |
18 | /// </summary> | 17 | /// </summary> |
@@ -45,7 +44,7 @@ namespace WixToolset.Mba.Core | |||
45 | this.Action = action; | 44 | this.Action = action; |
46 | this.Display = display; | 45 | this.Display = display; |
47 | this.Restart = restart; | 46 | this.Restart = restart; |
48 | this.commandLine = commandLine; | 47 | this.CommandLine = commandLine; |
49 | this.CmdShow = cmdShow; | 48 | this.CmdShow = cmdShow; |
50 | this.Resume = resume; | 49 | this.Resume = resume; |
51 | this.SplashScreen = splashScreen; | 50 | this.SplashScreen = splashScreen; |
@@ -66,7 +65,7 @@ namespace WixToolset.Mba.Core | |||
66 | public Restart Restart { get; } | 65 | public Restart Restart { get; } |
67 | 66 | ||
68 | /// <inheritdoc/> | 67 | /// <inheritdoc/> |
69 | public string[] CommandLineArgs => GetCommandLineArgs(this.commandLine); | 68 | public string CommandLine { get; } |
70 | 69 | ||
71 | /// <inheritdoc/> | 70 | /// <inheritdoc/> |
72 | public int CmdShow { get; } | 71 | public int CmdShow { get; } |
@@ -92,6 +91,49 @@ namespace WixToolset.Mba.Core | |||
92 | /// <inheritdoc/> | 91 | /// <inheritdoc/> |
93 | public string BootstrapperApplicationDataPath { get; } | 92 | public string BootstrapperApplicationDataPath { get; } |
94 | 93 | ||
94 | /// <inheritdoc/> | ||
95 | public IMbaCommand ParseCommandLine() | ||
96 | { | ||
97 | var args = ParseCommandLineToArgs(this.CommandLine); | ||
98 | var unknownArgs = new List<string>(); | ||
99 | var variables = new List<KeyValuePair<string, string>>(); | ||
100 | |||
101 | foreach (var arg in args) | ||
102 | { | ||
103 | var unknownArg = false; | ||
104 | |||
105 | if (arg[0] == '-' || arg[0] == '/') | ||
106 | { | ||
107 | unknownArg = true; | ||
108 | } | ||
109 | else | ||
110 | { | ||
111 | var index = arg.IndexOf('='); | ||
112 | if (index == -1) | ||
113 | { | ||
114 | unknownArg = true; | ||
115 | } | ||
116 | else | ||
117 | { | ||
118 | var name = arg.Substring(0, index); | ||
119 | var value = arg.Substring(index + 1); | ||
120 | variables.Add(new KeyValuePair<string, string>(name, value)); | ||
121 | } | ||
122 | } | ||
123 | |||
124 | if (unknownArg) | ||
125 | { | ||
126 | unknownArgs.Add(arg); | ||
127 | } | ||
128 | } | ||
129 | |||
130 | return new MbaCommand | ||
131 | { | ||
132 | UnknownCommandLineArgs = unknownArgs.ToArray(), | ||
133 | Variables = variables.ToArray(), | ||
134 | }; | ||
135 | } | ||
136 | |||
95 | /// <summary> | 137 | /// <summary> |
96 | /// Gets the command line arguments as a string array. | 138 | /// Gets the command line arguments as a string array. |
97 | /// </summary> | 139 | /// </summary> |
@@ -102,7 +144,7 @@ namespace WixToolset.Mba.Core | |||
102 | /// <remarks> | 144 | /// <remarks> |
103 | /// This method uses the same parsing as the operating system which handles quotes and spaces correctly. | 145 | /// This method uses the same parsing as the operating system which handles quotes and spaces correctly. |
104 | /// </remarks> | 146 | /// </remarks> |
105 | public static string[] GetCommandLineArgs(string commandLine) | 147 | public static string[] ParseCommandLineToArgs(string commandLine) |
106 | { | 148 | { |
107 | if (null == commandLine) | 149 | if (null == commandLine) |
108 | { | 150 | { |
diff --git a/src/api/burn/WixToolset.Mba.Core/BundleInfo.cs b/src/api/burn/WixToolset.Mba.Core/BundleInfo.cs index 3d5d535d..4a533bf9 100644 --- a/src/api/burn/WixToolset.Mba.Core/BundleInfo.cs +++ b/src/api/burn/WixToolset.Mba.Core/BundleInfo.cs | |||
@@ -23,6 +23,9 @@ namespace WixToolset.Mba.Core | |||
23 | public string LogVariable { get; internal set; } | 23 | public string LogVariable { get; internal set; } |
24 | 24 | ||
25 | /// <inheritdoc/> | 25 | /// <inheritdoc/> |
26 | public IOverridableVariables OverridableVariables { get; internal set; } | ||
27 | |||
28 | /// <inheritdoc/> | ||
26 | public IDictionary<string, IPackageInfo> Packages { get; internal set; } | 29 | public IDictionary<string, IPackageInfo> Packages { get; internal set; } |
27 | 30 | ||
28 | internal BundleInfo() | 31 | internal BundleInfo() |
@@ -78,6 +81,8 @@ namespace WixToolset.Mba.Core | |||
78 | 81 | ||
79 | bundle.LogVariable = BootstrapperApplicationData.GetAttribute(bundleNode, "LogPathVariable"); | 82 | bundle.LogVariable = BootstrapperApplicationData.GetAttribute(bundleNode, "LogPathVariable"); |
80 | 83 | ||
84 | bundle.OverridableVariables = OverridableVariablesInfo.ParseFromXml(root); | ||
85 | |||
81 | bundle.Packages = PackageInfo.ParsePackagesFromXml(root); | 86 | bundle.Packages = PackageInfo.ParsePackagesFromXml(root); |
82 | 87 | ||
83 | return bundle; | 88 | return bundle; |
diff --git a/src/api/burn/WixToolset.Mba.Core/IBootstrapperCommand.cs b/src/api/burn/WixToolset.Mba.Core/IBootstrapperCommand.cs index e861813f..b7baa55c 100644 --- a/src/api/burn/WixToolset.Mba.Core/IBootstrapperCommand.cs +++ b/src/api/burn/WixToolset.Mba.Core/IBootstrapperCommand.cs | |||
@@ -25,13 +25,12 @@ namespace WixToolset.Mba.Core | |||
25 | Restart Restart { get; } | 25 | Restart Restart { get; } |
26 | 26 | ||
27 | /// <summary> | 27 | /// <summary> |
28 | /// Gets the command line arguments as a string array. | 28 | /// Gets the command line arguments. |
29 | /// </summary> | 29 | /// </summary> |
30 | /// <returns> | 30 | /// <returns> |
31 | /// Array of command line arguments not handled by the engine. | 31 | /// Command line arguments not handled by the engine. |
32 | /// </returns> | 32 | /// </returns> |
33 | /// <exception type="Win32Exception">The command line could not be parsed into an array.</exception> | 33 | string CommandLine { get; } |
34 | string[] CommandLineArgs { get; } | ||
35 | 34 | ||
36 | /// <summary> | 35 | /// <summary> |
37 | /// Hint for the initial visibility of the window. | 36 | /// Hint for the initial visibility of the window. |
@@ -72,5 +71,14 @@ namespace WixToolset.Mba.Core | |||
72 | /// Gets path to BootstrapperApplicationData.xml. | 71 | /// Gets path to BootstrapperApplicationData.xml. |
73 | /// </summary> | 72 | /// </summary> |
74 | string BootstrapperApplicationDataPath { get; } | 73 | string BootstrapperApplicationDataPath { get; } |
74 | |||
75 | /// <summary> | ||
76 | /// Parses the command line arguments into an <see cref="IMbaCommand"/>. | ||
77 | /// </summary> | ||
78 | /// <returns> | ||
79 | /// The parsed information. | ||
80 | /// </returns> | ||
81 | /// <exception type="Win32Exception">The command line could not be parsed.</exception> | ||
82 | IMbaCommand ParseCommandLine(); | ||
75 | } | 83 | } |
76 | } | 84 | } |
diff --git a/src/api/burn/WixToolset.Mba.Core/IBundleInfo.cs b/src/api/burn/WixToolset.Mba.Core/IBundleInfo.cs index f4a82f36..35decc88 100644 --- a/src/api/burn/WixToolset.Mba.Core/IBundleInfo.cs +++ b/src/api/burn/WixToolset.Mba.Core/IBundleInfo.cs | |||
@@ -22,6 +22,11 @@ namespace WixToolset.Mba.Core | |||
22 | /// <summary> | 22 | /// <summary> |
23 | /// | 23 | /// |
24 | /// </summary> | 24 | /// </summary> |
25 | IOverridableVariables OverridableVariables { get; } | ||
26 | |||
27 | /// <summary> | ||
28 | /// | ||
29 | /// </summary> | ||
25 | IDictionary<string, IPackageInfo> Packages { get; } | 30 | IDictionary<string, IPackageInfo> Packages { get; } |
26 | 31 | ||
27 | /// <summary> | 32 | /// <summary> |
diff --git a/src/api/burn/WixToolset.Mba.Core/IMbaCommand.cs b/src/api/burn/WixToolset.Mba.Core/IMbaCommand.cs new file mode 100644 index 00000000..a3ad68d8 --- /dev/null +++ b/src/api/burn/WixToolset.Mba.Core/IMbaCommand.cs | |||
@@ -0,0 +1,30 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
2 | |||
3 | namespace WixToolset.Mba.Core | ||
4 | { | ||
5 | using System.Collections.Generic; | ||
6 | |||
7 | /// <summary> | ||
8 | /// Command information parsed from the command line. | ||
9 | /// </summary> | ||
10 | public interface IMbaCommand | ||
11 | { | ||
12 | /// <summary> | ||
13 | /// The command line arguments not parsed into <see cref="IBootstrapperCommand"/> or <see cref="IMbaCommand"/>. | ||
14 | /// </summary> | ||
15 | string[] UnknownCommandLineArgs { get; } | ||
16 | |||
17 | /// <summary> | ||
18 | /// The variables that were parsed from the command line. | ||
19 | /// Key = variable name, Value = variable value. | ||
20 | /// </summary> | ||
21 | KeyValuePair<string, string>[] Variables { get; } | ||
22 | |||
23 | /// <summary> | ||
24 | /// Sets overridable variables from the command line. | ||
25 | /// </summary> | ||
26 | /// <param name="overridableVariables">The overridable variable information from <see cref="IBootstrapperApplicationData"/>.</param> | ||
27 | /// <param name="engine">The engine.</param> | ||
28 | void SetOverridableVariables(IOverridableVariables overridableVariables, IEngine engine); | ||
29 | } | ||
30 | } | ||
diff --git a/src/api/burn/WixToolset.Mba.Core/IOverridableVariableInfo.cs b/src/api/burn/WixToolset.Mba.Core/IOverridableVariableInfo.cs new file mode 100644 index 00000000..d01dead3 --- /dev/null +++ b/src/api/burn/WixToolset.Mba.Core/IOverridableVariableInfo.cs | |||
@@ -0,0 +1,15 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
2 | |||
3 | namespace WixToolset.Mba.Core | ||
4 | { | ||
5 | /// <summary> | ||
6 | /// Overridable variable from the BA manifest. | ||
7 | /// </summary> | ||
8 | public interface IOverridableVariableInfo | ||
9 | { | ||
10 | /// <summary> | ||
11 | /// The Variable name. | ||
12 | /// </summary> | ||
13 | string Name { get; } | ||
14 | } | ||
15 | } \ No newline at end of file | ||
diff --git a/src/api/burn/WixToolset.Mba.Core/IOverridableVariables.cs b/src/api/burn/WixToolset.Mba.Core/IOverridableVariables.cs new file mode 100644 index 00000000..3944913b --- /dev/null +++ b/src/api/burn/WixToolset.Mba.Core/IOverridableVariables.cs | |||
@@ -0,0 +1,17 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
2 | |||
3 | namespace WixToolset.Mba.Core | ||
4 | { | ||
5 | using System.Collections.Generic; | ||
6 | |||
7 | /// <summary> | ||
8 | /// Overridable variable information from the BA manifest. | ||
9 | /// </summary> | ||
10 | public interface IOverridableVariables | ||
11 | { | ||
12 | /// <summary> | ||
13 | /// Variable Dictionary of variable name to <see cref="IOverridableVariableInfo"/>. | ||
14 | /// </summary> | ||
15 | IDictionary<string, IOverridableVariableInfo> Variables { get; } | ||
16 | } | ||
17 | } \ No newline at end of file | ||
diff --git a/src/api/burn/WixToolset.Mba.Core/MbaCommand.cs b/src/api/burn/WixToolset.Mba.Core/MbaCommand.cs new file mode 100644 index 00000000..e7e49607 --- /dev/null +++ b/src/api/burn/WixToolset.Mba.Core/MbaCommand.cs | |||
@@ -0,0 +1,33 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
2 | |||
3 | namespace WixToolset.Mba.Core | ||
4 | { | ||
5 | using System.Collections.Generic; | ||
6 | |||
7 | /// <summary> | ||
8 | /// Default implementation of <see cref="IMbaCommand"/>. | ||
9 | /// </summary> | ||
10 | internal sealed class MbaCommand : IMbaCommand | ||
11 | { | ||
12 | public string[] UnknownCommandLineArgs { get; internal set; } | ||
13 | |||
14 | public KeyValuePair<string, string>[] Variables { get; internal set; } | ||
15 | |||
16 | internal MbaCommand() { } | ||
17 | |||
18 | public void SetOverridableVariables(IOverridableVariables overridableVariables, IEngine engine) | ||
19 | { | ||
20 | foreach (var kvp in this.Variables) | ||
21 | { | ||
22 | if (!overridableVariables.Variables.TryGetValue(kvp.Key, out var overridableVariable)) | ||
23 | { | ||
24 | engine.Log(LogLevel.Error, string.Format("Ignoring attempt to set non-overridable variable: '{0}'.", kvp.Key)); | ||
25 | } | ||
26 | else | ||
27 | { | ||
28 | engine.SetVariableString(overridableVariable.Name, kvp.Value, false); | ||
29 | } | ||
30 | } | ||
31 | } | ||
32 | } | ||
33 | } | ||
diff --git a/src/api/burn/WixToolset.Mba.Core/OverridableVariableInfo.cs b/src/api/burn/WixToolset.Mba.Core/OverridableVariableInfo.cs new file mode 100644 index 00000000..b8e85c34 --- /dev/null +++ b/src/api/burn/WixToolset.Mba.Core/OverridableVariableInfo.cs | |||
@@ -0,0 +1,15 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
2 | |||
3 | namespace WixToolset.Mba.Core | ||
4 | { | ||
5 | /// <summary> | ||
6 | /// Default implementation of <see cref="IOverridableVariableInfo"/>. | ||
7 | /// </summary> | ||
8 | internal class OverridableVariableInfo : IOverridableVariableInfo | ||
9 | { | ||
10 | /// <inheritdoc /> | ||
11 | public string Name { get; internal set; } | ||
12 | |||
13 | internal OverridableVariableInfo() { } | ||
14 | } | ||
15 | } | ||
diff --git a/src/api/burn/WixToolset.Mba.Core/OverridableVariables.cs b/src/api/burn/WixToolset.Mba.Core/OverridableVariables.cs new file mode 100644 index 00000000..855ce9a9 --- /dev/null +++ b/src/api/burn/WixToolset.Mba.Core/OverridableVariables.cs | |||
@@ -0,0 +1,51 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
2 | |||
3 | namespace WixToolset.Mba.Core | ||
4 | { | ||
5 | using System; | ||
6 | using System.Collections.Generic; | ||
7 | using System.Xml; | ||
8 | using System.Xml.XPath; | ||
9 | |||
10 | /// <summary> | ||
11 | /// Default implementation of <see cref="IOverridableVariables"/>. | ||
12 | /// </summary> | ||
13 | public class OverridableVariablesInfo : IOverridableVariables | ||
14 | { | ||
15 | /// <inheritdoc /> | ||
16 | public IDictionary<string, IOverridableVariableInfo> Variables { get; internal set; } | ||
17 | |||
18 | internal OverridableVariablesInfo() { } | ||
19 | |||
20 | /// <summary> | ||
21 | /// Parses the overridable variable info from the BA manifest. | ||
22 | /// </summary> | ||
23 | /// <param name="root">XML root</param> | ||
24 | /// <returns>The parsed information.</returns> | ||
25 | public static IOverridableVariables ParseFromXml(XPathNavigator root) | ||
26 | { | ||
27 | XmlNamespaceManager namespaceManager = new XmlNamespaceManager(root.NameTable); | ||
28 | namespaceManager.AddNamespace("p", BootstrapperApplicationData.XMLNamespace); | ||
29 | XPathNodeIterator nodes = root.Select("/p:BootstrapperApplicationData/p:WixStdbaOverridableVariable", namespaceManager); | ||
30 | |||
31 | var overridableVariables = new OverridableVariablesInfo(); | ||
32 | overridableVariables.Variables = new Dictionary<string, IOverridableVariableInfo>(); | ||
33 | |||
34 | foreach (XPathNavigator node in nodes) | ||
35 | { | ||
36 | var variable = new OverridableVariableInfo(); | ||
37 | |||
38 | string name = BootstrapperApplicationData.GetAttribute(node, "Name"); | ||
39 | if (name == null) | ||
40 | { | ||
41 | throw new Exception("Failed to get name for overridable variable."); | ||
42 | } | ||
43 | variable.Name = name; | ||
44 | |||
45 | overridableVariables.Variables.Add(variable.Name, variable); | ||
46 | } | ||
47 | |||
48 | return overridableVariables; | ||
49 | } | ||
50 | } | ||
51 | } | ||
diff --git a/src/api/burn/balutil/balinfo.cpp b/src/api/burn/balutil/balinfo.cpp index 3abb9286..5927ef72 100644 --- a/src/api/burn/balutil/balinfo.cpp +++ b/src/api/burn/balutil/balinfo.cpp | |||
@@ -11,7 +11,88 @@ static HRESULT ParseBalPackageInfoFromXml( | |||
11 | __in BAL_INFO_PACKAGES* pPackages, | 11 | __in BAL_INFO_PACKAGES* pPackages, |
12 | __in IXMLDOMDocument* pixdManifest | 12 | __in IXMLDOMDocument* pixdManifest |
13 | ); | 13 | ); |
14 | static HRESULT ParseOverridableVariablesFromXml( | ||
15 | __in BAL_INFO_OVERRIDABLE_VARIABLES* pOverridableVariables, | ||
16 | __in IXMLDOMDocument* pixdManifest | ||
17 | ); | ||
18 | |||
19 | |||
20 | DAPI_(HRESULT) BalInfoParseCommandLine( | ||
21 | __in BAL_INFO_COMMAND* pCommand, | ||
22 | __in LPCWSTR wzCommandLine | ||
23 | ) | ||
24 | { | ||
25 | HRESULT hr = S_OK; | ||
26 | int argc = 0; | ||
27 | LPWSTR* argv = NULL; | ||
28 | BOOL fUnknownArg = FALSE; | ||
29 | |||
30 | BalInfoUninitializeCommandLine(pCommand); | ||
31 | |||
32 | if (!wzCommandLine || !*wzCommandLine) | ||
33 | { | ||
34 | ExitFunction(); | ||
35 | } | ||
36 | |||
37 | hr = AppParseCommandLine(wzCommandLine, &argc, &argv); | ||
38 | ExitOnFailure(hr, "Failed to parse command line."); | ||
14 | 39 | ||
40 | for (int i = 0; i < argc; ++i) | ||
41 | { | ||
42 | fUnknownArg = FALSE; | ||
43 | |||
44 | if (argv[i][0] == L'-' || argv[i][0] == L'/') | ||
45 | { | ||
46 | fUnknownArg = TRUE; | ||
47 | } | ||
48 | else | ||
49 | { | ||
50 | const wchar_t* pwc = wcschr(argv[i], L'='); | ||
51 | if (!pwc) | ||
52 | { | ||
53 | fUnknownArg = TRUE; | ||
54 | } | ||
55 | else | ||
56 | { | ||
57 | hr = MemEnsureArraySizeForNewItems(reinterpret_cast<LPVOID*>(&pCommand->rgVariableNames), pCommand->cVariables, 1, sizeof(LPWSTR), 5); | ||
58 | ExitOnFailure(hr, "Failed to ensure size for variable names."); | ||
59 | |||
60 | hr = MemEnsureArraySizeForNewItems(reinterpret_cast<LPVOID*>(&pCommand->rgVariableValues), pCommand->cVariables, 1, sizeof(LPWSTR), 5); | ||
61 | ExitOnFailure(hr, "Failed to ensure size for variable values."); | ||
62 | |||
63 | LPWSTR* psczVariableName = pCommand->rgVariableNames + pCommand->cVariables; | ||
64 | LPWSTR* psczVariableValue = pCommand->rgVariableValues + pCommand->cVariables; | ||
65 | pCommand->cVariables += 1; | ||
66 | |||
67 | hr = StrAllocString(psczVariableName, argv[i], pwc - argv[i]); | ||
68 | BalExitOnFailure(hr, "Failed to copy variable name."); | ||
69 | |||
70 | hr = StrAllocString(psczVariableValue, ++pwc, 0); | ||
71 | BalExitOnFailure(hr, "Failed to copy variable value."); | ||
72 | } | ||
73 | } | ||
74 | |||
75 | if (fUnknownArg) | ||
76 | { | ||
77 | hr = MemEnsureArraySizeForNewItems(reinterpret_cast<LPVOID*>(&pCommand->rgUnknownArgs), pCommand->cUnknownArgs, 1, sizeof(LPWSTR), 5); | ||
78 | BalExitOnFailure(hr, "Failed to ensure size for unknown args."); | ||
79 | |||
80 | LPWSTR* psczArg = pCommand->rgUnknownArgs + pCommand->cUnknownArgs; | ||
81 | pCommand->cUnknownArgs += 1; | ||
82 | |||
83 | StrAllocString(psczArg, argv[i], 0); | ||
84 | BalExitOnFailure(hr, "Failed to copy unknown arg."); | ||
85 | } | ||
86 | } | ||
87 | |||
88 | LExit: | ||
89 | if (argv) | ||
90 | { | ||
91 | AppFreeCommandLineArgs(argv); | ||
92 | } | ||
93 | |||
94 | return hr; | ||
95 | } | ||
15 | 96 | ||
16 | DAPI_(HRESULT) BalInfoParseFromXml( | 97 | DAPI_(HRESULT) BalInfoParseFromXml( |
17 | __in BAL_INFO_BUNDLE* pBundle, | 98 | __in BAL_INFO_BUNDLE* pBundle, |
@@ -45,6 +126,9 @@ DAPI_(HRESULT) BalInfoParseFromXml( | |||
45 | } | 126 | } |
46 | } | 127 | } |
47 | 128 | ||
129 | hr = ParseOverridableVariablesFromXml(&pBundle->overridableVariables, pixdManifest); | ||
130 | BalExitOnFailure(hr, "Failed to parse overridable variables from bootstrapper application data."); | ||
131 | |||
48 | hr = ParsePackagesFromXml(&pBundle->packages, pixdManifest); | 132 | hr = ParsePackagesFromXml(&pBundle->packages, pixdManifest); |
49 | BalExitOnFailure(hr, "Failed to parse package information from bootstrapper application data."); | 133 | BalExitOnFailure(hr, "Failed to parse package information from bootstrapper application data."); |
50 | 134 | ||
@@ -163,12 +247,76 @@ DAPI_(void) BalInfoUninitialize( | |||
163 | 247 | ||
164 | ReleaseMem(pBundle->packages.rgPackages); | 248 | ReleaseMem(pBundle->packages.rgPackages); |
165 | 249 | ||
250 | for (DWORD i = 0; i < pBundle->overridableVariables.cVariables; ++i) | ||
251 | { | ||
252 | ReleaseStr(pBundle->overridableVariables.rgVariables[i].sczName); | ||
253 | } | ||
254 | |||
255 | ReleaseMem(pBundle->overridableVariables.rgVariables); | ||
256 | ReleaseDict(pBundle->overridableVariables.sdVariables); | ||
257 | |||
166 | ReleaseStr(pBundle->sczName); | 258 | ReleaseStr(pBundle->sczName); |
167 | ReleaseStr(pBundle->sczLogVariable); | 259 | ReleaseStr(pBundle->sczLogVariable); |
168 | memset(pBundle, 0, sizeof(BAL_INFO_BUNDLE)); | 260 | memset(pBundle, 0, sizeof(BAL_INFO_BUNDLE)); |
169 | } | 261 | } |
170 | 262 | ||
171 | 263 | ||
264 | DAPI_(void) BalInfoUninitializeCommandLine( | ||
265 | __in BAL_INFO_COMMAND* pCommand | ||
266 | ) | ||
267 | { | ||
268 | for (DWORD i = 0; i < pCommand->cUnknownArgs; ++i) | ||
269 | { | ||
270 | ReleaseNullStrSecure(pCommand->rgUnknownArgs[i]); | ||
271 | } | ||
272 | |||
273 | ReleaseMem(pCommand->rgUnknownArgs); | ||
274 | |||
275 | for (DWORD i = 0; i < pCommand->cVariables; ++i) | ||
276 | { | ||
277 | ReleaseNullStrSecure(pCommand->rgVariableNames[i]); | ||
278 | ReleaseNullStrSecure(pCommand->rgVariableValues[i]); | ||
279 | } | ||
280 | |||
281 | ReleaseMem(pCommand->rgVariableNames); | ||
282 | ReleaseMem(pCommand->rgVariableValues); | ||
283 | |||
284 | memset(pCommand, 0, sizeof(BAL_INFO_COMMAND)); | ||
285 | } | ||
286 | |||
287 | |||
288 | DAPI_(HRESULT) BalSetOverridableVariablesFromEngine( | ||
289 | __in BAL_INFO_OVERRIDABLE_VARIABLES* pOverridableVariables, | ||
290 | __in BAL_INFO_COMMAND* pCommand, | ||
291 | __in IBootstrapperEngine* pEngine | ||
292 | ) | ||
293 | { | ||
294 | HRESULT hr = S_OK; | ||
295 | BAL_INFO_OVERRIDABLE_VARIABLE* pOverridableVariable = NULL; | ||
296 | |||
297 | for (DWORD i = 0; i < pCommand->cVariables; ++i) | ||
298 | { | ||
299 | LPCWSTR wzVariableName = pCommand->rgVariableNames[i]; | ||
300 | LPCWSTR wzVariableValue = pCommand->rgVariableValues[i]; | ||
301 | |||
302 | hr = DictGetValue(pOverridableVariables->sdVariables, wzVariableName, reinterpret_cast<void**>(&pOverridableVariable)); | ||
303 | if (E_NOTFOUND == hr) | ||
304 | { | ||
305 | BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Ignoring attempt to set non-overridable variable: '%ls'.", wzVariableName); | ||
306 | hr = S_OK; | ||
307 | continue; | ||
308 | } | ||
309 | BalExitOnFailure(hr, "Failed to check the dictionary of overridable variables."); | ||
310 | |||
311 | hr = pEngine->SetVariableString(pOverridableVariable->sczName, wzVariableValue, FALSE); | ||
312 | BalExitOnFailure(hr, "Failed to set variable: '%ls'.", pOverridableVariable->sczName); | ||
313 | } | ||
314 | |||
315 | LExit: | ||
316 | return hr; | ||
317 | } | ||
318 | |||
319 | |||
172 | static HRESULT ParsePackagesFromXml( | 320 | static HRESULT ParsePackagesFromXml( |
173 | __in BAL_INFO_PACKAGES* pPackages, | 321 | __in BAL_INFO_PACKAGES* pPackages, |
174 | __in IXMLDOMDocument* pixdManifest | 322 | __in IXMLDOMDocument* pixdManifest |
@@ -371,3 +519,58 @@ LExit: | |||
371 | 519 | ||
372 | return hr; | 520 | return hr; |
373 | } | 521 | } |
522 | |||
523 | |||
524 | static HRESULT ParseOverridableVariablesFromXml( | ||
525 | __in BAL_INFO_OVERRIDABLE_VARIABLES* pOverridableVariables, | ||
526 | __in IXMLDOMDocument* pixdManifest | ||
527 | ) | ||
528 | { | ||
529 | HRESULT hr = S_OK; | ||
530 | IXMLDOMNode* pNode = NULL; | ||
531 | IXMLDOMNodeList* pNodes = NULL; | ||
532 | BAL_INFO_OVERRIDABLE_VARIABLE* pOverridableVariable = NULL; | ||
533 | |||
534 | // Get the list of variables users can override on the command line. | ||
535 | hr = XmlSelectNodes(pixdManifest, L"/BootstrapperApplicationData/WixStdbaOverridableVariable", &pNodes); | ||
536 | if (S_FALSE == hr) | ||
537 | { | ||
538 | ExitFunction1(hr = S_OK); | ||
539 | } | ||
540 | ExitOnFailure(hr, "Failed to select overridable variable nodes."); | ||
541 | |||
542 | hr = pNodes->get_length(reinterpret_cast<long*>(&pOverridableVariables->cVariables)); | ||
543 | ExitOnFailure(hr, "Failed to get overridable variable node count."); | ||
544 | |||
545 | if (pOverridableVariables->cVariables) | ||
546 | { | ||
547 | hr = DictCreateWithEmbeddedKey(&pOverridableVariables->sdVariables, pOverridableVariables->cVariables, reinterpret_cast<void**>(&pOverridableVariables->rgVariables), offsetof(BAL_INFO_OVERRIDABLE_VARIABLE, sczName), DICT_FLAG_NONE); | ||
548 | ExitOnFailure(hr, "Failed to create the overridable variables string dictionary."); | ||
549 | |||
550 | hr = MemAllocArray(reinterpret_cast<LPVOID*>(&pOverridableVariables->rgVariables), sizeof(pOverridableVariable), pOverridableVariables->cVariables); | ||
551 | ExitOnFailure(hr, "Failed to create the overridable variables array."); | ||
552 | |||
553 | for (DWORD i = 0; i < pOverridableVariables->cVariables; ++i) | ||
554 | { | ||
555 | pOverridableVariable = pOverridableVariables->rgVariables + i; | ||
556 | |||
557 | hr = XmlNextElement(pNodes, &pNode, NULL); | ||
558 | ExitOnFailure(hr, "Failed to get next node."); | ||
559 | |||
560 | // @Name | ||
561 | hr = XmlGetAttributeEx(pNode, L"Name", &pOverridableVariable->sczName); | ||
562 | ExitOnFailure(hr, "Failed to get name for overridable variable."); | ||
563 | |||
564 | hr = DictAddValue(pOverridableVariables->sdVariables, pOverridableVariable); | ||
565 | ExitOnFailure(hr, "Failed to add \"%ls\" to the string dictionary.", pOverridableVariable->sczName); | ||
566 | |||
567 | // prepare next iteration | ||
568 | ReleaseNullObject(pNode); | ||
569 | } | ||
570 | } | ||
571 | |||
572 | LExit: | ||
573 | ReleaseObject(pNode); | ||
574 | ReleaseObject(pNodes); | ||
575 | return hr; | ||
576 | } | ||
diff --git a/src/api/burn/balutil/inc/balinfo.h b/src/api/burn/balutil/inc/balinfo.h index 8c2155e9..0fce35ec 100644 --- a/src/api/burn/balutil/inc/balinfo.h +++ b/src/api/burn/balutil/inc/balinfo.h | |||
@@ -47,15 +47,50 @@ typedef struct _BAL_INFO_PACKAGES | |||
47 | } BAL_INFO_PACKAGES; | 47 | } BAL_INFO_PACKAGES; |
48 | 48 | ||
49 | 49 | ||
50 | typedef struct _BAL_INFO_OVERRIDABLE_VARIABLE | ||
51 | { | ||
52 | LPWSTR sczName; | ||
53 | } BAL_INFO_OVERRIDABLE_VARIABLE; | ||
54 | |||
55 | |||
56 | typedef struct _BAL_INFO_OVERRIDABLE_VARIABLES | ||
57 | { | ||
58 | BAL_INFO_OVERRIDABLE_VARIABLE* rgVariables; | ||
59 | DWORD cVariables; | ||
60 | STRINGDICT_HANDLE sdVariables; | ||
61 | } BAL_INFO_OVERRIDABLE_VARIABLES; | ||
62 | |||
63 | |||
50 | typedef struct _BAL_INFO_BUNDLE | 64 | typedef struct _BAL_INFO_BUNDLE |
51 | { | 65 | { |
52 | BOOL fPerMachine; | 66 | BOOL fPerMachine; |
53 | LPWSTR sczName; | 67 | LPWSTR sczName; |
54 | LPWSTR sczLogVariable; | 68 | LPWSTR sczLogVariable; |
55 | BAL_INFO_PACKAGES packages; | 69 | BAL_INFO_PACKAGES packages; |
70 | BAL_INFO_OVERRIDABLE_VARIABLES overridableVariables; | ||
56 | } BAL_INFO_BUNDLE; | 71 | } BAL_INFO_BUNDLE; |
57 | 72 | ||
58 | 73 | ||
74 | typedef struct _BAL_INFO_COMMAND | ||
75 | { | ||
76 | DWORD cUnknownArgs; | ||
77 | LPWSTR* rgUnknownArgs; | ||
78 | DWORD cVariables; | ||
79 | LPWSTR* rgVariableNames; | ||
80 | LPWSTR* rgVariableValues; | ||
81 | } BAL_INFO_COMMAND; | ||
82 | |||
83 | |||
84 | /******************************************************************* | ||
85 | BalInfoParseCommandLine - parses wzCommandLine from BOOTSTRAPPER_COMMAND. | ||
86 | |||
87 | ********************************************************************/ | ||
88 | HRESULT DAPI BalInfoParseCommandLine( | ||
89 | __in BAL_INFO_COMMAND* pCommand, | ||
90 | __in LPCWSTR wzCommandLine | ||
91 | ); | ||
92 | |||
93 | |||
59 | /******************************************************************* | 94 | /******************************************************************* |
60 | BalInfoParseFromXml - loads the bundle and package info from the UX | 95 | BalInfoParseFromXml - loads the bundle and package info from the UX |
61 | manifest. | 96 | manifest. |
@@ -100,6 +135,26 @@ DAPI_(void) BalInfoUninitialize( | |||
100 | ); | 135 | ); |
101 | 136 | ||
102 | 137 | ||
138 | /******************************************************************* | ||
139 | BalInfoUninitializeCommandLine - uninitializes BAL_INFO_COMMAND. | ||
140 | |||
141 | ********************************************************************/ | ||
142 | void DAPI BalInfoUninitializeCommandLine( | ||
143 | __in BAL_INFO_COMMAND* pCommand | ||
144 | ); | ||
145 | |||
146 | |||
147 | /******************************************************************* | ||
148 | BalInfoSetOverridableVariablesFromEngine - sets overridable variables from command line. | ||
149 | |||
150 | ********************************************************************/ | ||
151 | HRESULT DAPI BalSetOverridableVariablesFromEngine( | ||
152 | __in BAL_INFO_OVERRIDABLE_VARIABLES* pOverridableVariables, | ||
153 | __in BAL_INFO_COMMAND* pCommand, | ||
154 | __in IBootstrapperEngine* pEngine | ||
155 | ); | ||
156 | |||
157 | |||
103 | #ifdef __cplusplus | 158 | #ifdef __cplusplus |
104 | } | 159 | } |
105 | #endif | 160 | #endif |
diff --git a/src/api/burn/balutil/precomp.h b/src/api/burn/balutil/precomp.h index 15142210..64d4a6cf 100644 --- a/src/api/burn/balutil/precomp.h +++ b/src/api/burn/balutil/precomp.h | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <strsafe.h> | 16 | #include <strsafe.h> |
17 | 17 | ||
18 | #include <dutil.h> | 18 | #include <dutil.h> |
19 | #include <apputil.h> | ||
19 | #include <pathutil.h> | 20 | #include <pathutil.h> |
20 | #include <locutil.h> | 21 | #include <locutil.h> |
21 | #include <memutil.h> | 22 | #include <memutil.h> |
diff --git a/src/api/burn/test/WixToolsetTest.Mba.Core/BaseBootstrapperApplicationFactoryFixture.cs b/src/api/burn/test/WixToolsetTest.Mba.Core/BaseBootstrapperApplicationFactoryFixture.cs index aaf5ee29..b49b3927 100644 --- a/src/api/burn/test/WixToolsetTest.Mba.Core/BaseBootstrapperApplicationFactoryFixture.cs +++ b/src/api/burn/test/WixToolsetTest.Mba.Core/BaseBootstrapperApplicationFactoryFixture.cs | |||
@@ -3,6 +3,7 @@ | |||
3 | namespace WixToolsetTest.Mba.Core | 3 | namespace WixToolsetTest.Mba.Core |
4 | { | 4 | { |
5 | using System; | 5 | using System; |
6 | using System.Collections.Generic; | ||
6 | using System.Runtime.InteropServices; | 7 | using System.Runtime.InteropServices; |
7 | using WixToolset.Mba.Core; | 8 | using WixToolset.Mba.Core; |
8 | using Xunit; | 9 | using Xunit; |
@@ -17,7 +18,7 @@ namespace WixToolsetTest.Mba.Core | |||
17 | action = LaunchAction.Install, | 18 | action = LaunchAction.Install, |
18 | cbSize = Marshal.SizeOf(typeof(TestCommand)), | 19 | cbSize = Marshal.SizeOf(typeof(TestCommand)), |
19 | display = Display.Full, | 20 | display = Display.Full, |
20 | wzCommandLine = "this \"is a\" test", | 21 | wzCommandLine = "this \"is a\" test VariableA=AVariable =EmptyName EmptyValue=", |
21 | }; | 22 | }; |
22 | var pCommand = Marshal.AllocHGlobal(command.cbSize); | 23 | var pCommand = Marshal.AllocHGlobal(command.cbSize); |
23 | try | 24 | try |
@@ -42,7 +43,15 @@ namespace WixToolsetTest.Mba.Core | |||
42 | Assert.Equal(baFactory.BA, createResults.pBA); | 43 | Assert.Equal(baFactory.BA, createResults.pBA); |
43 | Assert.Equal(baFactory.BA.Command.Action, command.action); | 44 | Assert.Equal(baFactory.BA.Command.Action, command.action); |
44 | Assert.Equal(baFactory.BA.Command.Display, command.display); | 45 | Assert.Equal(baFactory.BA.Command.Display, command.display); |
45 | Assert.Equal(baFactory.BA.Command.CommandLineArgs, new string[] { "this", "is a", "test" }); | 46 | |
47 | var mbaCommand = baFactory.BA.Command.ParseCommandLine(); | ||
48 | Assert.Equal(mbaCommand.UnknownCommandLineArgs, new string[] { "this", "is a", "test" }); | ||
49 | Assert.Equal(mbaCommand.Variables, new KeyValuePair<string, string>[] | ||
50 | { | ||
51 | new KeyValuePair<string, string>("VariableA", "AVariable"), | ||
52 | new KeyValuePair<string, string>("", "EmptyName"), | ||
53 | new KeyValuePair<string, string>("EmptyValue", ""), | ||
54 | }); | ||
46 | } | 55 | } |
47 | finally | 56 | finally |
48 | { | 57 | { |