diff options
Diffstat (limited to 'src')
21 files changed, 323 insertions, 41 deletions
diff --git a/src/wix/WixToolset.Core.Burn/Bind/ProcessBundleSoftwareTagsCommand.cs b/src/wix/WixToolset.Core.Burn/Bind/ProcessBundleSoftwareTagsCommand.cs index 5231e0be..70b98222 100644 --- a/src/wix/WixToolset.Core.Burn/Bind/ProcessBundleSoftwareTagsCommand.cs +++ b/src/wix/WixToolset.Core.Burn/Bind/ProcessBundleSoftwareTagsCommand.cs | |||
| @@ -69,7 +69,7 @@ namespace WixToolset.Core.Burn.Bind | |||
| 69 | { | 69 | { |
| 70 | var payload = payloadSymbolsById[msiPackage.PayloadRef]; | 70 | var payload = payloadSymbolsById[msiPackage.PayloadRef]; |
| 71 | 71 | ||
| 72 | using (var db = new Database(payload.SourceFile.Path, OpenDatabase.ReadOnly)) | 72 | using (var db = Database.OpenAsReadOnly(payload.SourceFile.Path)) |
| 73 | { | 73 | { |
| 74 | if (db.TableExists("SoftwareIdentificationTag")) | 74 | if (db.TableExists("SoftwareIdentificationTag")) |
| 75 | { | 75 | { |
diff --git a/src/wix/WixToolset.Core.Burn/Bundles/ProcessMsiPackageCommand.cs b/src/wix/WixToolset.Core.Burn/Bundles/ProcessMsiPackageCommand.cs index d6cf1cfd..0b78c545 100644 --- a/src/wix/WixToolset.Core.Burn/Bundles/ProcessMsiPackageCommand.cs +++ b/src/wix/WixToolset.Core.Burn/Bundles/ProcessMsiPackageCommand.cs | |||
| @@ -164,7 +164,7 @@ namespace WixToolset.Core.Burn.Bundles | |||
| 164 | 164 | ||
| 165 | this.CheckIfWindowsInstallerFileTooLarge(this.PackagePayload.SourceLineNumbers, sourcePath, "MSI"); | 165 | this.CheckIfWindowsInstallerFileTooLarge(this.PackagePayload.SourceLineNumbers, sourcePath, "MSI"); |
| 166 | 166 | ||
| 167 | using (var db = new Database(sourcePath, OpenDatabase.ReadOnly)) | 167 | using (var db = Database.OpenAsReadOnly(sourcePath)) |
| 168 | { | 168 | { |
| 169 | // Read data out of the msi database... | 169 | // Read data out of the msi database... |
| 170 | using (var sumInfo = new SummaryInformation(db)) | 170 | using (var sumInfo = new SummaryInformation(db)) |
diff --git a/src/wix/WixToolset.Core.Burn/Bundles/ProcessMspPackageCommand.cs b/src/wix/WixToolset.Core.Burn/Bundles/ProcessMspPackageCommand.cs index b889c2ce..8d1e9c39 100644 --- a/src/wix/WixToolset.Core.Burn/Bundles/ProcessMspPackageCommand.cs +++ b/src/wix/WixToolset.Core.Burn/Bundles/ProcessMspPackageCommand.cs | |||
| @@ -98,7 +98,7 @@ namespace WixToolset.Core.Burn.Bundles | |||
| 98 | 98 | ||
| 99 | try | 99 | try |
| 100 | { | 100 | { |
| 101 | using (var db = new Database(sourcePath, OpenDatabase.ReadOnly | OpenDatabase.OpenPatchFile)) | 101 | using (var db = Database.OpenAsReadOnly(sourcePath, asPatch: true)) |
| 102 | { | 102 | { |
| 103 | // Read data out of the msp database... | 103 | // Read data out of the msp database... |
| 104 | using (var sumInfo = new SummaryInformation(db)) | 104 | using (var sumInfo = new SummaryInformation(db)) |
diff --git a/src/wix/WixToolset.Core.Native/LongPathUtil.cs b/src/wix/WixToolset.Core.Native/LongPathUtil.cs new file mode 100644 index 00000000..c24f1736 --- /dev/null +++ b/src/wix/WixToolset.Core.Native/LongPathUtil.cs | |||
| @@ -0,0 +1,78 @@ | |||
| 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.Core.Native | ||
| 4 | { | ||
| 5 | using System.IO; | ||
| 6 | using System.Runtime.InteropServices; | ||
| 7 | using System.Text; | ||
| 8 | |||
| 9 | internal static class PathUtil | ||
| 10 | { | ||
| 11 | private const int MaxPath = 260; | ||
| 12 | private const string LongPathPrefix = @"\\?\"; | ||
| 13 | |||
| 14 | public static bool CreateOrGetShortPath(string path, out string shortPath) | ||
| 15 | { | ||
| 16 | var fileCreated = false; | ||
| 17 | |||
| 18 | // The file must exist so we can get its short path. | ||
| 19 | if (!File.Exists(path)) | ||
| 20 | { | ||
| 21 | using (File.Create(path)) | ||
| 22 | { | ||
| 23 | } | ||
| 24 | |||
| 25 | fileCreated = true; | ||
| 26 | } | ||
| 27 | |||
| 28 | // Use the short path to avoid issues with long paths in the MSI API. | ||
| 29 | shortPath = GetShortPath(path); | ||
| 30 | |||
| 31 | return fileCreated; | ||
| 32 | } | ||
| 33 | |||
| 34 | public static string GetPrefixedLongPath(string path) | ||
| 35 | { | ||
| 36 | if (path.Length > MaxPath && !path.StartsWith(LongPathPrefix)) | ||
| 37 | { | ||
| 38 | path = LongPathPrefix + path; | ||
| 39 | } | ||
| 40 | |||
| 41 | return path; | ||
| 42 | } | ||
| 43 | |||
| 44 | public static string GetShortPath(string longPath) | ||
| 45 | { | ||
| 46 | var path = GetPrefixedLongPath(longPath); | ||
| 47 | |||
| 48 | var buffer = new StringBuilder(MaxPath); // start with MAX_PATH. | ||
| 49 | |||
| 50 | var result = GetShortPathName(path, buffer, (uint)buffer.Capacity); | ||
| 51 | |||
| 52 | // If result > buffer.Capacity, reallocate and call again (even though we're usually using short names to avoid long path) | ||
| 53 | // so the short path result is still going to end up too long for APIs requiring a short path. | ||
| 54 | if (result > buffer.Capacity) | ||
| 55 | { | ||
| 56 | buffer = new StringBuilder((int)result); | ||
| 57 | |||
| 58 | result = GetShortPathName(path, buffer, (uint)buffer.Capacity); | ||
| 59 | } | ||
| 60 | |||
| 61 | // If we succeeded, return the short path without the prefix. | ||
| 62 | if (result > 0) | ||
| 63 | { | ||
| 64 | path = buffer.ToString(); | ||
| 65 | |||
| 66 | if (path.StartsWith(LongPathPrefix)) | ||
| 67 | { | ||
| 68 | path = path.Substring(LongPathPrefix.Length); | ||
| 69 | } | ||
| 70 | } | ||
| 71 | |||
| 72 | return path; | ||
| 73 | } | ||
| 74 | |||
| 75 | [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] | ||
| 76 | private static extern uint GetShortPathName(string lpszLongPath, StringBuilder lpszShortPath, uint cchBuffer); | ||
| 77 | } | ||
| 78 | } | ||
diff --git a/src/wix/WixToolset.Core.Native/Msi/Database.cs b/src/wix/WixToolset.Core.Native/Msi/Database.cs index ff966302..33eb8de6 100644 --- a/src/wix/WixToolset.Core.Native/Msi/Database.cs +++ b/src/wix/WixToolset.Core.Native/Msi/Database.cs | |||
| @@ -18,7 +18,7 @@ namespace WixToolset.Core.Native.Msi | |||
| 18 | /// </summary> | 18 | /// </summary> |
| 19 | /// <param name="path">Path to the database to be opened.</param> | 19 | /// <param name="path">Path to the database to be opened.</param> |
| 20 | /// <param name="type">Persist mode to use when opening the database.</param> | 20 | /// <param name="type">Persist mode to use when opening the database.</param> |
| 21 | public Database(string path, OpenDatabase type) | 21 | private Database(string path, OpenDatabase type) |
| 22 | { | 22 | { |
| 23 | var error = MsiInterop.MsiOpenDatabase(path, (IntPtr)type, out var handle); | 23 | var error = MsiInterop.MsiOpenDatabase(path, (IntPtr)type, out var handle); |
| 24 | if (0 != error) | 24 | if (0 != error) |
| @@ -35,14 +35,89 @@ namespace WixToolset.Core.Native.Msi | |||
| 35 | public static int MsiMaxStreamNameLength => MsiInterop.MsiMaxStreamNameLength; | 35 | public static int MsiMaxStreamNameLength => MsiInterop.MsiMaxStreamNameLength; |
| 36 | 36 | ||
| 37 | /// <summary> | 37 | /// <summary> |
| 38 | /// Creates a new <see cref="Database"/> with the specified path. | ||
| 39 | /// </summary> | ||
| 40 | /// <param name="path">Path of database to be created.</param> | ||
| 41 | /// <param name="asPatch">Indicates whether the database should be opened as a patch file.</param> | ||
| 42 | public static Database Create(string path, bool asPatch = false) | ||
| 43 | { | ||
| 44 | var fileCreated = false; | ||
| 45 | var mode = OpenDatabase.CreateDirect; | ||
| 46 | |||
| 47 | if (asPatch) | ||
| 48 | { | ||
| 49 | mode |= OpenDatabase.OpenPatchFile; | ||
| 50 | } | ||
| 51 | |||
| 52 | try | ||
| 53 | { | ||
| 54 | fileCreated = PathUtil.CreateOrGetShortPath(path, out var shortPath); | ||
| 55 | |||
| 56 | return new Database(shortPath, mode); | ||
| 57 | } | ||
| 58 | catch // cleanup on error if we created the short path file. | ||
| 59 | { | ||
| 60 | if (fileCreated) | ||
| 61 | { | ||
| 62 | File.Delete(path); | ||
| 63 | } | ||
| 64 | |||
| 65 | throw; | ||
| 66 | } | ||
| 67 | } | ||
| 68 | |||
| 69 | /// <summary> | ||
| 70 | /// Opens an existing <see cref="Database"/> with the specified path. | ||
| 71 | /// </summary> | ||
| 72 | /// <param name="path">Path of database to open.</param> | ||
| 73 | /// <param name="transact">Indicates whether to open the database in transaction mode.</param> | ||
| 74 | /// <param name="asPatch">Indicates whether the database should be opened as a patch file.</param> | ||
| 75 | public static Database Open(string path, bool transact = false, bool asPatch = false) | ||
| 76 | { | ||
| 77 | var mode = transact ? OpenDatabase.Transact : OpenDatabase.Direct; | ||
| 78 | |||
| 79 | if (asPatch) | ||
| 80 | { | ||
| 81 | mode |= OpenDatabase.OpenPatchFile; | ||
| 82 | } | ||
| 83 | |||
| 84 | // Use the short path to avoid issues with long paths in the MSI API. | ||
| 85 | var shortPath = PathUtil.GetShortPath(path); | ||
| 86 | |||
| 87 | return new Database(shortPath, mode); | ||
| 88 | } | ||
| 89 | |||
| 90 | /// <summary> | ||
| 91 | /// Opens an existing <see cref="Database"/> with the specified path. | ||
| 92 | /// </summary> | ||
| 93 | /// <param name="path">Path of database to open.</param> | ||
| 94 | /// <param name="asPatch">Indicates whether the database should be opened as a patch file.</param> | ||
| 95 | public static Database OpenAsReadOnly(string path, bool asPatch = false) | ||
| 96 | { | ||
| 97 | var mode = OpenDatabase.ReadOnly; | ||
| 98 | |||
| 99 | if (asPatch) | ||
| 100 | { | ||
| 101 | mode |= OpenDatabase.OpenPatchFile; | ||
| 102 | } | ||
| 103 | |||
| 104 | // Use the short path to avoid issues with long paths in the MSI API. | ||
| 105 | var shortPath = PathUtil.GetShortPath(path); | ||
| 106 | |||
| 107 | return new Database(shortPath, mode); | ||
| 108 | } | ||
| 109 | |||
| 110 | /// <summary> | ||
| 38 | /// Apply a transform to the MSI. | 111 | /// Apply a transform to the MSI. |
| 39 | /// </summary> | 112 | /// </summary> |
| 40 | /// <param name="transformFile">Path to transform to apply.</param> | 113 | /// <param name="transformFile">Path to transform to apply.</param> |
| 41 | public void ApplyTransform(string transformFile) | 114 | public void ApplyTransform(string transformFile) |
| 42 | { | 115 | { |
| 116 | var shortTransformFile = PathUtil.GetShortPath(transformFile); | ||
| 117 | |||
| 43 | // get the curret validation bits | 118 | // get the curret validation bits |
| 44 | var conditions = TransformErrorConditions.None; | 119 | var conditions = TransformErrorConditions.None; |
| 45 | using (var summaryInfo = new SummaryInformation(transformFile)) | 120 | using (var summaryInfo = new SummaryInformation(shortTransformFile)) |
| 46 | { | 121 | { |
| 47 | try | 122 | try |
| 48 | { | 123 | { |
| @@ -65,7 +140,9 @@ namespace WixToolset.Core.Native.Msi | |||
| 65 | /// <param name="errorConditions">Specifies the error conditions that are to be suppressed.</param> | 140 | /// <param name="errorConditions">Specifies the error conditions that are to be suppressed.</param> |
| 66 | public void ApplyTransform(string transformFile, TransformErrorConditions errorConditions) | 141 | public void ApplyTransform(string transformFile, TransformErrorConditions errorConditions) |
| 67 | { | 142 | { |
| 68 | var error = MsiInterop.MsiDatabaseApplyTransform(this.Handle, transformFile, errorConditions); | 143 | var shortTransformFile = PathUtil.GetShortPath(transformFile); |
| 144 | |||
| 145 | var error = MsiInterop.MsiDatabaseApplyTransform(this.Handle, shortTransformFile, errorConditions); | ||
| 69 | if (0 != error) | 146 | if (0 != error) |
| 70 | { | 147 | { |
| 71 | throw new MsiException(error); | 148 | throw new MsiException(error); |
| @@ -119,7 +196,9 @@ namespace WixToolset.Core.Native.Msi | |||
| 119 | /// shows which properties should be validated to verify that this transform can be applied to the database.</param> | 196 | /// shows which properties should be validated to verify that this transform can be applied to the database.</param> |
| 120 | public void CreateTransformSummaryInfo(Database referenceDatabase, string transformFile, TransformErrorConditions errorConditions, TransformValidations validations) | 197 | public void CreateTransformSummaryInfo(Database referenceDatabase, string transformFile, TransformErrorConditions errorConditions, TransformValidations validations) |
| 121 | { | 198 | { |
| 122 | var error = MsiInterop.MsiCreateTransformSummaryInfo(this.Handle, referenceDatabase.Handle, transformFile, errorConditions, validations); | 199 | var shortTransformFile = PathUtil.GetShortPath(transformFile); |
| 200 | |||
| 201 | var error = MsiInterop.MsiCreateTransformSummaryInfo(this.Handle, referenceDatabase.Handle, shortTransformFile, errorConditions, validations); | ||
| 123 | if (0 != error) | 202 | if (0 != error) |
| 124 | { | 203 | { |
| 125 | throw new MsiException(error); | 204 | throw new MsiException(error); |
| @@ -137,7 +216,9 @@ namespace WixToolset.Core.Native.Msi | |||
| 137 | var folderPath = Path.GetFullPath(Path.GetDirectoryName(idtPath)); | 216 | var folderPath = Path.GetFullPath(Path.GetDirectoryName(idtPath)); |
| 138 | var fileName = Path.GetFileName(idtPath); | 217 | var fileName = Path.GetFileName(idtPath); |
| 139 | 218 | ||
| 140 | var error = MsiInterop.MsiDatabaseImport(this.Handle, folderPath, fileName); | 219 | var shortFolderPath = PathUtil.GetShortPath(folderPath); |
| 220 | |||
| 221 | var error = MsiInterop.MsiDatabaseImport(this.Handle, shortFolderPath, fileName); | ||
| 141 | if (1627 == error) // ERROR_FUNCTION_FAILED | 222 | if (1627 == error) // ERROR_FUNCTION_FAILED |
| 142 | { | 223 | { |
| 143 | throw new WixInvalidIdtException(idtPath); | 224 | throw new WixInvalidIdtException(idtPath); |
| @@ -161,7 +242,9 @@ namespace WixToolset.Core.Native.Msi | |||
| 161 | folderPath = Environment.CurrentDirectory; | 242 | folderPath = Environment.CurrentDirectory; |
| 162 | } | 243 | } |
| 163 | 244 | ||
| 164 | var error = MsiInterop.MsiDatabaseExport(this.Handle, tableName, folderPath, fileName); | 245 | var shortFolderPath = PathUtil.GetShortPath(folderPath); |
| 246 | |||
| 247 | var error = MsiInterop.MsiDatabaseExport(this.Handle, tableName, shortFolderPath, fileName); | ||
| 165 | if (0 != error) | 248 | if (0 != error) |
| 166 | { | 249 | { |
| 167 | throw new MsiException(error); | 250 | throw new MsiException(error); |
| @@ -177,13 +260,29 @@ namespace WixToolset.Core.Native.Msi | |||
| 177 | /// there are no differences between the two databases.</returns> | 260 | /// there are no differences between the two databases.</returns> |
| 178 | public bool GenerateTransform(Database referenceDatabase, string transformFile) | 261 | public bool GenerateTransform(Database referenceDatabase, string transformFile) |
| 179 | { | 262 | { |
| 180 | var error = MsiInterop.MsiDatabaseGenerateTransform(this.Handle, referenceDatabase.Handle, transformFile, 0, 0); | 263 | var fileCreated = false; |
| 181 | if (0 != error && 0xE8 != error) // ERROR_NO_DATA(0xE8) means no differences were found | 264 | |
| 265 | try | ||
| 182 | { | 266 | { |
| 183 | throw new MsiException(error); | 267 | fileCreated = PathUtil.CreateOrGetShortPath(transformFile, out var shortTransformFile); |
| 268 | |||
| 269 | var error = MsiInterop.MsiDatabaseGenerateTransform(this.Handle, referenceDatabase.Handle, shortTransformFile, 0, 0); | ||
| 270 | if (0 != error && 0xE8 != error) // ERROR_NO_DATA(0xE8) means no differences were found | ||
| 271 | { | ||
| 272 | throw new MsiException(error); | ||
| 273 | } | ||
| 274 | |||
| 275 | return (0xE8 != error); | ||
| 184 | } | 276 | } |
| 277 | catch // Cleanup on error | ||
| 278 | { | ||
| 279 | if (fileCreated) | ||
| 280 | { | ||
| 281 | File.Delete(transformFile); | ||
| 282 | } | ||
| 185 | 283 | ||
| 186 | return (0xE8 != error); | 284 | throw; |
| 285 | } | ||
| 187 | } | 286 | } |
| 188 | 287 | ||
| 189 | /// <summary> | 288 | /// <summary> |
diff --git a/src/wix/WixToolset.Core.Native/Msi/Installer.cs b/src/wix/WixToolset.Core.Native/Msi/Installer.cs index b2c2c630..14745469 100644 --- a/src/wix/WixToolset.Core.Native/Msi/Installer.cs +++ b/src/wix/WixToolset.Core.Native/Msi/Installer.cs | |||
| @@ -34,11 +34,13 @@ namespace WixToolset.Core.Native.Msi | |||
| 34 | var buffer = new StringBuilder(65535); | 34 | var buffer = new StringBuilder(65535); |
| 35 | var size = buffer.Capacity; | 35 | var size = buffer.Capacity; |
| 36 | 36 | ||
| 37 | var error = MsiInterop.MsiExtractPatchXMLData(path, 0, buffer, ref size); | 37 | var shortPath = PathUtil.GetShortPath(path); |
| 38 | |||
| 39 | var error = MsiInterop.MsiExtractPatchXMLData(shortPath, 0, buffer, ref size); | ||
| 38 | if (234 == error) | 40 | if (234 == error) |
| 39 | { | 41 | { |
| 40 | buffer.EnsureCapacity(++size); | 42 | buffer.EnsureCapacity(++size); |
| 41 | error = MsiInterop.MsiExtractPatchXMLData(path, 0, buffer, ref size); | 43 | error = MsiInterop.MsiExtractPatchXMLData(shortPath, 0, buffer, ref size); |
| 42 | } | 44 | } |
| 43 | 45 | ||
| 44 | if (error != 0) | 46 | if (error != 0) |
| @@ -57,8 +59,12 @@ namespace WixToolset.Core.Native.Msi | |||
| 57 | /// <param name="hash">Int array that receives the returned file hash information.</param> | 59 | /// <param name="hash">Int array that receives the returned file hash information.</param> |
| 58 | public static void GetFileHash(string filePath, int options, out int[] hash) | 60 | public static void GetFileHash(string filePath, int options, out int[] hash) |
| 59 | { | 61 | { |
| 60 | var hashInterop = new MSIFILEHASHINFO(); | 62 | var hashInterop = new MSIFILEHASHINFO |
| 61 | hashInterop.FileHashInfoSize = 20; | 63 | { |
| 64 | FileHashInfoSize = 20 | ||
| 65 | }; | ||
| 66 | |||
| 67 | filePath = PathUtil.GetPrefixedLongPath(filePath); | ||
| 62 | 68 | ||
| 63 | var error = MsiInterop.MsiGetFileHash(filePath, Convert.ToUInt32(options), hashInterop); | 69 | var error = MsiInterop.MsiGetFileHash(filePath, Convert.ToUInt32(options), hashInterop); |
| 64 | if (0 != error) | 70 | if (0 != error) |
| @@ -76,9 +82,9 @@ namespace WixToolset.Core.Native.Msi | |||
| 76 | } | 82 | } |
| 77 | 83 | ||
| 78 | /// <summary> | 84 | /// <summary> |
| 79 | /// Returns the version string and language string in the format that the installer | 85 | /// Returns the version string and language string in the format that the installer |
| 80 | /// expects to find them in the database. If you just want version information, set | 86 | /// expects to find them in the database. If you just want version information, set |
| 81 | /// lpLangBuf and pcchLangBuf to zero. If you just want language information, set | 87 | /// lpLangBuf and pcchLangBuf to zero. If you just want language information, set |
| 82 | /// lpVersionBuf and pcchVersionBuf to zero. | 88 | /// lpVersionBuf and pcchVersionBuf to zero. |
| 83 | /// </summary> | 89 | /// </summary> |
| 84 | /// <param name="filePath">Specifies the path to the file.</param> | 90 | /// <param name="filePath">Specifies the path to the file.</param> |
| @@ -91,6 +97,8 @@ namespace WixToolset.Core.Native.Msi | |||
| 91 | var versionBuffer = new StringBuilder(versionLength); | 97 | var versionBuffer = new StringBuilder(versionLength); |
| 92 | var languageBuffer = new StringBuilder(languageLength); | 98 | var languageBuffer = new StringBuilder(languageLength); |
| 93 | 99 | ||
| 100 | filePath = PathUtil.GetPrefixedLongPath(filePath); | ||
| 101 | |||
| 94 | var error = MsiInterop.MsiGetFileVersion(filePath, versionBuffer, ref versionLength, languageBuffer, ref languageLength); | 102 | var error = MsiInterop.MsiGetFileVersion(filePath, versionBuffer, ref versionLength, languageBuffer, ref languageLength); |
| 95 | if (234 == error) | 103 | if (234 == error) |
| 96 | { | 104 | { |
diff --git a/src/wix/WixToolset.Core.Native/Msi/OpenDatabase.cs b/src/wix/WixToolset.Core.Native/Msi/OpenDatabase.cs index 18a78f77..6d0226d2 100644 --- a/src/wix/WixToolset.Core.Native/Msi/OpenDatabase.cs +++ b/src/wix/WixToolset.Core.Native/Msi/OpenDatabase.cs | |||
| @@ -1,4 +1,4 @@ | |||
| 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. | 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 | 2 | ||
| 3 | namespace WixToolset.Core.Native.Msi | 3 | namespace WixToolset.Core.Native.Msi |
| 4 | { | 4 | { |
diff --git a/src/wix/WixToolset.Core.Native/Msi/SummaryInformation.cs b/src/wix/WixToolset.Core.Native/Msi/SummaryInformation.cs index 3b3dea0f..3eed1274 100644 --- a/src/wix/WixToolset.Core.Native/Msi/SummaryInformation.cs +++ b/src/wix/WixToolset.Core.Native/Msi/SummaryInformation.cs | |||
| @@ -220,8 +220,10 @@ namespace WixToolset.Core.Native.Msi | |||
| 220 | throw new ArgumentNullException(nameof(databaseFile)); | 220 | throw new ArgumentNullException(nameof(databaseFile)); |
| 221 | } | 221 | } |
| 222 | 222 | ||
| 223 | var shortDatabaseFile = PathUtil.GetShortPath(databaseFile); | ||
| 224 | |||
| 223 | var handle = IntPtr.Zero; | 225 | var handle = IntPtr.Zero; |
| 224 | var error = MsiInterop.MsiGetSummaryInformation(IntPtr.Zero, databaseFile, 0, ref handle); | 226 | var error = MsiInterop.MsiGetSummaryInformation(IntPtr.Zero, shortDatabaseFile, 0, ref handle); |
| 225 | if (0 != error) | 227 | if (0 != error) |
| 226 | { | 228 | { |
| 227 | throw new MsiException(error); | 229 | throw new MsiException(error); |
diff --git a/src/wix/WixToolset.Core.Native/WindowsInstallerValidator.cs b/src/wix/WixToolset.Core.Native/WindowsInstallerValidator.cs index 7978304a..434b0887 100644 --- a/src/wix/WixToolset.Core.Native/WindowsInstallerValidator.cs +++ b/src/wix/WixToolset.Core.Native/WindowsInstallerValidator.cs | |||
| @@ -93,7 +93,7 @@ namespace WixToolset.Core.Native | |||
| 93 | 93 | ||
| 94 | try | 94 | try |
| 95 | { | 95 | { |
| 96 | using (var database = new Database(this.DatabasePath, OpenDatabase.Direct)) | 96 | using (var database = Database.Open(this.DatabasePath)) |
| 97 | { | 97 | { |
| 98 | var propertyTableExists = database.TableExists("Property"); | 98 | var propertyTableExists = database.TableExists("Property"); |
| 99 | string productCode = null; | 99 | string productCode = null; |
| @@ -130,7 +130,7 @@ namespace WixToolset.Core.Native | |||
| 130 | 130 | ||
| 131 | try | 131 | try |
| 132 | { | 132 | { |
| 133 | using (var cubeDatabase = new Database(findCubeFile.Path, OpenDatabase.ReadOnly)) | 133 | using (var cubeDatabase = Database.OpenAsReadOnly(findCubeFile.Path)) |
| 134 | { | 134 | { |
| 135 | try | 135 | try |
| 136 | { | 136 | { |
diff --git a/src/wix/WixToolset.Core.WindowsInstaller/Bind/BindTransformCommand.cs b/src/wix/WixToolset.Core.WindowsInstaller/Bind/BindTransformCommand.cs index e96df21f..f327081a 100644 --- a/src/wix/WixToolset.Core.WindowsInstaller/Bind/BindTransformCommand.cs +++ b/src/wix/WixToolset.Core.WindowsInstaller/Bind/BindTransformCommand.cs | |||
| @@ -418,8 +418,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
| 418 | Directory.CreateDirectory(Path.GetDirectoryName(this.OutputPath)); | 418 | Directory.CreateDirectory(Path.GetDirectoryName(this.OutputPath)); |
| 419 | 419 | ||
| 420 | // create the transform file | 420 | // create the transform file |
| 421 | using (var targetDatabase = new Database(targetDatabaseFile, OpenDatabase.ReadOnly)) | 421 | using (var targetDatabase = Database.OpenAsReadOnly(targetDatabaseFile)) |
| 422 | using (var updatedDatabase = new Database(updatedDatabaseFile, OpenDatabase.ReadOnly)) | 422 | using (var updatedDatabase = Database.OpenAsReadOnly(updatedDatabaseFile)) |
| 423 | { | 423 | { |
| 424 | if (updatedDatabase.GenerateTransform(targetDatabase, this.OutputPath)) | 424 | if (updatedDatabase.GenerateTransform(targetDatabase, this.OutputPath)) |
| 425 | { | 425 | { |
diff --git a/src/wix/WixToolset.Core.WindowsInstaller/Bind/ExtractMergeModuleFilesCommand.cs b/src/wix/WixToolset.Core.WindowsInstaller/Bind/ExtractMergeModuleFilesCommand.cs index 94ed0afc..117923e5 100644 --- a/src/wix/WixToolset.Core.WindowsInstaller/Bind/ExtractMergeModuleFilesCommand.cs +++ b/src/wix/WixToolset.Core.WindowsInstaller/Bind/ExtractMergeModuleFilesCommand.cs | |||
| @@ -90,7 +90,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
| 90 | try | 90 | try |
| 91 | { | 91 | { |
| 92 | // read the module's File table to get its FileMediaInformation entries and gather any other information needed from the module. | 92 | // read the module's File table to get its FileMediaInformation entries and gather any other information needed from the module. |
| 93 | using (var db = new Database(wixMergeRow.SourceFile, OpenDatabase.ReadOnly)) | 93 | using (var db = Database.OpenAsReadOnly(wixMergeRow.SourceFile)) |
| 94 | { | 94 | { |
| 95 | if (db.TableExists("File") && db.TableExists("Component")) | 95 | if (db.TableExists("File") && db.TableExists("Component")) |
| 96 | { | 96 | { |
diff --git a/src/wix/WixToolset.Core.WindowsInstaller/Bind/GenerateDatabaseCommand.cs b/src/wix/WixToolset.Core.WindowsInstaller/Bind/GenerateDatabaseCommand.cs index 3d831577..7414cb54 100644 --- a/src/wix/WixToolset.Core.WindowsInstaller/Bind/GenerateDatabaseCommand.cs +++ b/src/wix/WixToolset.Core.WindowsInstaller/Bind/GenerateDatabaseCommand.cs | |||
| @@ -81,20 +81,13 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
| 81 | 81 | ||
| 82 | var idtFolder = Path.Combine(baseDirectory, IdtsSubFolder); | 82 | var idtFolder = Path.Combine(baseDirectory, IdtsSubFolder); |
| 83 | 83 | ||
| 84 | var type = OpenDatabase.CreateDirect; | ||
| 85 | |||
| 86 | if (OutputType.Patch == this.Data.Type) | ||
| 87 | { | ||
| 88 | type |= OpenDatabase.OpenPatchFile; | ||
| 89 | } | ||
| 90 | |||
| 91 | try | 84 | try |
| 92 | { | 85 | { |
| 93 | Directory.CreateDirectory(Path.GetDirectoryName(this.OutputPath)); | 86 | Directory.CreateDirectory(Path.GetDirectoryName(this.OutputPath)); |
| 94 | 87 | ||
| 95 | Directory.CreateDirectory(idtFolder); | 88 | Directory.CreateDirectory(idtFolder); |
| 96 | 89 | ||
| 97 | using (var db = new Database(this.OutputPath, type)) | 90 | using (var db = Database.Create(this.OutputPath, asPatch: OutputType.Patch == this.Data.Type)) |
| 98 | { | 91 | { |
| 99 | // If we're not using the default codepage, import a new one into our | 92 | // If we're not using the default codepage, import a new one into our |
| 100 | // database before we add any tables (or the tables would be added | 93 | // database before we add any tables (or the tables would be added |
diff --git a/src/wix/WixToolset.Core.WindowsInstaller/Bind/MergeModulesCommand.cs b/src/wix/WixToolset.Core.WindowsInstaller/Bind/MergeModulesCommand.cs index 5f21f496..71a2e367 100644 --- a/src/wix/WixToolset.Core.WindowsInstaller/Bind/MergeModulesCommand.cs +++ b/src/wix/WixToolset.Core.WindowsInstaller/Bind/MergeModulesCommand.cs | |||
| @@ -223,7 +223,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
| 223 | return; | 223 | return; |
| 224 | } | 224 | } |
| 225 | 225 | ||
| 226 | using (var db = new Database(this.OutputPath, OpenDatabase.Direct)) | 226 | using (var db = Database.Open(this.OutputPath)) |
| 227 | { | 227 | { |
| 228 | // Suppress individual actions. | 228 | // Suppress individual actions. |
| 229 | foreach (var suppressAction in this.Section.Symbols.OfType<WixSuppressActionSymbol>()) | 229 | foreach (var suppressAction in this.Section.Symbols.OfType<WixSuppressActionSymbol>()) |
diff --git a/src/wix/WixToolset.Core.WindowsInstaller/Bind/ProcessUncompressedFilesCommand.cs b/src/wix/WixToolset.Core.WindowsInstaller/Bind/ProcessUncompressedFilesCommand.cs index c5f198f8..ff7c6579 100644 --- a/src/wix/WixToolset.Core.WindowsInstaller/Bind/ProcessUncompressedFilesCommand.cs +++ b/src/wix/WixToolset.Core.WindowsInstaller/Bind/ProcessUncompressedFilesCommand.cs | |||
| @@ -64,7 +64,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
| 64 | 64 | ||
| 65 | var mediaRows = this.Section.Symbols.OfType<MediaSymbol>().ToDictionary(t => t.DiskId); | 65 | var mediaRows = this.Section.Symbols.OfType<MediaSymbol>().ToDictionary(t => t.DiskId); |
| 66 | 66 | ||
| 67 | using (var db = new Database(this.DatabasePath, OpenDatabase.ReadOnly)) | 67 | using (var db = Database.OpenAsReadOnly(this.DatabasePath)) |
| 68 | { | 68 | { |
| 69 | using (var directoryView = db.OpenExecuteView("SELECT `Directory`, `Directory_Parent`, `DefaultDir` FROM `Directory`")) | 69 | using (var directoryView = db.OpenExecuteView("SELECT `Directory`, `Directory_Parent`, `DefaultDir` FROM `Directory`")) |
| 70 | { | 70 | { |
diff --git a/src/wix/WixToolset.Core.WindowsInstaller/Bind/UpdateFileFacadesCommand.cs b/src/wix/WixToolset.Core.WindowsInstaller/Bind/UpdateFileFacadesCommand.cs index 52d2146c..75e536c2 100644 --- a/src/wix/WixToolset.Core.WindowsInstaller/Bind/UpdateFileFacadesCommand.cs +++ b/src/wix/WixToolset.Core.WindowsInstaller/Bind/UpdateFileFacadesCommand.cs | |||
| @@ -76,7 +76,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
| 76 | var assemblySymbols = this.Section.Symbols.OfType<AssemblySymbol>().ToDictionary(t => t.Id.Id); | 76 | var assemblySymbols = this.Section.Symbols.OfType<AssemblySymbol>().ToDictionary(t => t.Id.Id); |
| 77 | 77 | ||
| 78 | Parallel.ForEach(facades, | 78 | Parallel.ForEach(facades, |
| 79 | new ParallelOptions{ | 79 | new ParallelOptions |
| 80 | { | ||
| 80 | CancellationToken = this.CancellationToken, | 81 | CancellationToken = this.CancellationToken, |
| 81 | MaxDegreeOfParallelism = this.ThreadCount | 82 | MaxDegreeOfParallelism = this.ThreadCount |
| 82 | }, | 83 | }, |
diff --git a/src/wix/WixToolset.Core.WindowsInstaller/Inscribe/InscribeMsiPackageCommand.cs b/src/wix/WixToolset.Core.WindowsInstaller/Inscribe/InscribeMsiPackageCommand.cs index 455057f6..344cccb8 100644 --- a/src/wix/WixToolset.Core.WindowsInstaller/Inscribe/InscribeMsiPackageCommand.cs +++ b/src/wix/WixToolset.Core.WindowsInstaller/Inscribe/InscribeMsiPackageCommand.cs | |||
| @@ -61,7 +61,7 @@ namespace WixToolset.Core.WindowsInstaller.Inscribe | |||
| 61 | return shouldCommit; | 61 | return shouldCommit; |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | using (var database = new Database(databasePath, OpenDatabase.Transact)) | 64 | using (var database = Database.Open(databasePath, transact: true)) |
| 65 | { | 65 | { |
| 66 | // Just use the English codepage, because the tables we're importing only have binary streams / MSI identifiers / other non-localizable content | 66 | // Just use the English codepage, because the tables we're importing only have binary streams / MSI identifiers / other non-localizable content |
| 67 | var codepage = 1252; | 67 | var codepage = 1252; |
diff --git a/src/wix/WixToolset.Core.WindowsInstaller/Unbind/UnbindDatabaseCommand.cs b/src/wix/WixToolset.Core.WindowsInstaller/Unbind/UnbindDatabaseCommand.cs index ef02f5d1..ac6a6ab3 100644 --- a/src/wix/WixToolset.Core.WindowsInstaller/Unbind/UnbindDatabaseCommand.cs +++ b/src/wix/WixToolset.Core.WindowsInstaller/Unbind/UnbindDatabaseCommand.cs | |||
| @@ -86,7 +86,7 @@ namespace WixToolset.Core.WindowsInstaller.Unbind | |||
| 86 | { | 86 | { |
| 87 | if (this.Database == null) | 87 | if (this.Database == null) |
| 88 | { | 88 | { |
| 89 | database = new Database(this.DatabasePath, OpenDatabase.ReadOnly); | 89 | database = Database.OpenAsReadOnly(this.DatabasePath); |
| 90 | this.Database = database; | 90 | this.Database = database; |
| 91 | } | 91 | } |
| 92 | 92 | ||
diff --git a/src/wix/WixToolset.Core.WindowsInstaller/Unbind/UnbindTransformCommand.cs b/src/wix/WixToolset.Core.WindowsInstaller/Unbind/UnbindTransformCommand.cs index aad3d34d..5df38db3 100644 --- a/src/wix/WixToolset.Core.WindowsInstaller/Unbind/UnbindTransformCommand.cs +++ b/src/wix/WixToolset.Core.WindowsInstaller/Unbind/UnbindTransformCommand.cs | |||
| @@ -273,7 +273,7 @@ namespace WixToolset.Core.WindowsInstaller.Unbind | |||
| 273 | 273 | ||
| 274 | private Database ApplyTransformToSchemaDatabase(string schemaDatabasePath, TransformErrorConditions transformConditions) | 274 | private Database ApplyTransformToSchemaDatabase(string schemaDatabasePath, TransformErrorConditions transformConditions) |
| 275 | { | 275 | { |
| 276 | var msiDatabase = new Database(schemaDatabasePath, OpenDatabase.Transact); | 276 | var msiDatabase = Database.Open(schemaDatabasePath, transact: true); |
| 277 | 277 | ||
| 278 | try | 278 | try |
| 279 | { | 279 | { |
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/LongPathFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/LongPathFixture.cs new file mode 100644 index 00000000..2cada64d --- /dev/null +++ b/src/wix/test/WixToolsetTest.CoreIntegration/LongPathFixture.cs | |||
| @@ -0,0 +1,89 @@ | |||
| 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 WixInternal.Core.TestPackage; | ||
| 8 | using WixInternal.TestSupport; | ||
| 9 | using WixToolset.Data; | ||
| 10 | using WixToolset.Data.Symbols; | ||
| 11 | using Xunit; | ||
| 12 | |||
| 13 | public class LongPathFixture | ||
| 14 | { | ||
| 15 | [Fact] | ||
| 16 | public void TestLongPathSupport() | ||
| 17 | { | ||
| 18 | var testDataFolder = TestData.Get(@"TestData", "SingleFile"); | ||
| 19 | |||
| 20 | using (var fs = new DisposableFileSystem()) | ||
| 21 | { | ||
| 22 | var folder = fs.GetFolder(); | ||
| 23 | |||
| 24 | while (folder.Length < 500) | ||
| 25 | { | ||
| 26 | folder = Path.Combine(folder, new string('z', 100)); | ||
| 27 | } | ||
| 28 | |||
| 29 | CopyDirectory(testDataFolder, folder); | ||
| 30 | |||
| 31 | var baseFolder = fs.GetFolder(); | ||
| 32 | |||
| 33 | while (baseFolder.Length < 500) | ||
| 34 | { | ||
| 35 | baseFolder = Path.Combine(baseFolder, new string('a', 100)); | ||
| 36 | } | ||
| 37 | |||
| 38 | var intermediateFolder = Path.Combine(baseFolder, "obj"); | ||
| 39 | |||
| 40 | var result = WixRunner.Execute( | ||
| 41 | [ | ||
| 42 | "build", | ||
| 43 | Path.Combine(folder, "Package.wxs"), | ||
| 44 | Path.Combine(folder, "PackageComponents.wxs"), | ||
| 45 | "-loc", Path.Combine(folder, "Package.en-us.wxl"), | ||
| 46 | "-bindpath", Path.Combine(folder, "data"), | ||
| 47 | "-intermediateFolder", intermediateFolder, | ||
| 48 | "-o", Path.Combine(baseFolder, "bin", "test.msi") | ||
| 49 | ]); | ||
| 50 | |||
| 51 | result.AssertSuccess(); | ||
| 52 | |||
| 53 | Assert.True(File.Exists(Path.Combine(baseFolder, "bin", "test.msi"))); | ||
| 54 | Assert.True(File.Exists(Path.Combine(baseFolder, "bin", "test.wixpdb"))); | ||
| 55 | Assert.True(File.Exists(Path.Combine(baseFolder, "bin", "PFiles", "Example Corporation MsiPackage", "test.txt"))); | ||
| 56 | |||
| 57 | var intermediate = Intermediate.Load(Path.Combine(baseFolder, "bin", "test.wixpdb")); | ||
| 58 | |||
| 59 | var section = intermediate.Sections.Single(); | ||
| 60 | |||
| 61 | var fileSymbol = section.Symbols.OfType<FileSymbol>().First(); | ||
| 62 | WixAssert.StringEqual(Path.Combine(folder, @"data\test.txt"), fileSymbol[FileSymbolFields.Source].AsPath().Path); | ||
| 63 | WixAssert.StringEqual(@"test.txt", fileSymbol[FileSymbolFields.Source].PreviousValue.AsPath().Path); | ||
| 64 | } | ||
| 65 | } | ||
| 66 | |||
| 67 | private static void CopyDirectory(string sourceFolder, string targetFolder) | ||
| 68 | { | ||
| 69 | // Ensure the target directory exists | ||
| 70 | Directory.CreateDirectory(targetFolder); | ||
| 71 | |||
| 72 | // Copy all files | ||
| 73 | foreach (var file in Directory.GetFiles(sourceFolder)) | ||
| 74 | { | ||
| 75 | var targetFile = Path.Combine(targetFolder, Path.GetFileName(file)); | ||
| 76 | |||
| 77 | File.Copy(file, targetFile); | ||
| 78 | } | ||
| 79 | |||
| 80 | // Recursively copy subdirectories | ||
| 81 | foreach (var subFolder in Directory.GetDirectories(sourceFolder)) | ||
| 82 | { | ||
| 83 | var targetSubFolder = Path.Combine(targetFolder, Path.GetFileName(subFolder)); | ||
| 84 | |||
| 85 | CopyDirectory(subFolder, targetSubFolder); | ||
| 86 | } | ||
| 87 | } | ||
| 88 | } | ||
| 89 | } | ||
diff --git a/src/wix/wixnative/wixnative.manifest b/src/wix/wixnative/wixnative.manifest new file mode 100644 index 00000000..ce288e89 --- /dev/null +++ b/src/wix/wixnative/wixnative.manifest | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | <?xml version="1.0" encoding="UTF-8" standalone="yes"?> | ||
| 2 | <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> | ||
| 3 | <assemblyIdentity name="WixToolset.Tools.WixNative" version="4.0.0.0" processorArchitecture="x86" type="win32"/> | ||
| 4 | <description>WiX Toolset Native</description> | ||
| 5 | <application xmlns="urn:schemas-microsoft-com:asm.v3"><windowsSettings> | ||
| 6 | <longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware> | ||
| 7 | </windowsSettings></application> | ||
| 8 | <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"><security><requestedPrivileges><requestedExecutionLevel level="asInvoker" uiAccess="false"/></requestedPrivileges></security></trustInfo> | ||
| 9 | </assembly> | ||
diff --git a/src/wix/wixnative/wixnative.vcxproj b/src/wix/wixnative/wixnative.vcxproj index e4474bb1..c4e05a62 100644 --- a/src/wix/wixnative/wixnative.vcxproj +++ b/src/wix/wixnative/wixnative.vcxproj | |||
| @@ -55,6 +55,9 @@ | |||
| 55 | <ClCompile Include="extractcab.cpp" /> | 55 | <ClCompile Include="extractcab.cpp" /> |
| 56 | <ClCompile Include="smartcab.cpp" /> | 56 | <ClCompile Include="smartcab.cpp" /> |
| 57 | </ItemGroup> | 57 | </ItemGroup> |
| 58 | <ItemGroup> | ||
| 59 | <Manifest Include="wixnative.manifest" /> | ||
| 60 | </ItemGroup> | ||
| 58 | 61 | ||
| 59 | <ItemGroup> | 62 | <ItemGroup> |
| 60 | <ClInclude Include="precomp.h" /> | 63 | <ClInclude Include="precomp.h" /> |
