diff options
author | Rob Mensching <rob@firegiant.com> | 2022-05-09 22:21:16 -0700 |
---|---|---|
committer | Rob Mensching <rob@firegiant.com> | 2022-05-10 13:03:03 -0700 |
commit | 02e682881979cd87592ee1e8e39b7744b575829c (patch) | |
tree | ef0db025ca499781cf5add96a49ffd3934c0b34e | |
parent | 905a6b0c4a214a373cb437ca28ea5610b3ad7654 (diff) | |
download | wix-02e682881979cd87592ee1e8e39b7744b575829c.tar.gz wix-02e682881979cd87592ee1e8e39b7744b575829c.tar.bz2 wix-02e682881979cd87592ee1e8e39b7744b575829c.zip |
Add support for semver in bundles and dependencies
Take advantage of WixVersion/verutil functionality to support wider
range of version numbers were possible in the WiX Toolset
Completes 4666
36 files changed, 568 insertions, 116 deletions
diff --git a/src/api/wix/WixToolset.Data/ErrorMessages.cs b/src/api/wix/WixToolset.Data/ErrorMessages.cs index 186acd29..d3d2932d 100644 --- a/src/api/wix/WixToolset.Data/ErrorMessages.cs +++ b/src/api/wix/WixToolset.Data/ErrorMessages.cs | |||
@@ -1076,7 +1076,7 @@ namespace WixToolset.Data | |||
1076 | 1076 | ||
1077 | public static Message IllegalVersionValue(SourceLineNumber sourceLineNumbers, string elementName, string attributeName, string value) | 1077 | public static Message IllegalVersionValue(SourceLineNumber sourceLineNumbers, string elementName, string attributeName, string value) |
1078 | { | 1078 | { |
1079 | return Message(sourceLineNumbers, Ids.IllegalVersionValue, "The {0}/@{1} attribute's value, '{2}', is not a valid version. Legal version values should look like 'x.x.x.x' where x is an integer from 0 to 65534.", elementName, attributeName, value); | 1079 | return Message(sourceLineNumbers, Ids.IllegalVersionValue, "The {0}/@{1} attribute's value, '{2}', is not a valid version. Specify a four-part version or semantic version, such as '#.#.#.#' or '#.#.#-label.#'.", elementName, attributeName, value); |
1080 | } | 1080 | } |
1081 | 1081 | ||
1082 | public static Message IllegalWarningIdAsError(string warningId) | 1082 | public static Message IllegalWarningIdAsError(string warningId) |
@@ -1279,9 +1279,9 @@ namespace WixToolset.Data | |||
1279 | return Message(sourceLineNumbers, Ids.InvalidMergeLanguage, "The Merge element '{0}' specified an invalid language '{1}'. Verify that localization tokens are being properly resolved to a numeric LCID.", mergeId, mergeLanguage); | 1279 | return Message(sourceLineNumbers, Ids.InvalidMergeLanguage, "The Merge element '{0}' specified an invalid language '{1}'. Verify that localization tokens are being properly resolved to a numeric LCID.", mergeId, mergeLanguage); |
1280 | } | 1280 | } |
1281 | 1281 | ||
1282 | public static Message InvalidModuleOrBundleVersion(SourceLineNumber sourceLineNumbers, string moduleOrBundle, string version) | 1282 | public static Message InvalidFourPartVersion(SourceLineNumber sourceLineNumbers, string elementName, string attributeName, string version) |
1283 | { | 1283 | { |
1284 | return Message(sourceLineNumbers, Ids.InvalidModuleOrBundleVersion, "Invalid {0}/@Version '{1}'. {0} version has a max value of \"65535.65535.65535.65535\" and must be all numeric.", moduleOrBundle, version); | 1284 | return Message(sourceLineNumbers, Ids.InvalidFourPartVersion, "Invalid {0}/@Version '{1}'. {0} version has a max value of \"65535.65535.65535.65535\" and must be all numeric.", elementName, version); |
1285 | } | 1285 | } |
1286 | 1286 | ||
1287 | public static Message InvalidPlatformValue(SourceLineNumber sourceLineNumbers, string value) | 1287 | public static Message InvalidPlatformValue(SourceLineNumber sourceLineNumbers, string value) |
@@ -2678,7 +2678,7 @@ namespace WixToolset.Data | |||
2678 | SplitCabinetNameCollision = 377, | 2678 | SplitCabinetNameCollision = 377, |
2679 | SplitCabinetInsertionFailed = 378, | 2679 | SplitCabinetInsertionFailed = 378, |
2680 | InvalidPreprocessorFunctionAutoVersion = 379, | 2680 | InvalidPreprocessorFunctionAutoVersion = 379, |
2681 | InvalidModuleOrBundleVersion = 380, | 2681 | InvalidFourPartVersion = 380, |
2682 | UnsupportedPlatformForElement = 381, | 2682 | UnsupportedPlatformForElement = 381, |
2683 | MissingMedia = 382, | 2683 | MissingMedia = 382, |
2684 | IllegalYesNoAlwaysValue = 384, | 2684 | IllegalYesNoAlwaysValue = 384, |
diff --git a/src/api/wix/WixToolset.Data/WarningMessages.cs b/src/api/wix/WixToolset.Data/WarningMessages.cs index ecd76392..5a5d1e79 100644 --- a/src/api/wix/WixToolset.Data/WarningMessages.cs +++ b/src/api/wix/WixToolset.Data/WarningMessages.cs | |||
@@ -367,9 +367,9 @@ namespace WixToolset.Data | |||
367 | return Message(sourceLineNumbers, Ids.InvalidHigherInstallerVersionInModule, "Merge module '{0}' has an installer version of {1} which is greater than the product's installer version of {2}. Merging a module with a higher installer version than the product it is being merged into can result in invalid values in the resulting msi. You must set the Package/@InstallerVersion attribute to {1} or greater to merge this merge module into your product.", moduleId, moduleInstallerVersion, productInstallerVersion); | 367 | return Message(sourceLineNumbers, Ids.InvalidHigherInstallerVersionInModule, "Merge module '{0}' has an installer version of {1} which is greater than the product's installer version of {2}. Merging a module with a higher installer version than the product it is being merged into can result in invalid values in the resulting msi. You must set the Package/@InstallerVersion attribute to {1} or greater to merge this merge module into your product.", moduleId, moduleInstallerVersion, productInstallerVersion); |
368 | } | 368 | } |
369 | 369 | ||
370 | public static Message InvalidModuleOrBundleVersion(SourceLineNumber sourceLineNumbers, string moduleOrBundle, string version) | 370 | public static Message InvalidFourPartVersion(SourceLineNumber sourceLineNumbers, string elementName, string version) |
371 | { | 371 | { |
372 | return Message(sourceLineNumbers, Ids.InvalidModuleOrBundleVersion, "Invalid {0}/@Version '{1}'. {0} version has a max value of \"65535.65535.65535.65535\" and must be all numeric.", moduleOrBundle, version); | 372 | return Message(sourceLineNumbers, Ids.InvalidFourPartVersion, "Invalid {0}/@Version '{1}'. {0} version has a max value of \"65535.65535.65535.65535\" and must be all numeric.", elementName, version); |
373 | } | 373 | } |
374 | 374 | ||
375 | public static Message InvalidRemoveFile(SourceLineNumber sourceLineNumbers, string file, string component) | 375 | public static Message InvalidRemoveFile(SourceLineNumber sourceLineNumbers, string file, string component) |
@@ -663,9 +663,9 @@ namespace WixToolset.Data | |||
663 | return Message(sourceLineNumbers, Ids.VariableDeclarationCollision, "The variable '{0}' with value '{1}' was previously declared with value '{2}'.", variableName, variableValue, variableCollidingValue); | 663 | return Message(sourceLineNumbers, Ids.VariableDeclarationCollision, "The variable '{0}' with value '{1}' was previously declared with value '{2}'.", variableName, variableValue, variableCollidingValue); |
664 | } | 664 | } |
665 | 665 | ||
666 | public static Message VersionTruncated(SourceLineNumber sourceLineNumbers, string originalVersion, string package, string truncatedVersion) | 666 | public static Message InvalidMsiProductVersion(SourceLineNumber sourceLineNumbers, string version, string package) |
667 | { | 667 | { |
668 | return Message(sourceLineNumbers, Ids.VersionTruncated, "Product version {0} in package '{1}' is not valid per the MSI SDK and cannot be represented in a bundle. It has been truncated to {2}.", originalVersion, package, truncatedVersion); | 668 | return Message(sourceLineNumbers, Ids.InvalidMsiProductVersion, "Invalid product version '{0}' in MSI package '{1}'. Product version should have a major version less than 256, a minor version less than 256, and a build version less than 65536. The bundle may incorrectly detect upgrades of this package.", version, package); |
669 | } | 669 | } |
670 | 670 | ||
671 | public static Message CollidingModularizationTypes(string tableName, string columnName, string foreignTableName, int foreignColumnNumber, string modularizationType, string foreignModularizationType) | 671 | public static Message CollidingModularizationTypes(string tableName, string columnName, string foreignTableName, int foreignColumnNumber, string modularizationType, string foreignModularizationType) |
@@ -764,7 +764,7 @@ namespace WixToolset.Data | |||
764 | DeprecatedPackageCompressedAttribute = 1087, | 764 | DeprecatedPackageCompressedAttribute = 1087, |
765 | DeprecatedQuestionMarksGuid = 1090, | 765 | DeprecatedQuestionMarksGuid = 1090, |
766 | PackageCodeSet = 1091, | 766 | PackageCodeSet = 1091, |
767 | InvalidModuleOrBundleVersion = 1093, | 767 | InvalidFourPartVersion = 1093, |
768 | InvalidRemoveFile = 1095, | 768 | InvalidRemoveFile = 1095, |
769 | PreprocessorWarning = 1096, | 769 | PreprocessorWarning = 1096, |
770 | UpdateOfNonKeyPathFile = 1097, | 770 | UpdateOfNonKeyPathFile = 1097, |
@@ -816,7 +816,7 @@ namespace WixToolset.Data | |||
816 | AllChangesIncludedInPatch = 1145, | 816 | AllChangesIncludedInPatch = 1145, |
817 | RelatedAttributeConditionallyIgnored = 1146, | 817 | RelatedAttributeConditionallyIgnored = 1146, |
818 | BackslashTerminateInlineDirectorySyntax = 1147, | 818 | BackslashTerminateInlineDirectorySyntax = 1147, |
819 | VersionTruncated = 1148, | 819 | InvalidMsiProductVersion = 1148, |
820 | ServiceConfigFamilyNotSupported = 1149, | 820 | ServiceConfigFamilyNotSupported = 1149, |
821 | SymbolNotTranslatedToOutput = 1150, | 821 | SymbolNotTranslatedToOutput = 1150, |
822 | MsiTransactionLimitations = 1151, | 822 | MsiTransactionLimitations = 1151, |
diff --git a/src/api/wix/WixToolset.Extensibility/Services/IBackendHelper.cs b/src/api/wix/WixToolset.Extensibility/Services/IBackendHelper.cs index 23ad44f5..1c92303e 100644 --- a/src/api/wix/WixToolset.Extensibility/Services/IBackendHelper.cs +++ b/src/api/wix/WixToolset.Extensibility/Services/IBackendHelper.cs | |||
@@ -104,13 +104,27 @@ namespace WixToolset.Extensibility.Services | |||
104 | bool IsValidBinderVariable(string variable); | 104 | bool IsValidBinderVariable(string variable); |
105 | 105 | ||
106 | /// <summary> | 106 | /// <summary> |
107 | /// Verifies the given string is a valid 4-part version module or bundle version. | 107 | /// Verifies the given string is a valid 4-part version. |
108 | /// </summary> | 108 | /// </summary> |
109 | /// <param name="version">The version to verify.</param> | 109 | /// <param name="version">The version to verify.</param> |
110 | /// <returns>True if version is a valid module or bundle version.</returns> | 110 | /// <returns>True if version is a valid 4-part version.</returns> |
111 | bool IsValidFourPartVersion(string version); | 111 | bool IsValidFourPartVersion(string version); |
112 | 112 | ||
113 | /// <summary> | 113 | /// <summary> |
114 | /// Verifies the given string is a valid MSI product version. | ||
115 | /// </summary> | ||
116 | /// <param name="version">The MSI product version to verify.</param> | ||
117 | /// <returns>True if version is a valid MSI product version</returns> | ||
118 | bool IsValidMsiProductVersion(string version); | ||
119 | |||
120 | /// <summary> | ||
121 | /// Verifies the given string is a valid WiX version. | ||
122 | /// </summary> | ||
123 | /// <param name="version">The version to verify.</param> | ||
124 | /// <returns>True if version is a valid WiX version.</returns> | ||
125 | bool IsValidWixVersion(string version); | ||
126 | |||
127 | /// <summary> | ||
114 | /// Determines if value is a valid identifier. | 128 | /// Determines if value is a valid identifier. |
115 | /// </summary> | 129 | /// </summary> |
116 | /// <param name="id">Identifier to validate.</param> | 130 | /// <param name="id">Identifier to validate.</param> |
diff --git a/src/ext/Dependency/Dependency.wixext.v3.ncrunchsolution b/src/ext/Dependency/Dependency.wixext.v3.ncrunchsolution new file mode 100644 index 00000000..10420ac9 --- /dev/null +++ b/src/ext/Dependency/Dependency.wixext.v3.ncrunchsolution | |||
@@ -0,0 +1,6 @@ | |||
1 | <SolutionConfiguration> | ||
2 | <Settings> | ||
3 | <AllowParallelTestExecution>True</AllowParallelTestExecution> | ||
4 | <SolutionConfigured>True</SolutionConfigured> | ||
5 | </Settings> | ||
6 | </SolutionConfiguration> \ No newline at end of file | ||
diff --git a/src/ext/Dependency/test/WixToolsetTest.Dependency/DependencyExtensionFixture.cs b/src/ext/Dependency/test/WixToolsetTest.Dependency/DependencyExtensionFixture.cs index bce128e8..9e837cff 100644 --- a/src/ext/Dependency/test/WixToolsetTest.Dependency/DependencyExtensionFixture.cs +++ b/src/ext/Dependency/test/WixToolsetTest.Dependency/DependencyExtensionFixture.cs | |||
@@ -17,13 +17,14 @@ namespace WixToolsetTest.Dependency | |||
17 | var folder = TestData.Get(@"TestData\UsingProvides"); | 17 | var folder = TestData.Get(@"TestData\UsingProvides"); |
18 | var build = new Builder(folder, typeof(DependencyExtensionFactory), new[] { folder }); | 18 | var build = new Builder(folder, typeof(DependencyExtensionFactory), new[] { folder }); |
19 | 19 | ||
20 | var results = build.BuildAndQuery(Build, "CustomAction", "Wix4DependencyProvider") | 20 | var results = build.BuildAndQuery(Build, "CustomAction", "Wix4DependencyProvider", "Wix4Dependency") |
21 | .Select(r => Regex.Replace(r, "{[^}]*}", "{*}")) | 21 | .Select(r => Regex.Replace(r, "{[^}]*}", "{*}")) |
22 | .ToArray(); | 22 | .ToArray(); |
23 | WixAssert.CompareLineByLine(new[] | 23 | WixAssert.CompareLineByLine(new[] |
24 | { | 24 | { |
25 | "CustomAction:Wix4DependencyCheck_X86\t1\tDependencyCA_X86\tWixDependencyCheck\t", | 25 | "CustomAction:Wix4DependencyCheck_X86\t1\tDependencyCA_X86\tWixDependencyCheck\t", |
26 | "CustomAction:Wix4DependencyRequire_X86\t1\tDependencyCA_X86\tWixDependencyRequire\t", | 26 | "CustomAction:Wix4DependencyRequire_X86\t1\tDependencyCA_X86\tWixDependencyRequire\t", |
27 | "Wix4Dependency:depL8BNflcqZaN5CQEWh2U3SBHFDdg\tUsingRequires\t1.0.0-beta.9\t\t0", | ||
27 | "Wix4DependencyProvider:dep74OfIcniaqxA7EprRGBw4Oyy3r8\tfilF5_pLhBuF5b4N9XEo52g_hUM5Lo\tUsingProvides\t\t\t", | 28 | "Wix4DependencyProvider:dep74OfIcniaqxA7EprRGBw4Oyy3r8\tfilF5_pLhBuF5b4N9XEo52g_hUM5Lo\tUsingProvides\t\t\t", |
28 | "Wix4DependencyProvider:depTpv28q7slcxvXPWmU4Z0GfbiI.4\tfilF5_pLhBuF5b4N9XEo52g_hUM5Lo\t{*}\t\t\t", | 29 | "Wix4DependencyProvider:depTpv28q7slcxvXPWmU4Z0GfbiI.4\tfilF5_pLhBuF5b4N9XEo52g_hUM5Lo\t{*}\t\t\t", |
29 | }, results); | 30 | }, results); |
diff --git a/src/ext/Dependency/test/WixToolsetTest.Dependency/TestData/UsingProvides/Package.wxs b/src/ext/Dependency/test/WixToolsetTest.Dependency/TestData/UsingProvides/Package.wxs index 65984395..990d984e 100644 --- a/src/ext/Dependency/test/WixToolsetTest.Dependency/TestData/UsingProvides/Package.wxs +++ b/src/ext/Dependency/test/WixToolsetTest.Dependency/TestData/UsingProvides/Package.wxs | |||
@@ -12,7 +12,7 @@ | |||
12 | <File Name="example.txt" Source="Package.wxs" /> | 12 | <File Name="example.txt" Source="Package.wxs" /> |
13 | <Provides Key="UsingProvides" dep:Check="yes" /> | 13 | <Provides Key="UsingProvides" dep:Check="yes" /> |
14 | <Provides> | 14 | <Provides> |
15 | <Requires ProviderKey="UsingRequires" Minimum="1.0.0.0" dep:Enforce="yes" /> | 15 | <Requires ProviderKey="UsingRequires" Minimum="1.0.0-beta.9" dep:Enforce="yes" /> |
16 | </Provides> | 16 | </Provides> |
17 | </Component> | 17 | </Component> |
18 | </Feature> | 18 | </Feature> |
diff --git a/src/libs/dutil/WixToolset.DUtil/deputil.cpp b/src/libs/dutil/WixToolset.DUtil/deputil.cpp index 1a480263..4de85199 100644 --- a/src/libs/dutil/WixToolset.DUtil/deputil.cpp +++ b/src/libs/dutil/WixToolset.DUtil/deputil.cpp | |||
@@ -121,9 +121,10 @@ DAPI_(HRESULT) DepCheckDependency( | |||
121 | HRESULT hr = S_OK; | 121 | HRESULT hr = S_OK; |
122 | LPWSTR sczKey = NULL; | 122 | LPWSTR sczKey = NULL; |
123 | HKEY hkKey = NULL; | 123 | HKEY hkKey = NULL; |
124 | DWORD64 dw64Version = 0; | 124 | VERUTIL_VERSION* pVersion = NULL; |
125 | DWORD64 dw64MinVersion = 0; | 125 | VERUTIL_VERSION* pMinVersion = NULL; |
126 | DWORD64 dw64MaxVersion = 0; | 126 | VERUTIL_VERSION* pMaxVersion = NULL; |
127 | int nResult = 0; | ||
127 | BOOL fAllowEqual = FALSE; | 128 | BOOL fAllowEqual = FALSE; |
128 | LPWSTR sczName = NULL; | 129 | LPWSTR sczName = NULL; |
129 | 130 | ||
@@ -138,7 +139,7 @@ DAPI_(HRESULT) DepCheckDependency( | |||
138 | DepExitOnFailure(hr, "Failed to open the registry key for dependency \"%ls\".", wzProviderKey); | 139 | DepExitOnFailure(hr, "Failed to open the registry key for dependency \"%ls\".", wzProviderKey); |
139 | 140 | ||
140 | // If there are no registry values, consider the key orphaned and treat it as missing. | 141 | // If there are no registry values, consider the key orphaned and treat it as missing. |
141 | hr = RegReadVersion(hkKey, vcszVersionValue, &dw64Version); | 142 | hr = RegReadWixVersion(hkKey, vcszVersionValue, &pVersion); |
142 | if (E_FILENOTFOUND != hr) | 143 | if (E_FILENOTFOUND != hr) |
143 | { | 144 | { |
144 | DepExitOnFailure(hr, "Failed to read the %ls registry value for dependency \"%ls\".", vcszVersionValue, wzProviderKey); | 145 | DepExitOnFailure(hr, "Failed to read the %ls registry value for dependency \"%ls\".", vcszVersionValue, wzProviderKey); |
@@ -171,11 +172,15 @@ DAPI_(HRESULT) DepCheckDependency( | |||
171 | { | 172 | { |
172 | if (*wzMinVersion) | 173 | if (*wzMinVersion) |
173 | { | 174 | { |
174 | hr = FileVersionFromStringEx(wzMinVersion, 0, &dw64MinVersion); | 175 | hr = VerParseVersion(wzMinVersion, 0, FALSE, &pMinVersion); |
175 | DepExitOnFailure(hr, "Failed to get the 64-bit version number from \"%ls\".", wzMinVersion); | 176 | DepExitOnFailure(hr, "Failed to get the min version number from \"%ls\".", wzMinVersion); |
177 | |||
178 | hr = VerCompareParsedVersions(pVersion, pMinVersion, &nResult); | ||
179 | DepExitOnFailure(hr, "Failed to compare dependency with min version \"%ls\".", wzMinVersion); | ||
176 | 180 | ||
177 | fAllowEqual = iAttributes & RequiresAttributesMinVersionInclusive; | 181 | fAllowEqual = iAttributes & RequiresAttributesMinVersionInclusive; |
178 | if (!(fAllowEqual && dw64MinVersion <= dw64Version || dw64MinVersion < dw64Version)) | 182 | // !(fAllowEqual && pMinVersion <= pVersion || pMinVersion < pVersion)) |
183 | if (!(fAllowEqual && 0 <= nResult || 0 < nResult)) | ||
179 | { | 184 | { |
180 | hr = DictKeyExists(sdDependencies, wzProviderKey); | 185 | hr = DictKeyExists(sdDependencies, wzProviderKey); |
181 | if (E_NOTFOUND != hr) | 186 | if (E_NOTFOUND != hr) |
@@ -205,11 +210,15 @@ DAPI_(HRESULT) DepCheckDependency( | |||
205 | { | 210 | { |
206 | if (*wzMaxVersion) | 211 | if (*wzMaxVersion) |
207 | { | 212 | { |
208 | hr = FileVersionFromStringEx(wzMaxVersion, 0, &dw64MaxVersion); | 213 | hr = VerParseVersion(wzMaxVersion, 0, FALSE, &pMaxVersion); |
209 | DepExitOnFailure(hr, "Failed to get the 64-bit version number from \"%ls\".", wzMaxVersion); | 214 | DepExitOnFailure(hr, "Failed to get the max version number from \"%ls\".", wzMaxVersion); |
215 | |||
216 | hr = VerCompareParsedVersions(pMaxVersion, pVersion, &nResult); | ||
217 | DepExitOnFailure(hr, "Failed to compare dependency with max version \"%ls\".", wzMaxVersion); | ||
210 | 218 | ||
211 | fAllowEqual = iAttributes & RequiresAttributesMaxVersionInclusive; | 219 | fAllowEqual = iAttributes & RequiresAttributesMaxVersionInclusive; |
212 | if (!(fAllowEqual && dw64Version <= dw64MaxVersion || dw64Version < dw64MaxVersion)) | 220 | // !(fAllowEqual && pVersion <= pMaxVersion || pVersion < pMaxVersion) |
221 | if (!(fAllowEqual && 0 <= nResult || 0 < nResult)) | ||
213 | { | 222 | { |
214 | hr = DictKeyExists(sdDependencies, wzProviderKey); | 223 | hr = DictKeyExists(sdDependencies, wzProviderKey); |
215 | if (E_NOTFOUND != hr) | 224 | if (E_NOTFOUND != hr) |
@@ -235,6 +244,9 @@ DAPI_(HRESULT) DepCheckDependency( | |||
235 | } | 244 | } |
236 | 245 | ||
237 | LExit: | 246 | LExit: |
247 | ReleaseVerutilVersion(pMaxVersion); | ||
248 | ReleaseVerutilVersion(pMinVersion); | ||
249 | ReleaseVerutilVersion(pVersion); | ||
238 | ReleaseStr(sczName); | 250 | ReleaseStr(sczName); |
239 | ReleaseRegKey(hkKey); | 251 | ReleaseRegKey(hkKey); |
240 | ReleaseStr(sczKey); | 252 | ReleaseStr(sczKey); |
diff --git a/src/libs/dutil/WixToolset.DUtil/inc/regutil.h b/src/libs/dutil/WixToolset.DUtil/inc/regutil.h index 3cbb53b0..76d2d7cb 100644 --- a/src/libs/dutil/WixToolset.DUtil/inc/regutil.h +++ b/src/libs/dutil/WixToolset.DUtil/inc/regutil.h | |||
@@ -1,6 +1,7 @@ | |||
1 | #pragma once | 1 | #pragma once |
2 | // 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 | // 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. |
3 | 3 | ||
4 | #include "verutil.h" | ||
4 | 5 | ||
5 | #ifdef __cplusplus | 6 | #ifdef __cplusplus |
6 | extern "C" { | 7 | extern "C" { |
@@ -261,6 +262,16 @@ HRESULT DAPI RegReadVersion( | |||
261 | ); | 262 | ); |
262 | 263 | ||
263 | /******************************************************************** | 264 | /******************************************************************** |
265 | RegReadWixVersion - reads a registry key value as a WiX version. | ||
266 | |||
267 | *********************************************************************/ | ||
268 | HRESULT DAPI RegReadWixVersion( | ||
269 | __in HKEY hk, | ||
270 | __in_z_opt LPCWSTR wzName, | ||
271 | __out VERUTIL_VERSION** ppVersion | ||
272 | ); | ||
273 | |||
274 | /******************************************************************** | ||
264 | RegReadNone - reads a NONE registry key value. | 275 | RegReadNone - reads a NONE registry key value. |
265 | 276 | ||
266 | *********************************************************************/ | 277 | *********************************************************************/ |
diff --git a/src/libs/dutil/WixToolset.DUtil/regutil.cpp b/src/libs/dutil/WixToolset.DUtil/regutil.cpp index 78507ade..64224d42 100644 --- a/src/libs/dutil/WixToolset.DUtil/regutil.cpp +++ b/src/libs/dutil/WixToolset.DUtil/regutil.cpp | |||
@@ -590,6 +590,7 @@ DAPI_(HRESULT) RegReadVersion( | |||
590 | { | 590 | { |
591 | ExitFunction1(hr = E_FILENOTFOUND); | 591 | ExitFunction1(hr = E_FILENOTFOUND); |
592 | } | 592 | } |
593 | |||
593 | if (REG_SZ == dwType || REG_EXPAND_SZ == dwType) | 594 | if (REG_SZ == dwType || REG_EXPAND_SZ == dwType) |
594 | { | 595 | { |
595 | hr = RegReadString(hk, wzName, &sczVersion); | 596 | hr = RegReadString(hk, wzName, &sczVersion); |
@@ -614,6 +615,58 @@ LExit: | |||
614 | return hr; | 615 | return hr; |
615 | } | 616 | } |
616 | 617 | ||
618 | |||
619 | DAPI_(HRESULT) RegReadWixVersion( | ||
620 | __in HKEY hk, | ||
621 | __in_z_opt LPCWSTR wzName, | ||
622 | __out VERUTIL_VERSION** ppVersion | ||
623 | ) | ||
624 | { | ||
625 | HRESULT hr = S_OK; | ||
626 | DWORD er = ERROR_SUCCESS; | ||
627 | DWORD dwType = 0; | ||
628 | DWORD cb = 0; | ||
629 | DWORD64 dw64Version = 0; | ||
630 | LPWSTR sczVersion = NULL; | ||
631 | VERUTIL_VERSION* pVersion = NULL; | ||
632 | |||
633 | cb = sizeof(DWORD64); | ||
634 | er = vpfnRegQueryValueExW(hk, wzName, NULL, &dwType, reinterpret_cast<LPBYTE>(&dw64Version), &cb); | ||
635 | if (E_FILENOTFOUND == HRESULT_FROM_WIN32(er)) | ||
636 | { | ||
637 | ExitFunction1(hr = E_FILENOTFOUND); | ||
638 | } | ||
639 | |||
640 | if (REG_SZ == dwType || REG_EXPAND_SZ == dwType) | ||
641 | { | ||
642 | hr = RegReadString(hk, wzName, &sczVersion); | ||
643 | RegExitOnFailure(hr, "Failed to read registry version as string."); | ||
644 | |||
645 | hr = VerParseVersion(sczVersion, 0, FALSE, &pVersion); | ||
646 | RegExitOnFailure(hr, "Failed to convert registry string to version."); | ||
647 | } | ||
648 | else if (REG_QWORD == dwType) | ||
649 | { | ||
650 | hr = VerVersionFromQword(dw64Version, &pVersion); | ||
651 | RegExitOnFailure(hr, "Failed to convert registry string to version."); | ||
652 | } | ||
653 | else // unexpected data type | ||
654 | { | ||
655 | hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATATYPE); | ||
656 | RegExitOnRootFailure(hr, "Error reading version registry value due to unexpected data type: %u", dwType); | ||
657 | } | ||
658 | |||
659 | *ppVersion = pVersion; | ||
660 | pVersion = NULL; | ||
661 | |||
662 | LExit: | ||
663 | ReleaseVerutilVersion(pVersion); | ||
664 | ReleaseStr(sczVersion); | ||
665 | |||
666 | return hr; | ||
667 | } | ||
668 | |||
669 | |||
617 | DAPI_(HRESULT) RegReadNone( | 670 | DAPI_(HRESULT) RegReadNone( |
618 | __in HKEY hk, | 671 | __in HKEY hk, |
619 | __in_z_opt LPCWSTR wzName | 672 | __in_z_opt LPCWSTR wzName |
diff --git a/src/test/burn/TestData/DependencyTests/PackageB/ProductComponents.wxs b/src/test/burn/TestData/DependencyTests/PackageB/ProductComponents.wxs index b59e53e1..65ae1e44 100644 --- a/src/test/burn/TestData/DependencyTests/PackageB/ProductComponents.wxs +++ b/src/test/burn/TestData/DependencyTests/PackageB/ProductComponents.wxs | |||
@@ -11,7 +11,7 @@ | |||
11 | <Component Id="FileComponent2" Guid="A1866388-65B4-4215-A8FB-9A7AADBE4E8E" Directory="INSTALLFOLDER"> | 11 | <Component Id="FileComponent2" Guid="A1866388-65B4-4215-A8FB-9A7AADBE4E8E" Directory="INSTALLFOLDER"> |
12 | <File Source="$(sys.SOURCEFILEPATH)" /> | 12 | <File Source="$(sys.SOURCEFILEPATH)" /> |
13 | <Provides> | 13 | <Provides> |
14 | <Requires ProviderKey="WiX.$(var.TestGroupName).A,v1.0" Minimum="1.0.0.0" IncludeMinimum="yes" dep:Enforce="yes" /> | 14 | <Requires ProviderKey="WiX.$(var.TestGroupName).A,v1.0" Minimum="1.0.0-alpha.420" IncludeMinimum="yes" dep:Enforce="yes" /> |
15 | </Provides> | 15 | </Provides> |
16 | </Component> | 16 | </Component> |
17 | </Fragment> | 17 | </Fragment> |
diff --git a/src/test/burn/WixToolsetTest.BurnE2E/DependencyTests.cs b/src/test/burn/WixToolsetTest.BurnE2E/DependencyTests.cs index 3437bf00..f4bc6ba9 100644 --- a/src/test/burn/WixToolsetTest.BurnE2E/DependencyTests.cs +++ b/src/test/burn/WixToolsetTest.BurnE2E/DependencyTests.cs | |||
@@ -1086,5 +1086,24 @@ namespace WixToolsetTest.BurnE2E | |||
1086 | packageA.UninstallProduct(); | 1086 | packageA.UninstallProduct(); |
1087 | packageA.VerifyInstalled(false); | 1087 | packageA.VerifyInstalled(false); |
1088 | } | 1088 | } |
1089 | |||
1090 | [Fact] | ||
1091 | public void CannotInstallWhenDependencyUnsatisfied() | ||
1092 | { | ||
1093 | var packageA = this.CreatePackageInstaller("PackageAv1"); | ||
1094 | var packageB = this.CreatePackageInstaller("PackageB"); | ||
1095 | var bundleB = this.CreateBundleInstaller("BundleB"); | ||
1096 | var testBAController = this.CreateTestBAController(); | ||
1097 | |||
1098 | packageA.VerifyInstalled(false); | ||
1099 | packageB.VerifyInstalled(false); | ||
1100 | |||
1101 | // Prevent install of PackageA to cause PackageB's enforced dependency | ||
1102 | // to fail the install. | ||
1103 | testBAController.SetPackageRequestedState("PackageA", RequestState.None); | ||
1104 | |||
1105 | var bundleBInstallLogFilePath = bundleB.Install((int)MSIExec.MSIExecReturnCode.ERROR_INSTALL_FAILURE); | ||
1106 | Assert.True(LogVerifier.MessageInLogFileRegex(bundleBInstallLogFilePath, @"Applied execute package: PackageB, result: 0x80070643, restart: None")); | ||
1107 | } | ||
1089 | } | 1108 | } |
1090 | } | 1109 | } |
diff --git a/src/wix/WixToolset.Core.Burn/Bundles/CreateBundleExeCommand.cs b/src/wix/WixToolset.Core.Burn/Bundles/CreateBundleExeCommand.cs index 8211bf83..e63bf65c 100644 --- a/src/wix/WixToolset.Core.Burn/Bundles/CreateBundleExeCommand.cs +++ b/src/wix/WixToolset.Core.Burn/Bundles/CreateBundleExeCommand.cs | |||
@@ -71,11 +71,11 @@ namespace WixToolset.Core.Burn.Bundles | |||
71 | FileSystem.CopyFile(stubFile, bundleTempPath, allowHardlink: false); | 71 | FileSystem.CopyFile(stubFile, bundleTempPath, allowHardlink: false); |
72 | File.SetAttributes(bundleTempPath, FileAttributes.Normal); | 72 | File.SetAttributes(bundleTempPath, FileAttributes.Normal); |
73 | 73 | ||
74 | var windowsAssemblyVersion = GetWindowsAssemblyVersion(this.BundleSymbol); | 74 | var fourPartVersion = this.GetFourPartVersion(this.BundleSymbol); |
75 | 75 | ||
76 | var applicationManifestData = GenerateApplicationManifest(this.BundleSymbol, this.BootstrapperApplicationDllSymbol, this.OutputPath, windowsAssemblyVersion); | 76 | var applicationManifestData = GenerateApplicationManifest(this.BundleSymbol, this.BootstrapperApplicationDllSymbol, this.OutputPath, fourPartVersion); |
77 | 77 | ||
78 | UpdateBurnResources(bundleTempPath, this.OutputPath, this.BundleSymbol, windowsAssemblyVersion, applicationManifestData); | 78 | this.UpdateBurnResources(bundleTempPath, this.OutputPath, this.BundleSymbol, fourPartVersion, applicationManifestData); |
79 | 79 | ||
80 | // Update the .wixburn section to point to at the UX and attached container(s) then attach the containers | 80 | // Update the .wixburn section to point to at the UX and attached container(s) then attach the containers |
81 | // if they should be attached. | 81 | // if they should be attached. |
@@ -242,24 +242,37 @@ namespace WixToolset.Core.Burn.Bundles | |||
242 | } | 242 | } |
243 | } | 243 | } |
244 | 244 | ||
245 | private static Version GetWindowsAssemblyVersion(WixBundleSymbol bundleSymbol) | 245 | private Version GetFourPartVersion(WixBundleSymbol bundleSymbol) |
246 | { | 246 | { |
247 | // Ensure the bundle info provides a full four part version. | 247 | // Ensure the bundle info provides a full four-part version. |
248 | var fourPartVersion = new Version(bundleSymbol.Version); | 248 | |
249 | var major = (fourPartVersion.Major < 0) ? 0 : fourPartVersion.Major; | 249 | if (!WixVersion.TryParse(bundleSymbol.Version, out var wixVersion)) |
250 | var minor = (fourPartVersion.Minor < 0) ? 0 : fourPartVersion.Minor; | 250 | { |
251 | var build = (fourPartVersion.Build < 0) ? 0 : fourPartVersion.Build; | 251 | // Display an error message indicating that we will require a four-part version number |
252 | var revision = (fourPartVersion.Revision < 0) ? 0 : fourPartVersion.Revision; | 252 | // not just a WixVersion. |
253 | this.Messaging.Write(ErrorMessages.IllegalVersionValue(bundleSymbol.SourceLineNumbers, "Bundle", "Version", bundleSymbol.Version)); | ||
254 | return new Version(0, 0); | ||
255 | } | ||
256 | |||
257 | var major = wixVersion.Major ?? 0; | ||
258 | var minor = wixVersion.Minor ?? 0; | ||
259 | var build = wixVersion.Patch ?? 0; | ||
260 | var revision = wixVersion.Revision ?? 0; | ||
253 | 261 | ||
254 | if (UInt16.MaxValue < major || UInt16.MaxValue < minor || UInt16.MaxValue < build || UInt16.MaxValue < revision) | 262 | if (UInt16.MaxValue < major || UInt16.MaxValue < minor || UInt16.MaxValue < build || UInt16.MaxValue < revision) |
255 | { | 263 | { |
256 | throw new WixException(ErrorMessages.InvalidModuleOrBundleVersion(bundleSymbol.SourceLineNumbers, "Bundle", bundleSymbol.Version)); | 264 | major = Math.Max(major, UInt16.MaxValue); |
265 | minor = Math.Max(minor, UInt16.MaxValue); | ||
266 | build = Math.Max(build, UInt16.MaxValue); | ||
267 | revision = Math.Max(revision, UInt16.MaxValue); | ||
268 | |||
269 | this.Messaging.Write(BurnBackendWarnings.CannotParseBundleVersionAsFourPartVersion(bundleSymbol.SourceLineNumbers, bundleSymbol.Version)); | ||
257 | } | 270 | } |
258 | 271 | ||
259 | return new Version(major, minor, build, revision); | 272 | return new Version((int)major, (int)minor, (int)build, (int)revision); |
260 | } | 273 | } |
261 | 274 | ||
262 | private void UpdateBurnResources(string bundleTempPath, string outputPath, WixBundleSymbol bundleInfo, Version windowsAssemblyVersion, byte[] applicationManifestData) | 275 | private void UpdateBurnResources(string bundleTempPath, string outputPath, WixBundleSymbol bundleInfo, Version fourPartVersion, byte[] applicationManifestData) |
263 | { | 276 | { |
264 | const int burnLocale = 1033; | 277 | const int burnLocale = 1033; |
265 | var resources = new ResourceCollection(); | 278 | var resources = new ResourceCollection(); |
@@ -268,8 +281,8 @@ namespace WixToolset.Core.Burn.Bundles | |||
268 | version.Load(bundleTempPath); | 281 | version.Load(bundleTempPath); |
269 | resources.Add(version); | 282 | resources.Add(version); |
270 | 283 | ||
271 | version.FileVersion = windowsAssemblyVersion; | 284 | version.FileVersion = fourPartVersion; |
272 | version.ProductVersion = windowsAssemblyVersion; | 285 | version.ProductVersion = fourPartVersion; |
273 | 286 | ||
274 | var strings = version[burnLocale] ?? version.Add(burnLocale); | 287 | var strings = version[burnLocale] ?? version.Add(burnLocale); |
275 | strings["LegalCopyright"] = bundleInfo.Copyright; | 288 | strings["LegalCopyright"] = bundleInfo.Copyright; |
diff --git a/src/wix/WixToolset.Core.Burn/Bundles/ProcessMsiPackageCommand.cs b/src/wix/WixToolset.Core.Burn/Bundles/ProcessMsiPackageCommand.cs index d640e85d..87528a48 100644 --- a/src/wix/WixToolset.Core.Burn/Bundles/ProcessMsiPackageCommand.cs +++ b/src/wix/WixToolset.Core.Burn/Bundles/ProcessMsiPackageCommand.cs | |||
@@ -118,30 +118,9 @@ namespace WixToolset.Core.Burn.Bundles | |||
118 | this.ChainPackage.Version = this.MsiPackage.ProductVersion; | 118 | this.ChainPackage.Version = this.MsiPackage.ProductVersion; |
119 | } | 119 | } |
120 | 120 | ||
121 | if (!this.BackendHelper.IsValidFourPartVersion(this.MsiPackage.ProductVersion)) | 121 | if (!this.BackendHelper.IsValidMsiProductVersion(this.MsiPackage.ProductVersion)) |
122 | { | 122 | { |
123 | // not a proper .NET version (e.g., five fields); can we get a valid four-part version number? | 123 | this.Messaging.Write(WarningMessages.InvalidMsiProductVersion(this.PackagePayload.SourceLineNumbers, this.MsiPackage.ProductVersion, this.PackageId)); |
124 | string version = null; | ||
125 | var versionParts = this.MsiPackage.ProductVersion.Split('.'); | ||
126 | var count = versionParts.Length; | ||
127 | if (0 < count) | ||
128 | { | ||
129 | version = versionParts[0]; | ||
130 | for (var i = 1; i < 4 && i < count; ++i) | ||
131 | { | ||
132 | version = String.Concat(version, ".", versionParts[i]); | ||
133 | } | ||
134 | } | ||
135 | |||
136 | if (!String.IsNullOrEmpty(version) && this.BackendHelper.IsValidFourPartVersion(version)) | ||
137 | { | ||
138 | this.Messaging.Write(WarningMessages.VersionTruncated(this.PackagePayload.SourceLineNumbers, this.MsiPackage.ProductVersion, this.PackageId, version)); | ||
139 | this.MsiPackage.ProductVersion = version; | ||
140 | } | ||
141 | else | ||
142 | { | ||
143 | this.Messaging.Write(ErrorMessages.InvalidProductVersion(this.PackagePayload.SourceLineNumbers, this.MsiPackage.ProductVersion, this.PackageId)); | ||
144 | } | ||
145 | } | 124 | } |
146 | 125 | ||
147 | this.SetPerMachineAppropriately(harvestedMsiPackage.AllUsers); | 126 | this.SetPerMachineAppropriately(harvestedMsiPackage.AllUsers); |
diff --git a/src/wix/WixToolset.Core.Burn/BurnBackendWarnings.cs b/src/wix/WixToolset.Core.Burn/BurnBackendWarnings.cs index 0c305331..69cd8fa6 100644 --- a/src/wix/WixToolset.Core.Burn/BurnBackendWarnings.cs +++ b/src/wix/WixToolset.Core.Burn/BurnBackendWarnings.cs | |||
@@ -16,6 +16,11 @@ namespace WixToolset.Core.Burn | |||
16 | return Message(sourceLineNumbers, Ids.AttachedContainerPayloadCollision2, "The location of the payload related to the previous error."); | 16 | return Message(sourceLineNumbers, Ids.AttachedContainerPayloadCollision2, "The location of the payload related to the previous error."); |
17 | } | 17 | } |
18 | 18 | ||
19 | public static Message CannotParseBundleVersionAsFourPartVersion(SourceLineNumber originalLineNumber, string version) | ||
20 | { | ||
21 | return Message(originalLineNumber, Ids.CannotParseBundleVersionAsFourPartVersion, "The Bundle/@Version was not be able to be used as a four-part version. A valid four-part version has a max value of \"65535.65535.65535.65535\" and must be all numeric.", version); | ||
22 | } | ||
23 | |||
19 | public static Message EmptyContainer(SourceLineNumber sourceLineNumbers, string containerId) | 24 | public static Message EmptyContainer(SourceLineNumber sourceLineNumbers, string containerId) |
20 | { | 25 | { |
21 | return Message(sourceLineNumbers, Ids.EmptyContainer, "The Container '{0}' is being ignored because it doesn't have any payloads.", containerId); | 26 | return Message(sourceLineNumbers, Ids.EmptyContainer, "The Container '{0}' is being ignored because it doesn't have any payloads.", containerId); |
@@ -61,6 +66,7 @@ namespace WixToolset.Core.Burn | |||
61 | UnknownBundleRelationAction = 8505, | 66 | UnknownBundleRelationAction = 8505, |
62 | HiddenBundleNotSupported = 8506, | 67 | HiddenBundleNotSupported = 8506, |
63 | UnknownMsiPackagePlatform = 8507, | 68 | UnknownMsiPackagePlatform = 8507, |
69 | CannotParseBundleVersionAsFourPartVersion = 8508, | ||
64 | } // last available is 8999. 9000 is VerboseMessages. | 70 | } // last available is 8999. 9000 is VerboseMessages. |
65 | } | 71 | } |
66 | } | 72 | } |
diff --git a/src/wix/WixToolset.Core.Burn/ExtensibilityServices/BurnBackendHelper.cs b/src/wix/WixToolset.Core.Burn/ExtensibilityServices/BurnBackendHelper.cs index ed662b7f..909c9b60 100644 --- a/src/wix/WixToolset.Core.Burn/ExtensibilityServices/BurnBackendHelper.cs +++ b/src/wix/WixToolset.Core.Burn/ExtensibilityServices/BurnBackendHelper.cs | |||
@@ -104,6 +104,16 @@ namespace WixToolset.Core.Burn.ExtensibilityServices | |||
104 | return this.backendHelper.IsValidIdentifier(id); | 104 | return this.backendHelper.IsValidIdentifier(id); |
105 | } | 105 | } |
106 | 106 | ||
107 | public bool IsValidMsiProductVersion(string version) | ||
108 | { | ||
109 | return this.backendHelper.IsValidMsiProductVersion(version); | ||
110 | } | ||
111 | |||
112 | public bool IsValidWixVersion(string version) | ||
113 | { | ||
114 | return this.backendHelper.IsValidWixVersion(version); | ||
115 | } | ||
116 | |||
107 | public bool IsValidLongFilename(string filename, bool allowWildcards, bool allowRelative) | 117 | public bool IsValidLongFilename(string filename, bool allowWildcards, bool allowRelative) |
108 | { | 118 | { |
109 | return this.backendHelper.IsValidLongFilename(filename, allowWildcards, allowRelative); | 119 | return this.backendHelper.IsValidLongFilename(filename, allowWildcards, allowRelative); |
diff --git a/src/wix/WixToolset.Core.Burn/ExtensibilityServices/PayloadHarvester.cs b/src/wix/WixToolset.Core.Burn/ExtensibilityServices/PayloadHarvester.cs index 9ef91028..3022ba76 100644 --- a/src/wix/WixToolset.Core.Burn/ExtensibilityServices/PayloadHarvester.cs +++ b/src/wix/WixToolset.Core.Burn/ExtensibilityServices/PayloadHarvester.cs | |||
@@ -52,16 +52,27 @@ namespace WixToolset.Core.Burn.ExtensibilityServices | |||
52 | 52 | ||
53 | if (null != versionInfo) | 53 | if (null != versionInfo) |
54 | { | 54 | { |
55 | // Use the fixed version info block for the file since the resource text may not be a dotted quad. | 55 | var version = versionInfo.ProductVersion; |
56 | var version = new Version(versionInfo.ProductMajorPart, versionInfo.ProductMinorPart, versionInfo.ProductBuildPart, versionInfo.ProductPrivatePart); | ||
57 | 56 | ||
58 | if (PayloadHarvester.EmptyVersion != version) | 57 | if (String.IsNullOrEmpty(version)) |
59 | { | 58 | { |
60 | payload.Version = version.ToString(); | 59 | version = versionInfo.FileVersion; |
60 | } | ||
61 | |||
62 | if (String.IsNullOrEmpty(version)) | ||
63 | { | ||
64 | // Fallback to fixed version info block for the file. | ||
65 | var fixedVersion = new Version(versionInfo.ProductMajorPart, versionInfo.ProductMinorPart, versionInfo.ProductBuildPart, versionInfo.ProductPrivatePart); | ||
66 | |||
67 | if (PayloadHarvester.EmptyVersion != fixedVersion) | ||
68 | { | ||
69 | version = fixedVersion.ToString(); | ||
70 | } | ||
61 | } | 71 | } |
62 | 72 | ||
63 | payload.Description = versionInfo.FileDescription; | 73 | payload.Description = versionInfo.FileDescription; |
64 | payload.DisplayName = versionInfo.ProductName; | 74 | payload.DisplayName = versionInfo.ProductName; |
75 | payload.Version = version; | ||
65 | } | 76 | } |
66 | } | 77 | } |
67 | } | 78 | } |
diff --git a/src/wix/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs b/src/wix/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs index 69a954eb..28b95810 100644 --- a/src/wix/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs +++ b/src/wix/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs | |||
@@ -298,6 +298,9 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
298 | command.Execute(); | 298 | command.Execute(); |
299 | } | 299 | } |
300 | 300 | ||
301 | // Now that delayed fields are processed, validate the package/module version. | ||
302 | this.VerifyVersion(packageSymbol, moduleSymbol); | ||
303 | |||
301 | // Process dependency references. | 304 | // Process dependency references. |
302 | if (SectionType.Product == section.Type || SectionType.Module == section.Type) | 305 | if (SectionType.Product == section.Type || SectionType.Module == section.Type) |
303 | { | 306 | { |
@@ -537,6 +540,24 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
537 | return result; | 540 | return result; |
538 | } | 541 | } |
539 | 542 | ||
543 | private void VerifyVersion(WixPackageSymbol packageSymbol, WixModuleSymbol moduleSymbol) | ||
544 | { | ||
545 | if (packageSymbol != null) | ||
546 | { | ||
547 | if (!this.WindowsInstallerBackendHelper.IsValidMsiProductVersion(packageSymbol.Version)) | ||
548 | { | ||
549 | this.Messaging.Write(ErrorMessages.InvalidProductVersion(packageSymbol.SourceLineNumbers, packageSymbol.Version)); | ||
550 | } | ||
551 | } | ||
552 | else if (moduleSymbol != null) | ||
553 | { | ||
554 | if (!this.WindowsInstallerBackendHelper.IsValidFourPartVersion(moduleSymbol.Version)) | ||
555 | { | ||
556 | this.Messaging.Write(WindowsInstallerBackendErrors.InvalidModuleVersion(moduleSymbol.SourceLineNumbers, moduleSymbol.Version)); | ||
557 | } | ||
558 | } | ||
559 | } | ||
560 | |||
540 | private int CalculateCodepage(WixPackageSymbol packageSymbol, WixModuleSymbol moduleSymbol, WixPatchSymbol patchSymbol) | 561 | private int CalculateCodepage(WixPackageSymbol packageSymbol, WixModuleSymbol moduleSymbol, WixPatchSymbol patchSymbol) |
541 | { | 562 | { |
542 | var codepage = packageSymbol?.Codepage ?? moduleSymbol?.Codepage ?? patchSymbol?.Codepage; | 563 | var codepage = packageSymbol?.Codepage ?? moduleSymbol?.Codepage ?? patchSymbol?.Codepage; |
diff --git a/src/wix/WixToolset.Core.WindowsInstaller/Bind/CreateWindowsInstallerDataFromIRCommand.cs b/src/wix/WixToolset.Core.WindowsInstaller/Bind/CreateWindowsInstallerDataFromIRCommand.cs index 5b44e765..e5966920 100644 --- a/src/wix/WixToolset.Core.WindowsInstaller/Bind/CreateWindowsInstallerDataFromIRCommand.cs +++ b/src/wix/WixToolset.Core.WindowsInstaller/Bind/CreateWindowsInstallerDataFromIRCommand.cs | |||
@@ -1033,6 +1033,16 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
1033 | 1033 | ||
1034 | private void AddUpgradeSymbol(UpgradeSymbol symbol) | 1034 | private void AddUpgradeSymbol(UpgradeSymbol symbol) |
1035 | { | 1035 | { |
1036 | if (!String.IsNullOrEmpty(symbol.VersionMin) && !this.BackendHelper.IsValidMsiProductVersion(symbol.VersionMin)) | ||
1037 | { | ||
1038 | this.Messaging.Write(ErrorMessages.InvalidProductVersion(symbol.SourceLineNumbers, symbol.VersionMin)); | ||
1039 | } | ||
1040 | |||
1041 | if (!String.IsNullOrEmpty(symbol.VersionMax) && !this.BackendHelper.IsValidMsiProductVersion(symbol.VersionMax)) | ||
1042 | { | ||
1043 | this.Messaging.Write(ErrorMessages.InvalidProductVersion(symbol.SourceLineNumbers, symbol.VersionMax)); | ||
1044 | } | ||
1045 | |||
1036 | var row = (UpgradeRow)this.CreateRow(symbol, "Upgrade"); | 1046 | var row = (UpgradeRow)this.CreateRow(symbol, "Upgrade"); |
1037 | row.UpgradeCode = symbol.UpgradeCode; | 1047 | row.UpgradeCode = symbol.UpgradeCode; |
1038 | row.VersionMin = symbol.VersionMin; | 1048 | row.VersionMin = symbol.VersionMin; |
diff --git a/src/wix/WixToolset.Core.WindowsInstaller/ExtensibilityServices/WindowsInstallerBackendHelper.cs b/src/wix/WixToolset.Core.WindowsInstaller/ExtensibilityServices/WindowsInstallerBackendHelper.cs index b3b4421a..30e167f5 100644 --- a/src/wix/WixToolset.Core.WindowsInstaller/ExtensibilityServices/WindowsInstallerBackendHelper.cs +++ b/src/wix/WixToolset.Core.WindowsInstaller/ExtensibilityServices/WindowsInstallerBackendHelper.cs | |||
@@ -93,6 +93,16 @@ namespace WixToolset.Core.WindowsInstaller.ExtensibilityServices | |||
93 | return this.backendHelper.IsValidIdentifier(id); | 93 | return this.backendHelper.IsValidIdentifier(id); |
94 | } | 94 | } |
95 | 95 | ||
96 | public bool IsValidMsiProductVersion(string version) | ||
97 | { | ||
98 | return this.backendHelper.IsValidMsiProductVersion(version); | ||
99 | } | ||
100 | |||
101 | public bool IsValidWixVersion(string version) | ||
102 | { | ||
103 | return this.backendHelper.IsValidWixVersion(version); | ||
104 | } | ||
105 | |||
96 | public bool IsValidLongFilename(string filename, bool allowWildcards, bool allowRelative) | 106 | public bool IsValidLongFilename(string filename, bool allowWildcards, bool allowRelative) |
97 | { | 107 | { |
98 | return this.backendHelper.IsValidLongFilename(filename, allowWildcards, allowRelative); | 108 | return this.backendHelper.IsValidLongFilename(filename, allowWildcards, allowRelative); |
diff --git a/src/wix/WixToolset.Core.WindowsInstaller/WindowsInstallerBackendErrors.cs b/src/wix/WixToolset.Core.WindowsInstaller/WindowsInstallerBackendErrors.cs index 2efb06f1..57b7181b 100644 --- a/src/wix/WixToolset.Core.WindowsInstaller/WindowsInstallerBackendErrors.cs +++ b/src/wix/WixToolset.Core.WindowsInstaller/WindowsInstallerBackendErrors.cs | |||
@@ -14,6 +14,11 @@ namespace WixToolset.Core.WindowsInstaller | |||
14 | return Message(sourceLineNumbers, Ids.CannotLoadWixoutAsTransform, "Could not load wixout file as a transform{1}", additionalDetail); | 14 | return Message(sourceLineNumbers, Ids.CannotLoadWixoutAsTransform, "Could not load wixout file as a transform{1}", additionalDetail); |
15 | } | 15 | } |
16 | 16 | ||
17 | public static Message InvalidModuleVersion(SourceLineNumber originalLineNumber, string version) | ||
18 | { | ||
19 | return Message(originalLineNumber, Ids.InvalidModuleVersion, "The Module/@Version was not be able to be used as a four-part version. A valid four-part version has a max value of \"65535.65535.65535.65535\" and must be all numeric.", version); | ||
20 | } | ||
21 | |||
17 | private static Message Message(SourceLineNumber sourceLineNumber, Ids id, string format, params object[] args) | 22 | private static Message Message(SourceLineNumber sourceLineNumber, Ids id, string format, params object[] args) |
18 | { | 23 | { |
19 | return new Message(sourceLineNumber, MessageLevel.Error, (int)id, format, args); | 24 | return new Message(sourceLineNumber, MessageLevel.Error, (int)id, format, args); |
@@ -22,6 +27,7 @@ namespace WixToolset.Core.WindowsInstaller | |||
22 | public enum Ids | 27 | public enum Ids |
23 | { | 28 | { |
24 | CannotLoadWixoutAsTransform = 7500, | 29 | CannotLoadWixoutAsTransform = 7500, |
30 | InvalidModuleVersion = 7501, | ||
25 | } // last available is 7999. 8000 is BurnBackendErrors. | 31 | } // last available is 7999. 8000 is BurnBackendErrors. |
26 | } | 32 | } |
27 | } | 33 | } |
diff --git a/src/wix/WixToolset.Core/Common.cs b/src/wix/WixToolset.Core/Common.cs index 8e341c52..7a7a654c 100644 --- a/src/wix/WixToolset.Core/Common.cs +++ b/src/wix/WixToolset.Core/Common.cs | |||
@@ -132,6 +132,11 @@ namespace WixToolset.Core | |||
132 | return true; | 132 | return true; |
133 | } | 133 | } |
134 | 134 | ||
135 | public static bool IsValidMsiProductVersion(string version) | ||
136 | { | ||
137 | return Version.TryParse(version, out var ver) && ver.Major < 256 && ver.Minor < 256 && ver.Build < 65536; | ||
138 | } | ||
139 | |||
135 | public static bool IsValidLongFilename(string filename, bool allowWildcards, bool allowRelative) | 140 | public static bool IsValidLongFilename(string filename, bool allowWildcards, bool allowRelative) |
136 | { | 141 | { |
137 | if (String.IsNullOrEmpty(filename)) | 142 | if (String.IsNullOrEmpty(filename)) |
diff --git a/src/wix/WixToolset.Core/CompilerCore.cs b/src/wix/WixToolset.Core/CompilerCore.cs index 0fd302e5..8c676f51 100644 --- a/src/wix/WixToolset.Core/CompilerCore.cs +++ b/src/wix/WixToolset.Core/CompilerCore.cs | |||
@@ -221,27 +221,7 @@ namespace WixToolset.Core | |||
221 | /// <returns>True if version is a valid product version</returns> | 221 | /// <returns>True if version is a valid product version</returns> |
222 | public static bool IsValidProductVersion(string version) | 222 | public static bool IsValidProductVersion(string version) |
223 | { | 223 | { |
224 | if (!Common.IsValidBinderVariable(version)) | 224 | return Common.IsValidBinderVariable(version) || Common.IsValidMsiProductVersion(version); |
225 | { | ||
226 | Version ver = new Version(version); | ||
227 | |||
228 | if (255 < ver.Major || 255 < ver.Minor || 65535 < ver.Build) | ||
229 | { | ||
230 | return false; | ||
231 | } | ||
232 | } | ||
233 | |||
234 | return true; | ||
235 | } | ||
236 | |||
237 | /// <summary> | ||
238 | /// Verifies the given string is a valid module or bundle version. | ||
239 | /// </summary> | ||
240 | /// <param name="version">The version to verify.</param> | ||
241 | /// <returns>True if version is a valid module or bundle version.</returns> | ||
242 | public static bool IsValidModuleOrBundleVersion(string version) | ||
243 | { | ||
244 | return Common.IsValidFourPartVersion(version); | ||
245 | } | 225 | } |
246 | 226 | ||
247 | /// <summary> | 227 | /// <summary> |
diff --git a/src/wix/WixToolset.Core/Compiler_Bundle.cs b/src/wix/WixToolset.Core/Compiler_Bundle.cs index 3039a205..36194882 100644 --- a/src/wix/WixToolset.Core/Compiler_Bundle.cs +++ b/src/wix/WixToolset.Core/Compiler_Bundle.cs | |||
@@ -246,10 +246,6 @@ namespace WixToolset.Core | |||
246 | { | 246 | { |
247 | this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Version")); | 247 | this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Version")); |
248 | } | 248 | } |
249 | else if (!CompilerCore.IsValidModuleOrBundleVersion(version)) | ||
250 | { | ||
251 | this.Core.Write(WarningMessages.InvalidModuleOrBundleVersion(sourceLineNumbers, "Bundle", version)); | ||
252 | } | ||
253 | 249 | ||
254 | if (String.IsNullOrEmpty(upgradeCode)) | 250 | if (String.IsNullOrEmpty(upgradeCode)) |
255 | { | 251 | { |
diff --git a/src/wix/WixToolset.Core/Compiler_Module.cs b/src/wix/WixToolset.Core/Compiler_Module.cs index 7b708981..7e3a2a0e 100644 --- a/src/wix/WixToolset.Core/Compiler_Module.cs +++ b/src/wix/WixToolset.Core/Compiler_Module.cs | |||
@@ -96,10 +96,6 @@ namespace WixToolset.Core | |||
96 | { | 96 | { |
97 | this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Version")); | 97 | this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Version")); |
98 | } | 98 | } |
99 | else if (!CompilerCore.IsValidModuleOrBundleVersion(version)) | ||
100 | { | ||
101 | this.Core.Write(WarningMessages.InvalidModuleOrBundleVersion(sourceLineNumbers, "Module", version)); | ||
102 | } | ||
103 | 99 | ||
104 | try | 100 | try |
105 | { | 101 | { |
diff --git a/src/wix/WixToolset.Core/Compiler_Package.cs b/src/wix/WixToolset.Core/Compiler_Package.cs index d969decb..6ef3f241 100644 --- a/src/wix/WixToolset.Core/Compiler_Package.cs +++ b/src/wix/WixToolset.Core/Compiler_Package.cs | |||
@@ -105,12 +105,8 @@ namespace WixToolset.Core | |||
105 | case "UpgradeCode": | 105 | case "UpgradeCode": |
106 | upgradeCode = this.Core.GetAttributeGuidValue(sourceLineNumbers, attrib, false); | 106 | upgradeCode = this.Core.GetAttributeGuidValue(sourceLineNumbers, attrib, false); |
107 | break; | 107 | break; |
108 | case "Version": // if the attribute is valid version, use the attribute value as is (so "1.0000.01.01" would *not* get translated to "1.0.1.1"). | 108 | case "Version": |
109 | var verifiedVersion = this.Core.GetAttributeVersionValue(sourceLineNumbers, attrib); | 109 | version = this.Core.GetAttributeVersionValue(sourceLineNumbers, attrib); |
110 | if (!String.IsNullOrEmpty(verifiedVersion)) | ||
111 | { | ||
112 | version = attrib.Value; | ||
113 | } | ||
114 | break; | 110 | break; |
115 | default: | 111 | default: |
116 | this.Core.UnexpectedAttribute(node, attrib); | 112 | this.Core.UnexpectedAttribute(node, attrib); |
@@ -147,10 +143,6 @@ namespace WixToolset.Core | |||
147 | { | 143 | { |
148 | this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Version")); | 144 | this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Version")); |
149 | } | 145 | } |
150 | else if (!CompilerCore.IsValidProductVersion(version)) | ||
151 | { | ||
152 | this.Core.Write(ErrorMessages.InvalidProductVersion(sourceLineNumbers, version)); | ||
153 | } | ||
154 | 146 | ||
155 | if (compressed != YesNoDefaultType.No) | 147 | if (compressed != YesNoDefaultType.No) |
156 | { | 148 | { |
diff --git a/src/wix/WixToolset.Core/ExtensibilityServices/BackendHelper.cs b/src/wix/WixToolset.Core/ExtensibilityServices/BackendHelper.cs index 3348ad0b..f3e526a9 100644 --- a/src/wix/WixToolset.Core/ExtensibilityServices/BackendHelper.cs +++ b/src/wix/WixToolset.Core/ExtensibilityServices/BackendHelper.cs | |||
@@ -95,6 +95,16 @@ namespace WixToolset.Core.ExtensibilityServices | |||
95 | return Common.IsValidFourPartVersion(version); | 95 | return Common.IsValidFourPartVersion(version); |
96 | } | 96 | } |
97 | 97 | ||
98 | public bool IsValidMsiProductVersion(string version) | ||
99 | { | ||
100 | return Common.IsValidMsiProductVersion(version); | ||
101 | } | ||
102 | |||
103 | public bool IsValidWixVersion(string version) | ||
104 | { | ||
105 | return WixVersion.TryParse(version, out _); | ||
106 | } | ||
107 | |||
98 | public bool IsValidIdentifier(string id) | 108 | public bool IsValidIdentifier(string id) |
99 | { | 109 | { |
100 | return Common.IsIdentifier(id); | 110 | return Common.IsIdentifier(id); |
diff --git a/src/wix/WixToolset.Core/ExtensibilityServices/ParseHelper.cs b/src/wix/WixToolset.Core/ExtensibilityServices/ParseHelper.cs index bab1dd34..4c6702b8 100644 --- a/src/wix/WixToolset.Core/ExtensibilityServices/ParseHelper.cs +++ b/src/wix/WixToolset.Core/ExtensibilityServices/ParseHelper.cs | |||
@@ -552,9 +552,10 @@ namespace WixToolset.Core.ExtensibilityServices | |||
552 | 552 | ||
553 | if (!String.IsNullOrEmpty(value)) | 553 | if (!String.IsNullOrEmpty(value)) |
554 | { | 554 | { |
555 | if (Version.TryParse(value, out var version)) | 555 | if (WixVersion.TryParse(value, out var version)) |
556 | { | 556 | { |
557 | return version.ToString(); | 557 | // Return the attribute value sans-prefix, if present. |
558 | return version.Prefix.HasValue ? value.Substring(1) : value; | ||
558 | } | 559 | } |
559 | 560 | ||
560 | // Allow versions to contain binder variables. | 561 | // Allow versions to contain binder variables. |
diff --git a/src/wix/test/WixToolsetTest.Core/ParserHelperFixture.cs b/src/wix/test/WixToolsetTest.Core/ParserHelperFixture.cs new file mode 100644 index 00000000..95433ab3 --- /dev/null +++ b/src/wix/test/WixToolsetTest.Core/ParserHelperFixture.cs | |||
@@ -0,0 +1,99 @@ | |||
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 WixToolsetTest.Core | ||
4 | { | ||
5 | using System; | ||
6 | using System.Xml.Linq; | ||
7 | using WixToolset.Core; | ||
8 | using WixToolset.Data; | ||
9 | using WixToolset.Extensibility.Services; | ||
10 | using Xunit; | ||
11 | |||
12 | public class ParserHelperFixture | ||
13 | { | ||
14 | [Fact] | ||
15 | public void CanParseFourPartAttributeVersion() | ||
16 | { | ||
17 | var helper = GetParserHelper(); | ||
18 | |||
19 | var attribute = CreateAttribute("1.2.3.4"); | ||
20 | var result = helper.GetAttributeVersionValue(null, attribute); | ||
21 | |||
22 | Assert.Equal("1.2.3.4", result); | ||
23 | } | ||
24 | |||
25 | [Fact] | ||
26 | public void CannotParseFivePartAttributeVersion() | ||
27 | { | ||
28 | var helper = GetParserHelper(); | ||
29 | |||
30 | var attribute = CreateAttribute("1.2.3.4.5"); | ||
31 | var exception = Assert.Throws<WixException>(() => { helper.GetAttributeVersionValue(null, attribute); }); | ||
32 | Assert.Equal("The Test/@Value attribute's value, '1.2.3.4.5', is not a valid version. Specify a four-part version or semantic version, such as '#.#.#.#' or '#.#.#-label.#'.", exception.Message); | ||
33 | } | ||
34 | |||
35 | [Fact] | ||
36 | public void CannotParseVersionTooLargeAttributeVersion() | ||
37 | { | ||
38 | var version = "4294967296.2.3.4"; | ||
39 | AssertVersion(version); | ||
40 | } | ||
41 | |||
42 | private static void AssertVersion(string version) | ||
43 | { | ||
44 | var helper = GetParserHelper(); | ||
45 | var attribute = CreateAttribute(version); | ||
46 | var exception = Assert.Throws<WixException>(() => { helper.GetAttributeVersionValue(null, attribute); }); | ||
47 | Assert.Equal($"The Test/@Value attribute's value, '{version}', is not a valid version. Specify a four-part version or semantic version, such as '#.#.#.#' or '#.#.#-label.#'.", exception.Message); | ||
48 | } | ||
49 | |||
50 | [Fact] | ||
51 | public void CanParseSemverAttributeVersion() | ||
52 | { | ||
53 | var helper = GetParserHelper(); | ||
54 | |||
55 | var attribute = CreateAttribute("10.99.444-preview.0"); | ||
56 | var result = helper.GetAttributeVersionValue(null, attribute); | ||
57 | |||
58 | Assert.Equal("10.99.444-preview.0", result); | ||
59 | } | ||
60 | |||
61 | [Fact] | ||
62 | public void CanParseFourPartSemverAttributeVersion() | ||
63 | { | ||
64 | var helper = GetParserHelper(); | ||
65 | |||
66 | var attribute = CreateAttribute("1.2.3.4-meta.123-other.456"); | ||
67 | var result = helper.GetAttributeVersionValue(null, attribute); | ||
68 | |||
69 | Assert.Equal("1.2.3.4-meta.123-other.456", result); | ||
70 | } | ||
71 | |||
72 | [Fact] | ||
73 | public void CanParseVersionWithLeadingV() | ||
74 | { | ||
75 | var helper = GetParserHelper(); | ||
76 | |||
77 | var attribute = CreateAttribute("v1.2.3.4"); | ||
78 | var result = helper.GetAttributeVersionValue(null, attribute); | ||
79 | |||
80 | Assert.Equal("1.2.3.4", result); | ||
81 | } | ||
82 | |||
83 | |||
84 | private static IParseHelper GetParserHelper() | ||
85 | { | ||
86 | var sp = WixToolsetServiceProviderFactory.CreateServiceProvider(); | ||
87 | var helper = sp.GetService<IParseHelper>(); | ||
88 | return helper; | ||
89 | } | ||
90 | |||
91 | private static XAttribute CreateAttribute(string value) | ||
92 | { | ||
93 | var attribute = new XAttribute("Value", value); | ||
94 | _ = new XElement("Test", attribute); | ||
95 | |||
96 | return attribute; | ||
97 | } | ||
98 | } | ||
99 | } | ||
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/BundlePackageFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/BundlePackageFixture.cs index eb5cf211..bf9e330c 100644 --- a/src/wix/test/WixToolsetTest.CoreIntegration/BundlePackageFixture.cs +++ b/src/wix/test/WixToolsetTest.CoreIntegration/BundlePackageFixture.cs | |||
@@ -274,8 +274,8 @@ namespace WixToolsetTest.CoreIntegration | |||
274 | .ToArray(); | 274 | .ToArray(); |
275 | WixAssert.CompareLineByLine(new string[] | 275 | WixAssert.CompareLineByLine(new string[] |
276 | { | 276 | { |
277 | $"<BundlePackage Id='chain.exe' Cache='keep' CacheId='{chainBundleId}v1.0.0.0' InstallSize='34' Size='*' PerMachine='yes' Permanent='yes' Vital='yes' RollbackBoundaryForward='WixDefaultBoundary' RollbackBoundaryBackward='WixDefaultBoundary' LogPathVariable='WixBundleLog_chain.exe' RollbackLogPathVariable='WixBundleRollbackLog_chain.exe' BundleId='{chainBundleId}' Version='1.0.0.0' InstallArguments='' UninstallArguments='' RepairArguments='' SupportsBurnProtocol='yes' Win64='no'>" + | 277 | $"<BundlePackage Id='chain.exe' Cache='keep' CacheId='{chainBundleId}v1.0.0-foo.55' InstallSize='34' Size='*' PerMachine='yes' Permanent='yes' Vital='yes' RollbackBoundaryForward='WixDefaultBoundary' RollbackBoundaryBackward='WixDefaultBoundary' LogPathVariable='WixBundleLog_chain.exe' RollbackLogPathVariable='WixBundleRollbackLog_chain.exe' BundleId='{chainBundleId}' Version='1.0.0-foo.55' InstallArguments='' UninstallArguments='' RepairArguments='' SupportsBurnProtocol='yes' Win64='no'>" + |
278 | "<Provides Key='MyProviderKey,v1.0' Version='1.0.0.0' DisplayName='BurnBundle' Imported='yes' />" + | 278 | "<Provides Key='MyProviderKey,v1.0' Version='1.0.0-foo.55' DisplayName='BurnBundle' Imported='yes' />" + |
279 | "<RelatedBundle Id='{B94478B1-E1F3-4700-9CE8-6AA090854AEC}' Action='Upgrade' />" + | 279 | "<RelatedBundle Id='{B94478B1-E1F3-4700-9CE8-6AA090854AEC}' Action='Upgrade' />" + |
280 | "<PayloadRef Id='chain.exe' />" + | 280 | "<PayloadRef Id='chain.exe' />" + |
281 | "</BundlePackage>", | 281 | "</BundlePackage>", |
@@ -302,7 +302,7 @@ namespace WixToolsetTest.CoreIntegration | |||
302 | .ToArray(); | 302 | .ToArray(); |
303 | WixAssert.CompareLineByLine(new string[] | 303 | WixAssert.CompareLineByLine(new string[] |
304 | { | 304 | { |
305 | "<WixPackageProperties Package='chain.exe' Vital='yes' DisplayName='BurnBundle' Description='BurnBundleDescription' DownloadSize='*' PackageSize='*' InstalledSize='34' PackageType='Bundle' Permanent='yes' LogPathVariable='WixBundleLog_chain.exe' RollbackLogPathVariable='WixBundleRollbackLog_chain.exe' Compressed='no' Version='1.0.0.0' Cache='keep' />", | 305 | "<WixPackageProperties Package='chain.exe' Vital='yes' DisplayName='BurnBundle' Description='BurnBundleDescription' DownloadSize='*' PackageSize='*' InstalledSize='34' PackageType='Bundle' Permanent='yes' LogPathVariable='WixBundleLog_chain.exe' RollbackLogPathVariable='WixBundleRollbackLog_chain.exe' Compressed='no' Version='1.0.0-foo.55' Cache='keep' />", |
306 | }, packageElements); | 306 | }, packageElements); |
307 | } | 307 | } |
308 | } | 308 | } |
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/RemotePayloadFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/RemotePayloadFixture.cs index 7126b0d5..9336a635 100644 --- a/src/wix/test/WixToolsetTest.CoreIntegration/RemotePayloadFixture.cs +++ b/src/wix/test/WixToolsetTest.CoreIntegration/RemotePayloadFixture.cs | |||
@@ -205,7 +205,7 @@ namespace WixToolsetTest.CoreIntegration | |||
205 | 205 | ||
206 | WixAssert.CompareLineByLine(new[] | 206 | WixAssert.CompareLineByLine(new[] |
207 | { | 207 | { |
208 | @"<ExePackagePayload Name='burn.exe' ProductName='Windows Installer XML Toolset' Description='WiX Toolset Bootstrapper' DownloadUrl='https://www.example.com/files/burn.exe' Hash='F6E722518AC3AB7E31C70099368D5770788C179AA23226110DCF07319B1E1964E246A1E8AE72E2CF23E0138AFC281BAFDE45969204405E114EB20C8195DA7E5E' Size='463360' Version='3.14.1703.0' />", | 208 | @"<ExePackagePayload Name='burn.exe' ProductName='Windows Installer XML Toolset' Description='WiX Toolset Bootstrapper' DownloadUrl='https://www.example.com/files/burn.exe' Hash='F6E722518AC3AB7E31C70099368D5770788C179AA23226110DCF07319B1E1964E246A1E8AE72E2CF23E0138AFC281BAFDE45969204405E114EB20C8195DA7E5E' Size='463360' Version='3.14.0.1703' />", |
209 | }, elements); | 209 | }, elements); |
210 | } | 210 | } |
211 | } | 211 | } |
@@ -265,7 +265,7 @@ namespace WixToolsetTest.CoreIntegration | |||
265 | 265 | ||
266 | WixAssert.CompareLineByLine(new[] | 266 | WixAssert.CompareLineByLine(new[] |
267 | { | 267 | { |
268 | @"<ExePackagePayload Name='burn.exe' ProductName='Windows Installer XML Toolset' Description='WiX Toolset Bootstrapper' Hash='F6E722518AC3AB7E31C70099368D5770788C179AA23226110DCF07319B1E1964E246A1E8AE72E2CF23E0138AFC281BAFDE45969204405E114EB20C8195DA7E5E' Size='463360' Version='3.14.1703.0' />", | 268 | @"<ExePackagePayload Name='burn.exe' ProductName='Windows Installer XML Toolset' Description='WiX Toolset Bootstrapper' Hash='F6E722518AC3AB7E31C70099368D5770788C179AA23226110DCF07319B1E1964E246A1E8AE72E2CF23E0138AFC281BAFDE45969204405E114EB20C8195DA7E5E' Size='463360' Version='3.14.0.1703' />", |
269 | @"<Payload Name='signed_cab1.cab' CertificatePublicKey='BBD1B48A37503767C71F455624967D406A5D66C3' CertificateThumbprint='DE13B4CE635E3F63AA2394E66F95C460267BC82F' Hash='D8D3842403710E1F6036A62543224855CADF546853933C2B17BA99D789D4347B36717687C022678A9D3DE749DFC1482DAAB92B997B62BB32A8A6828B9D04C414' Size='1585' />", | 269 | @"<Payload Name='signed_cab1.cab' CertificatePublicKey='BBD1B48A37503767C71F455624967D406A5D66C3' CertificateThumbprint='DE13B4CE635E3F63AA2394E66F95C460267BC82F' Hash='D8D3842403710E1F6036A62543224855CADF546853933C2B17BA99D789D4347B36717687C022678A9D3DE749DFC1482DAAB92B997B62BB32A8A6828B9D04C414' Size='1585' />", |
270 | }, elements); | 270 | }, elements); |
271 | } | 271 | } |
@@ -296,7 +296,7 @@ namespace WixToolsetTest.CoreIntegration | |||
296 | 296 | ||
297 | WixAssert.CompareLineByLine(new[] | 297 | WixAssert.CompareLineByLine(new[] |
298 | { | 298 | { |
299 | @"<ExePackagePayload Name='burn.exe' ProductName='Windows Installer XML Toolset' Description='WiX Toolset Bootstrapper' Hash='F6E722518AC3AB7E31C70099368D5770788C179AA23226110DCF07319B1E1964E246A1E8AE72E2CF23E0138AFC281BAFDE45969204405E114EB20C8195DA7E5E' Size='463360' Version='3.14.1703.0' />", | 299 | @"<ExePackagePayload Name='burn.exe' ProductName='Windows Installer XML Toolset' Description='WiX Toolset Bootstrapper' Hash='F6E722518AC3AB7E31C70099368D5770788C179AA23226110DCF07319B1E1964E246A1E8AE72E2CF23E0138AFC281BAFDE45969204405E114EB20C8195DA7E5E' Size='463360' Version='3.14.0.1703' />", |
300 | @"<Payload Name='signed_cab1.cab' Hash='D8D3842403710E1F6036A62543224855CADF546853933C2B17BA99D789D4347B36717687C022678A9D3DE749DFC1482DAAB92B997B62BB32A8A6828B9D04C414' Size='1585' />", | 300 | @"<Payload Name='signed_cab1.cab' Hash='D8D3842403710E1F6036A62543224855CADF546853933C2B17BA99D789D4347B36717687C022678A9D3DE749DFC1482DAAB92B997B62BB32A8A6828B9D04C414' Size='1585' />", |
301 | }, elements); | 301 | }, elements); |
302 | } | 302 | } |
@@ -331,7 +331,7 @@ namespace WixToolsetTest.CoreIntegration | |||
331 | 331 | ||
332 | WixAssert.CompareLineByLine(new[] | 332 | WixAssert.CompareLineByLine(new[] |
333 | { | 333 | { |
334 | @"<ExePackagePayload Name='burn.exe' ProductName='Windows Installer XML Toolset' Description='WiX Toolset Bootstrapper' DownloadUrl='https://www.example.com/files/burn.exe' Hash='F6E722518AC3AB7E31C70099368D5770788C179AA23226110DCF07319B1E1964E246A1E8AE72E2CF23E0138AFC281BAFDE45969204405E114EB20C8195DA7E5E' Size='463360' Version='3.14.1703.0' />", | 334 | @"<ExePackagePayload Name='burn.exe' ProductName='Windows Installer XML Toolset' Description='WiX Toolset Bootstrapper' DownloadUrl='https://www.example.com/files/burn.exe' Hash='F6E722518AC3AB7E31C70099368D5770788C179AA23226110DCF07319B1E1964E246A1E8AE72E2CF23E0138AFC281BAFDE45969204405E114EB20C8195DA7E5E' Size='463360' Version='3.14.0.1703' />", |
335 | @"<Payload Name='a.dat' DownloadUrl='https://www.example.com/files/RemotePayload/recurse/a.dat' Hash='D13926E5CBE5ED8B46133F9199FAF2FF25B25981C67A31AE2BC3F6C20390FACBFADCD89BD22D3445D95B989C8EACFB1E68DB634BECB5C9624865BA453BCE362A' Size='16' />", | 335 | @"<Payload Name='a.dat' DownloadUrl='https://www.example.com/files/RemotePayload/recurse/a.dat' Hash='D13926E5CBE5ED8B46133F9199FAF2FF25B25981C67A31AE2BC3F6C20390FACBFADCD89BD22D3445D95B989C8EACFB1E68DB634BECB5C9624865BA453BCE362A' Size='16' />", |
336 | @"<Payload Name='b.dat' DownloadUrl='https://www.example.com/files/RemotePayload/recurse/subfolder/b.dat' Hash='5F94707BC29ADFE3B9615E6753388707FD0B8F5FD9EEEC2B17E21E72F1635FF7D7A101E7D14F614E111F263CB9AC4D0940BE1247881A7844F226D6C400293D8E' Size='37' />", | 336 | @"<Payload Name='b.dat' DownloadUrl='https://www.example.com/files/RemotePayload/recurse/subfolder/b.dat' Hash='5F94707BC29ADFE3B9615E6753388707FD0B8F5FD9EEEC2B17E21E72F1635FF7D7A101E7D14F614E111F263CB9AC4D0940BE1247881A7844F226D6C400293D8E' Size='37' />", |
337 | @"<Payload Name='c.dat' DownloadUrl='https://www.example.com/files/RemotePayload/recurse/subfolder/c.dat' Hash='97D6209A5571E05E4F72F9C6BF0987651FA03E63F971F9B53C2B3D798A666D9864F232D4E2D6442E47D9D72B282309B6EEFF4EE017B43B706FA92A0F5EF74734' Size='42' />", | 337 | @"<Payload Name='c.dat' DownloadUrl='https://www.example.com/files/RemotePayload/recurse/subfolder/c.dat' Hash='97D6209A5571E05E4F72F9C6BF0987651FA03E63F971F9B53C2B3D798A666D9864F232D4E2D6442E47D9D72B282309B6EEFF4EE017B43B706FA92A0F5EF74734' Size='42' />", |
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/BundlePackage/RemoteBundlePackage.wxs b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/BundlePackage/RemoteBundlePackage.wxs index 1a2b17f5..8800ea1b 100644 --- a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/BundlePackage/RemoteBundlePackage.wxs +++ b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/BundlePackage/RemoteBundlePackage.wxs | |||
@@ -18,7 +18,7 @@ | |||
18 | ProtocolVersion="1" | 18 | ProtocolVersion="1" |
19 | ProviderKey="MyProviderKey,v1.0" | 19 | ProviderKey="MyProviderKey,v1.0" |
20 | UpgradeCode="{B94478B1-E1F3-4700-9CE8-6AA090854AEC}" | 20 | UpgradeCode="{B94478B1-E1F3-4700-9CE8-6AA090854AEC}" |
21 | Version="1.0.0.0" | 21 | Version="1.0.0-foo.55" |
22 | Win64="no" | 22 | Win64="no" |
23 | /> | 23 | /> |
24 | </BundlePackagePayload> | 24 | </BundlePackagePayload> |
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/Upgrade/UpgradeInvalidMinVersion.wxs b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/Upgrade/UpgradeInvalidMinVersion.wxs new file mode 100644 index 00000000..41c93bec --- /dev/null +++ b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/Upgrade/UpgradeInvalidMinVersion.wxs | |||
@@ -0,0 +1,12 @@ | |||
1 | <?xml version="1.0" encoding="utf-8"?> | ||
2 | <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> | ||
3 | <Fragment> | ||
4 | <ComponentGroup Id="ProductComponents"> | ||
5 | <ComponentGroupRef Id="MinimalComponentGroup"></ComponentGroupRef> | ||
6 | </ComponentGroup> | ||
7 | |||
8 | <Upgrade Id="B05772EA-82B8-4DE0-B7EB-45B5F0CCFE6D"> | ||
9 | <UpgradeVersion Minimum="1.256.0" Property="RELPRODFOUND"></UpgradeVersion> | ||
10 | </Upgrade> | ||
11 | </Fragment> | ||
12 | </Wix> | ||
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/Version/Bundle.wxs b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/Version/Bundle.wxs new file mode 100644 index 00000000..01c56be2 --- /dev/null +++ b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/Version/Bundle.wxs | |||
@@ -0,0 +1,11 @@ | |||
1 | <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> | ||
2 | <Bundle Name="MsiPackage-Bundle" Version="$(Version)" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a"> | ||
3 | <BootstrapperApplication> | ||
4 | <BootstrapperApplicationDll SourceFile="fakeba.dll" /> | ||
5 | </BootstrapperApplication> | ||
6 | |||
7 | <Chain> | ||
8 | <MsiPackage SourceFile="test1.msi" /> | ||
9 | </Chain> | ||
10 | </Bundle> | ||
11 | </Wix> | ||
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/Version/Package.wxs b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/Version/Package.wxs new file mode 100644 index 00000000..1a9e102f --- /dev/null +++ b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/Version/Package.wxs | |||
@@ -0,0 +1,31 @@ | |||
1 | <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> | ||
2 | <Package Version="$(Version)" | ||
3 | Name="MsiPackage" | ||
4 | Manufacturer="Example Corporation" | ||
5 | UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a" | ||
6 | Scope="perUser"> | ||
7 | <MajorUpgrade DowngradeErrorMessage="Downgrade not allowed" /> | ||
8 | <MediaTemplate EmbedCab="true" /> | ||
9 | |||
10 | <Feature Id="ProductFeature" Title="Feature title"> | ||
11 | <ComponentGroupRef Id="ProductComponents" /> | ||
12 | </Feature> | ||
13 | </Package> | ||
14 | |||
15 | <Fragment> | ||
16 | <StandardDirectory Id="DesktopFolder"> | ||
17 | <Directory Id="INSTALLFOLDER" Name="MsiPackage $(Version)v" /> | ||
18 | </StandardDirectory> | ||
19 | </Fragment> | ||
20 | |||
21 | <Fragment> | ||
22 | <ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER"> | ||
23 | <Component> | ||
24 | <File Source="test.txt" /> | ||
25 | </Component> | ||
26 | <Component Id="Shared.dll" Shared="yes"> | ||
27 | <File Name="Shared.dll" Source="test.txt" /> | ||
28 | </Component> | ||
29 | </ComponentGroup> | ||
30 | </Fragment> | ||
31 | </Wix> | ||
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/UpgradeFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/UpgradeFixture.cs new file mode 100644 index 00000000..39ccc683 --- /dev/null +++ b/src/wix/test/WixToolsetTest.CoreIntegration/UpgradeFixture.cs | |||
@@ -0,0 +1,43 @@ | |||
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 WixToolsetTest.CoreIntegration | ||
4 | { | ||
5 | using System.IO; | ||
6 | using System.Linq; | ||
7 | using WixBuildTools.TestSupport; | ||
8 | using WixToolset.Core.TestPackage; | ||
9 | using WixToolset.Data; | ||
10 | using Xunit; | ||
11 | |||
12 | public class UpgradeFixture | ||
13 | { | ||
14 | |||
15 | [Fact] | ||
16 | public void PopulatesInstallExecuteSequenceTable() | ||
17 | { | ||
18 | var folder = TestData.Get(@"TestData"); | ||
19 | |||
20 | using (var fs = new DisposableFileSystem()) | ||
21 | { | ||
22 | var baseFolder = fs.GetFolder(); | ||
23 | var intermediateFolder = Path.Combine(baseFolder, "obj"); | ||
24 | var msiPath = Path.Combine(baseFolder, @"bin\test.msi"); | ||
25 | |||
26 | var result = WixRunner.Execute(new[] | ||
27 | { | ||
28 | "build", | ||
29 | Path.Combine(folder, "Upgrade", "UpgradeInvalidMinVersion.wxs"), | ||
30 | Path.Combine(folder, "ProductWithComponentGroupRef", "MinimalComponentGroup.wxs"), | ||
31 | Path.Combine(folder, "ProductWithComponentGroupRef", "Product.wxs"), | ||
32 | "-bindpath", Path.Combine(folder, "SingleFile", "data"), | ||
33 | "-intermediateFolder", intermediateFolder, | ||
34 | "-o", msiPath | ||
35 | }); | ||
36 | |||
37 | var message = result.Messages.Single(m => m.Level == MessageLevel.Error); | ||
38 | Assert.Equal("Invalid product version '1.256.0'. Product version must have a major version less than 256, a minor version less than 256, and a build version less than 65536.", message.ToString()); | ||
39 | Assert.Equal(242, result.ExitCode); | ||
40 | } | ||
41 | } | ||
42 | } | ||
43 | } | ||
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/VersionFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/VersionFixture.cs new file mode 100644 index 00000000..c3758c7e --- /dev/null +++ b/src/wix/test/WixToolsetTest.CoreIntegration/VersionFixture.cs | |||
@@ -0,0 +1,94 @@ | |||
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 WixToolsetTest.CoreIntegration | ||
4 | { | ||
5 | using System.IO; | ||
6 | using System.Linq; | ||
7 | using System.Xml; | ||
8 | using WixBuildTools.TestSupport; | ||
9 | using WixToolset.Core.TestPackage; | ||
10 | using WixToolset.Data; | ||
11 | using Xunit; | ||
12 | |||
13 | public class VersionFixture | ||
14 | { | ||
15 | [Fact] | ||
16 | public void CannotBuildMsiWithInvalidMajorVersion() | ||
17 | { | ||
18 | var folder = TestData.Get(@"TestData"); | ||
19 | |||
20 | using (var fs = new DisposableFileSystem()) | ||
21 | { | ||
22 | var baseFolder = fs.GetFolder(); | ||
23 | var intermediateFolder = Path.Combine(baseFolder, "obj"); | ||
24 | var msiPath = Path.Combine(baseFolder, @"bin\test1.msi"); | ||
25 | |||
26 | var result = WixRunner.Execute(new[] | ||
27 | { | ||
28 | "build", | ||
29 | Path.Combine(folder, "Version", "Package.wxs"), | ||
30 | "-bindpath", Path.Combine(folder, "SingleFile", "data"), | ||
31 | "-intermediateFolder", intermediateFolder, | ||
32 | "-d", "Version=257.0.0", | ||
33 | "-o", msiPath | ||
34 | }); | ||
35 | |||
36 | var message = result.Messages.Single(m => m.Level == MessageLevel.Error); | ||
37 | Assert.Equal("Invalid product version '257.0.0'. Product version must have a major version less than 256, a minor version less than 256, and a build version less than 65536.", message.ToString()); | ||
38 | Assert.Equal(242, result.ExitCode); | ||
39 | } | ||
40 | } | ||
41 | |||
42 | [Fact] | ||
43 | public void CanBuildBundleWithSemanticVersion() | ||
44 | { | ||
45 | var folder = TestData.Get(@"TestData"); | ||
46 | |||
47 | using (var fs = new DisposableFileSystem()) | ||
48 | { | ||
49 | var baseFolder = fs.GetFolder(); | ||
50 | var intermediateFolder = Path.Combine(baseFolder, "obj"); | ||
51 | var msiPath = Path.Combine(baseFolder, @"bin\test1.msi"); | ||
52 | var msi2Path = Path.Combine(baseFolder, @"bin\test2.msi"); | ||
53 | var bundlePath = Path.Combine(baseFolder, @"bin\bundle.exe"); | ||
54 | |||
55 | var result = WixRunner.Execute(new[] | ||
56 | { | ||
57 | "build", | ||
58 | Path.Combine(folder, "Version", "Package.wxs"), | ||
59 | "-bindpath", Path.Combine(folder, "SingleFile", "data"), | ||
60 | "-intermediateFolder", intermediateFolder, | ||
61 | "-d", "Version=255.255.65535", | ||
62 | "-o", msiPath | ||
63 | }); | ||
64 | |||
65 | result.AssertSuccess(); | ||
66 | |||
67 | var result3 = WixRunner.Execute(new[] | ||
68 | { | ||
69 | "build", | ||
70 | Path.Combine(folder, "Version", "Bundle.wxs"), | ||
71 | "-bindpath", Path.Combine(folder, "SimpleBundle", "data"), | ||
72 | "-bindpath", Path.Combine(baseFolder, "bin"), | ||
73 | "-intermediateFolder", intermediateFolder, | ||
74 | "-d", "Version=2022.3.9-preview.0-build.5+0987654321abcdef1234567890", | ||
75 | "-o", bundlePath | ||
76 | }); | ||
77 | |||
78 | result3.AssertSuccess(); | ||
79 | |||
80 | var propertyTable = Query.QueryDatabase(msiPath, new[] { "Property" }).Select(r => r.Split('\t')).ToDictionary(r => r[0].Substring("Property:".Length), r => r[1]); | ||
81 | Assert.True(propertyTable.TryGetValue("ProductVersion", out var productVersion)); | ||
82 | Assert.Equal("255.255.65535", productVersion); | ||
83 | |||
84 | var extractResult = BundleExtractor.ExtractAllContainers(null, bundlePath, Path.Combine(baseFolder, "ba"), Path.Combine(baseFolder, "attached"), Path.Combine(baseFolder, "extract")); | ||
85 | extractResult.AssertSuccess(); | ||
86 | |||
87 | var bundleVersion = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:Registration/@Version") | ||
88 | .Cast<XmlAttribute>() | ||
89 | .Single(); | ||
90 | Assert.Equal("2022.3.9-preview.0-build.5+0987654321abcdef1234567890", bundleVersion.Value); | ||
91 | } | ||
92 | } | ||
93 | } | ||
94 | } | ||