aboutsummaryrefslogtreecommitdiff
path: root/src/WixToolset.Core
diff options
context:
space:
mode:
authorRob Mensching <rob@firegiant.com>2021-03-14 07:38:48 -0700
committerRob Mensching <rob@firegiant.com>2021-03-14 07:47:48 -0700
commit3ccd5e439da4296d6f2b66ce47075ab20d039676 (patch)
treeb5546552613b869367d09f444492a0bbcfadcfe0 /src/WixToolset.Core
parent574785ab1421c9b67336c13ade5c2263e665ca07 (diff)
downloadwix-3ccd5e439da4296d6f2b66ce47075ab20d039676.tar.gz
wix-3ccd5e439da4296d6f2b66ce47075ab20d039676.tar.bz2
wix-3ccd5e439da4296d6f2b66ce47075ab20d039676.zip
Minimize public surface area of Core
Fixes wixtoolset/issues#6374
Diffstat (limited to 'src/WixToolset.Core')
-rw-r--r--src/WixToolset.Core/AppCommon.cs45
-rw-r--r--src/WixToolset.Core/Bind/ExtractEmbeddedFilesCommand.cs3
-rw-r--r--src/WixToolset.Core/Bind/ResolveDelayedFieldsCommand.cs17
-rw-r--r--src/WixToolset.Core/CommandLine/CommandLine.cs10
-rw-r--r--src/WixToolset.Core/CommandLine/HelpCommand.cs8
-rw-r--r--src/WixToolset.Core/Common.cs324
-rw-r--r--src/WixToolset.Core/Compiler.cs8
-rw-r--r--src/WixToolset.Core/CompilerCore.cs37
-rw-r--r--src/WixToolset.Core/Compiler_Package.cs10
-rw-r--r--src/WixToolset.Core/Compiler_Patch.cs14
-rw-r--r--src/WixToolset.Core/ExtensibilityServices/BackendHelper.cs86
-rw-r--r--src/WixToolset.Core/ExtensibilityServices/FileFacade.cs (renamed from src/WixToolset.Core/Bind/FileFacade.cs)6
-rw-r--r--src/WixToolset.Core/ExtensibilityServices/ParseHelper.cs111
-rw-r--r--src/WixToolset.Core/ExtensibilityServices/WixBranding.cs124
-rw-r--r--src/WixToolset.Core/LocalizationParser.cs26
-rw-r--r--src/WixToolset.Core/OptimizeCA.cs33
-rw-r--r--src/WixToolset.Core/PatchSymbolFlagsType.cs34
-rw-r--r--src/WixToolset.Core/ResolvedCabinet.cs2
-rw-r--r--src/WixToolset.Core/WixDistribution.cs109
-rw-r--r--src/WixToolset.Core/WixToolsetServiceProvider.cs1
20 files changed, 406 insertions, 602 deletions
diff --git a/src/WixToolset.Core/AppCommon.cs b/src/WixToolset.Core/AppCommon.cs
deleted file mode 100644
index 7f54b057..00000000
--- a/src/WixToolset.Core/AppCommon.cs
+++ /dev/null
@@ -1,45 +0,0 @@
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
3namespace WixToolset.Core
4{
5 using System;
6 using System.Reflection;
7
8 /// <summary>
9 /// Common utilities for Wix applications.
10 /// </summary>
11 public static class AppCommon
12 {
13 /// <summary>
14 /// Creates and returns the string for CreatingApplication field (MSI Summary Information Stream).
15 /// </summary>
16 /// <remarks>It reads the AssemblyProductAttribute and AssemblyVersionAttribute of executing assembly
17 /// and builds the CreatingApplication string of the form "[ProductName] ([ProductVersion])".</remarks>
18 /// <returns>Returns value for PID_APPNAME."</returns>
19 public static string GetCreatingApplicationString()
20 {
21 var assembly = Assembly.GetExecutingAssembly();
22 return WixDistribution.ReplacePlaceholders("[AssemblyProduct] ([FileVersion])", assembly);
23 }
24
25 /// <summary>
26 /// Displays help message header on Console for caller tool.
27 /// </summary>
28 public static void DisplayToolHeader()
29 {
30 var assembly = Assembly.GetCallingAssembly();
31 Console.WriteLine(WixDistribution.ReplacePlaceholders("[AssemblyProduct] [AssemblyDescription] version [FileVersion]", assembly));
32 Console.WriteLine(WixDistribution.ReplacePlaceholders("[AssemblyCopyright]", assembly));
33 }
34
35 /// <summary>
36 /// Displays help message header on Console for caller tool.
37 /// </summary>
38 public static void DisplayToolFooter()
39 {
40 var assembly = Assembly.GetCallingAssembly();
41 Console.WriteLine();
42 Console.WriteLine(WixDistribution.ReplacePlaceholders("For more information see: [SupportUrl]", assembly));
43 }
44 }
45}
diff --git a/src/WixToolset.Core/Bind/ExtractEmbeddedFilesCommand.cs b/src/WixToolset.Core/Bind/ExtractEmbeddedFilesCommand.cs
index 29fba6b2..981a991f 100644
--- a/src/WixToolset.Core/Bind/ExtractEmbeddedFilesCommand.cs
+++ b/src/WixToolset.Core/Bind/ExtractEmbeddedFilesCommand.cs
@@ -9,8 +9,7 @@ namespace WixToolset.Core.Bind
9 using WixToolset.Extensibility.Data; 9 using WixToolset.Extensibility.Data;
10 using WixToolset.Extensibility.Services; 10 using WixToolset.Extensibility.Services;
11 11
12#pragma warning disable 1591 // TODO: this shouldn't be public, need interface in Extensibility 12 internal class ExtractEmbeddedFilesCommand
13 public class ExtractEmbeddedFilesCommand
14 { 13 {
15 public ExtractEmbeddedFilesCommand(IBackendHelper backendHelper, IEnumerable<IExpectedExtractFile> embeddedFiles) 14 public ExtractEmbeddedFilesCommand(IBackendHelper backendHelper, IEnumerable<IExpectedExtractFile> embeddedFiles)
16 { 15 {
diff --git a/src/WixToolset.Core/Bind/ResolveDelayedFieldsCommand.cs b/src/WixToolset.Core/Bind/ResolveDelayedFieldsCommand.cs
index 14b6d011..0afcc2b3 100644
--- a/src/WixToolset.Core/Bind/ResolveDelayedFieldsCommand.cs
+++ b/src/WixToolset.Core/Bind/ResolveDelayedFieldsCommand.cs
@@ -10,19 +10,18 @@ namespace WixToolset.Core.Bind
10 using WixToolset.Extensibility.Data; 10 using WixToolset.Extensibility.Data;
11 using WixToolset.Extensibility.Services; 11 using WixToolset.Extensibility.Services;
12 12
13#pragma warning disable 1591 // TODO: this shouldn't be public, need interface in Extensibility
14 /// <summary> 13 /// <summary>
15 /// Resolves the fields which had variables that needed to be resolved after the file information 14 /// Resolves the fields which had variables that needed to be resolved after the file information
16 /// was loaded. 15 /// was loaded.
17 /// </summary> 16 /// </summary>
18 public class ResolveDelayedFieldsCommand 17 internal class ResolveDelayedFieldsCommand
19 { 18 {
20 /// <summary> 19 /// <summary>
21 /// Resolve delayed fields. 20 /// Resolve delayed fields.
22 /// </summary> 21 /// </summary>
23 /// <param name="messaging"></param> 22 /// <param name="messaging"></param>
24 /// <param name="delayedFields">The fields which had resolution delayed.</param> 23 /// <param name="delayedFields">The fields which had resolution delayed.</param>
25 /// <param name="variableCache">The file information to use when resolving variables.</param> 24 /// <param name="variableCache">The cached variable values used when resolving delayed fields.</param>
26 public ResolveDelayedFieldsCommand(IMessaging messaging, IEnumerable<IDelayedField> delayedFields, Dictionary<string, string> variableCache) 25 public ResolveDelayedFieldsCommand(IMessaging messaging, IEnumerable<IDelayedField> delayedFields, Dictionary<string, string> variableCache)
27 { 26 {
28 this.Messaging = messaging; 27 this.Messaging = messaging;
@@ -49,7 +48,7 @@ namespace WixToolset.Core.Bind
49 // process properties first in case they refer to other binder variables 48 // process properties first in case they refer to other binder variables
50 if (delayedField.Symbol.Definition.Type == SymbolDefinitionType.Property) 49 if (delayedField.Symbol.Definition.Type == SymbolDefinitionType.Property)
51 { 50 {
52 var value = ResolveDelayedVariables(propertySymbol.SourceLineNumbers, delayedField.Field.AsString(), this.VariableCache); 51 var value = this.ResolveDelayedVariables(propertySymbol.SourceLineNumbers, delayedField.Field.AsString());
53 52
54 // update the variable cache with the new value 53 // update the variable cache with the new value
55 var key = String.Concat("property.", propertySymbol.Id.Id); 54 var key = String.Concat("property.", propertySymbol.Id.Id);
@@ -72,7 +71,7 @@ namespace WixToolset.Core.Bind
72 71
73 // add specialization for ProductVersion fields 72 // add specialization for ProductVersion fields
74 var keyProductVersion = "property.ProductVersion"; 73 var keyProductVersion = "property.ProductVersion";
75 if (this.VariableCache.TryGetValue(keyProductVersion, out var versionValue) && Version.TryParse(versionValue, out Version productVersion)) 74 if (this.VariableCache.TryGetValue(keyProductVersion, out var versionValue) && Version.TryParse(versionValue, out var productVersion))
76 { 75 {
77 // Don't add the variable if it already exists (developer defined a property with the same name). 76 // Don't add the variable if it already exists (developer defined a property with the same name).
78 var fieldKey = String.Concat(keyProductVersion, ".Major"); 77 var fieldKey = String.Concat(keyProductVersion, ".Major");
@@ -105,7 +104,7 @@ namespace WixToolset.Core.Bind
105 { 104 {
106 try 105 try
107 { 106 {
108 var value = ResolveDelayedVariables(delayedField.Symbol.SourceLineNumbers, delayedField.Field.AsString(), this.VariableCache); 107 var value = this.ResolveDelayedVariables(delayedField.Symbol.SourceLineNumbers, delayedField.Field.AsString());
109 delayedField.Field.Set(value); 108 delayedField.Field.Set(value);
110 } 109 }
111 catch (WixException we) 110 catch (WixException we)
@@ -115,7 +114,7 @@ namespace WixToolset.Core.Bind
115 } 114 }
116 } 115 }
117 116
118 private static string ResolveDelayedVariables(SourceLineNumber sourceLineNumbers, string value, IDictionary<string, string> resolutionData) 117 private string ResolveDelayedVariables(SourceLineNumber sourceLineNumbers, string value)
119 { 118 {
120 var start = 0; 119 var start = 0;
121 120
@@ -125,7 +124,7 @@ namespace WixToolset.Core.Bind
125 { 124 {
126 var key = String.Concat(parsed.Name, ".", parsed.Scope); 125 var key = String.Concat(parsed.Name, ".", parsed.Scope);
127 126
128 if (!resolutionData.TryGetValue(key, out var resolvedValue)) 127 if (!this.VariableCache.TryGetValue(key, out var resolvedValue))
129 { 128 {
130 resolvedValue = parsed.DefaultValue; 129 resolvedValue = parsed.DefaultValue;
131 } 130 }
@@ -149,7 +148,7 @@ namespace WixToolset.Core.Bind
149 } 148 }
150 else 149 else
151 { 150 {
152 throw new WixException(ErrorMessages.UnresolvedBindReference(sourceLineNumbers, value)); 151 this.Messaging.Write(ErrorMessages.UnresolvedBindReference(sourceLineNumbers, value));
153 } 152 }
154 } 153 }
155 else 154 else
diff --git a/src/WixToolset.Core/CommandLine/CommandLine.cs b/src/WixToolset.Core/CommandLine/CommandLine.cs
index 0c21eaaa..7371628b 100644
--- a/src/WixToolset.Core/CommandLine/CommandLine.cs
+++ b/src/WixToolset.Core/CommandLine/CommandLine.cs
@@ -55,7 +55,9 @@ namespace WixToolset.Core.CommandLine
55 55
56 if (command.ShowLogo) 56 if (command.ShowLogo)
57 { 57 {
58 AppCommon.DisplayToolHeader(); 58 var branding = this.ServiceProvider.GetService<IWixBranding>();
59 Console.WriteLine(branding.ReplacePlaceholders("[AssemblyProduct] [AssemblyDescription] version [FileVersion]"));
60 Console.WriteLine(branding.ReplacePlaceholders("[AssemblyCopyright]"));
59 } 61 }
60 62
61 return command; 63 return command;
@@ -73,6 +75,7 @@ namespace WixToolset.Core.CommandLine
73 75
74 private ICommandLineCommand Parse(ICommandLineContext context) 76 private ICommandLineCommand Parse(ICommandLineContext context)
75 { 77 {
78 var branding = context.ServiceProvider.GetService<IWixBranding>();
76 var extensions = context.ExtensionManager.GetServices<IExtensionCommandLine>(); 79 var extensions = context.ExtensionManager.GetServices<IExtensionCommandLine>();
77 80
78 foreach (var extension in extensions) 81 foreach (var extension in extensions)
@@ -118,7 +121,7 @@ namespace WixToolset.Core.CommandLine
118 extension.PostParse(); 121 extension.PostParse();
119 } 122 }
120 123
121 return command ?? new HelpCommand(extensions); 124 return command ?? new HelpCommand(extensions, branding);
122 } 125 }
123 126
124 private bool TryParseCommand(string arg, ICommandLineParser parser, IEnumerable<IExtensionCommandLine> extensions, out ICommandLineCommand command) 127 private bool TryParseCommand(string arg, ICommandLineParser parser, IEnumerable<IExtensionCommandLine> extensions, out ICommandLineCommand command)
@@ -134,7 +137,8 @@ namespace WixToolset.Core.CommandLine
134 case "h": 137 case "h":
135 case "help": 138 case "help":
136 case "-help": 139 case "-help":
137 command = new HelpCommand(extensions); 140 var branding = this.ServiceProvider.GetService<IWixBranding>();
141 command = new HelpCommand(extensions, branding);
138 break; 142 break;
139 143
140 case "version": 144 case "version":
diff --git a/src/WixToolset.Core/CommandLine/HelpCommand.cs b/src/WixToolset.Core/CommandLine/HelpCommand.cs
index 3af442aa..6a5ac183 100644
--- a/src/WixToolset.Core/CommandLine/HelpCommand.cs
+++ b/src/WixToolset.Core/CommandLine/HelpCommand.cs
@@ -19,9 +19,10 @@ namespace WixToolset.Core.CommandLine
19 new ExtensionCommandLineSwitch { Switch = "decompile", Description = "Decompile a package or bundle into source code." }, 19 new ExtensionCommandLineSwitch { Switch = "decompile", Description = "Decompile a package or bundle into source code." },
20 }; 20 };
21 21
22 public HelpCommand(IEnumerable<IExtensionCommandLine> extensions) 22 public HelpCommand(IEnumerable<IExtensionCommandLine> extensions, IWixBranding branding)
23 { 23 {
24 this.Extensions = extensions; 24 this.Extensions = extensions;
25 this.Branding = branding;
25 } 26 }
26 27
27 public bool ShowLogo => true; 28 public bool ShowLogo => true;
@@ -30,6 +31,8 @@ namespace WixToolset.Core.CommandLine
30 31
31 private IEnumerable<IExtensionCommandLine> Extensions { get; } 32 private IEnumerable<IExtensionCommandLine> Extensions { get; }
32 33
34 private IWixBranding Branding { get; }
35
33 public Task<int> ExecuteAsync(CancellationToken _) 36 public Task<int> ExecuteAsync(CancellationToken _)
34 { 37 {
35 var commandLineSwitches = new List<ExtensionCommandLineSwitch>(BuiltInSwitches); 38 var commandLineSwitches = new List<ExtensionCommandLineSwitch>(BuiltInSwitches);
@@ -52,7 +55,8 @@ namespace WixToolset.Core.CommandLine
52 55
53 Console.WriteLine(); 56 Console.WriteLine();
54 Console.WriteLine("Run 'wix [command] --help' for more information on a command."); 57 Console.WriteLine("Run 'wix [command] --help' for more information on a command.");
55 AppCommon.DisplayToolFooter(); 58 Console.WriteLine();
59 Console.WriteLine(this.Branding.ReplacePlaceholders("For more information see: [SupportUrl]"));
56 60
57 return Task.FromResult(-1); 61 return Task.FromResult(-1);
58 } 62 }
diff --git a/src/WixToolset.Core/Common.cs b/src/WixToolset.Core/Common.cs
index 79f06135..848f009a 100644
--- a/src/WixToolset.Core/Common.cs
+++ b/src/WixToolset.Core/Common.cs
@@ -18,124 +18,35 @@ namespace WixToolset.Core
18 /// <summary> 18 /// <summary>
19 /// Common Wix utility methods and types. 19 /// Common Wix utility methods and types.
20 /// </summary> 20 /// </summary>
21 public static class Common 21 internal static class Common
22 { 22 {
23 // TODO: Find a place to put all of these so they doesn't have to be public and exposed by WixToolset.Core.dll 23 private static readonly char[] IllegalShortFilenameCharacters = new[] { '\\', '?', '|', '>', '<', ':', '/', '*', '\"', '+', ',', ';', '=', '[', ']', '.', ' ' };
24 /// <summary> 24 private static readonly char[] IllegalWildcardShortFilenameCharacters = new[] { '\\', '|', '>', '<', ':', '/', '\"', '+', ',', ';', '=', '[', ']', '.', ' ' };
25 ///
26 /// </summary>
27 public const string UpgradeDetectedProperty = "WIX_UPGRADE_DETECTED";
28 /// <summary>
29 ///
30 /// </summary>
31 public const string UpgradePreventedCondition = "NOT WIX_UPGRADE_DETECTED";
32 /// <summary>
33 ///
34 /// </summary>
35 public const string DowngradeDetectedProperty = "WIX_DOWNGRADE_DETECTED";
36 /// <summary>
37 ///
38 /// </summary>
39 public const string DowngradePreventedCondition = "NOT WIX_DOWNGRADE_DETECTED";
40
41 //-------------------------------------------------------------------------------------------------
42 // Layout of an Access Mask (from http://technet.microsoft.com/en-us/library/cc783530(WS.10).aspx)
43 //
44 // -------------------------------------------------------------------------------------------------
45 // |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
46 // -------------------------------------------------------------------------------------------------
47 // |GR|GW|GE|GA| Reserved |AS|StandardAccessRights| Object-Specific Access Rights |
48 //
49 // Key
50 // GR = Generic Read
51 // GW = Generic Write
52 // GE = Generic Execute
53 // GA = Generic All
54 // AS = Right to access SACL
55 //
56 // TODO: what is the expected decompile behavior if a bit is found that is not explicitly enumerated
57 //
58 //-------------------------------------------------------------------------------------------------
59 // Generic Access Rights (per WinNT.h)
60 // ---------------------
61 // GENERIC_ALL (0x10000000L)
62 // GENERIC_EXECUTE (0x20000000L)
63 // GENERIC_WRITE (0x40000000L)
64 // GENERIC_READ (0x80000000L)
65 // TODO: Find a place to put this that it doesn't have to be public and exposed by WixToolset.Core.dll
66 /// <summary>
67 ///
68 /// </summary>
69 public static readonly string[] GenericPermissions = { "GenericAll", "GenericExecute", "GenericWrite", "GenericRead" };
70
71 // Standard Access Rights (per WinNT.h)
72 // ----------------------
73 // DELETE (0x00010000L)
74 // READ_CONTROL (0x00020000L)
75 // WRITE_DAC (0x00040000L)
76 // WRITE_OWNER (0x00080000L)
77 // SYNCHRONIZE (0x00100000L)
78 // TODO: Find a place to put this that it doesn't have to be public and exposed by WixToolset.Core.dll
79 /// <summary>
80 ///
81 /// </summary>
82 public static readonly string[] StandardPermissions = { "Delete", "ReadPermission", "ChangePermission", "TakeOwnership", "Synchronize" };
83
84 // Object-Specific Access Rights
85 // =============================
86 // Directory Access Rights (per WinNT.h)
87 // -----------------------
88 // FILE_LIST_DIRECTORY ( 0x0001 )
89 // FILE_ADD_FILE ( 0x0002 )
90 // FILE_ADD_SUBDIRECTORY ( 0x0004 )
91 // FILE_READ_EA ( 0x0008 )
92 // FILE_WRITE_EA ( 0x0010 )
93 // FILE_TRAVERSE ( 0x0020 )
94 // FILE_DELETE_CHILD ( 0x0040 )
95 // FILE_READ_ATTRIBUTES ( 0x0080 )
96 // FILE_WRITE_ATTRIBUTES ( 0x0100 )
97 // TODO: Find a place to put this that it doesn't have to be public and exposed by WixToolset.Core.dll
98 /// <summary>
99 ///
100 /// </summary>
101 public static readonly string[] FolderPermissions = { "Read", "CreateFile", "CreateChild", "ReadExtendedAttributes", "WriteExtendedAttributes", "Traverse", "DeleteChild", "ReadAttributes", "WriteAttributes" };
102
103 // Registry Access Rights (per TODO)
104 // ----------------------
105 // TODO: Find a place to put this that it doesn't have to be public and exposed by WixToolset.Core.dll
106 /// <summary>
107 ///
108 /// </summary>
109 public static readonly string[] RegistryPermissions = { "Read", "Write", "CreateSubkeys", "EnumerateSubkeys", "Notify", "CreateLink" };
110
111 // File Access Rights (per WinNT.h)
112 // ------------------
113 // FILE_READ_DATA ( 0x0001 )
114 // FILE_WRITE_DATA ( 0x0002 )
115 // FILE_APPEND_DATA ( 0x0004 )
116 // FILE_READ_EA ( 0x0008 )
117 // FILE_WRITE_EA ( 0x0010 )
118 // FILE_EXECUTE ( 0x0020 )
119 // via mask FILE_ALL_ACCESS ( 0x0040 )
120 // FILE_READ_ATTRIBUTES ( 0x0080 )
121 // FILE_WRITE_ATTRIBUTES ( 0x0100 )
122 //
123 // STANDARD_RIGHTS_REQUIRED (0x000F0000L)
124 // FILE_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1FF)
125 // TODO: Find a place to put this that it doesn't have to be public and exposed by WixToolset.Core.dll
126 /// <summary>
127 ///
128 /// </summary>
129 public static readonly string[] FilePermissions = { "Read", "Write", "Append", "ReadExtendedAttributes", "WriteExtendedAttributes", "Execute", "FileAllRights", "ReadAttributes", "WriteAttributes" };
130 25
131 internal static readonly char[] IllegalLongFilenameCharacters = new[] { '\\', '/', '?', '*', '|', '>', '<', ':', '\"' }; // illegal: \ / ? | > < : / * " 26 internal static readonly char[] IllegalLongFilenameCharacters = new[] { '\\', '/', '?', '*', '|', '>', '<', ':', '\"' }; // illegal: \ / ? | > < : / * "
132 internal static readonly char[] IllegalRelativeLongFilenameCharacters = new[] { '?', '*', '|', '>', '<', ':', '\"' }; // like illegal, but we allow '\' and '/' 27 internal static readonly char[] IllegalRelativeLongFilenameCharacters = new[] { '?', '*', '|', '>', '<', ':', '\"' }; // like illegal, but we allow '\' and '/'
133 internal static readonly char[] IllegalWildcardLongFilenameCharacters = new[] { '\\', '/', '|', '>', '<', ':', '\"' }; // like illegal: but we allow '*' and '?' 28 internal static readonly char[] IllegalWildcardLongFilenameCharacters = new[] { '\\', '/', '|', '>', '<', ':', '\"' }; // like illegal: but we allow '*' and '?'
134 29
135 private static readonly char[] IllegalShortFilenameCharacters = new[] { '\\', '?', '|', '>', '<', ':', '/', '*', '\"', '+', ',', ';', '=', '[', ']', '.', ' ' }; 30 public static string GetCanonicalRelativePath(SourceLineNumber sourceLineNumbers, string elementName, string attributeName, string relativePath, IMessaging messageHandler)
136 private static readonly char[] IllegalWildcardShortFilenameCharacters = new[] { '\\', '|', '>', '<', ':', '/', '\"', '+', ',', ';', '=', '[', ']', '.', ' ' }; 31 {
137 32 const string root = @"C:\";
33 if (!Path.IsPathRooted(relativePath))
34 {
35 var normalizedPath = Path.GetFullPath(root + relativePath);
36 if (normalizedPath.StartsWith(root))
37 {
38 var canonicalizedPath = normalizedPath.Substring(root.Length);
39 if (canonicalizedPath != relativePath)
40 {
41 messageHandler.Write(WarningMessages.PathCanonicalized(sourceLineNumbers, elementName, attributeName, relativePath, canonicalizedPath));
42 }
43 return canonicalizedPath;
44 }
45 }
138 46
47 messageHandler.Write(ErrorMessages.PayloadMustBeRelativeToCache(sourceLineNumbers, elementName, attributeName, relativePath));
48 return relativePath;
49 }
139 50
140 /// <summary> 51 /// <summary>
141 /// Gets a valid code page from the given web name or integer value. 52 /// Gets a valid code page from the given web name or integer value.
@@ -157,8 +68,8 @@ namespace WixToolset.Core
157 { 68 {
158 Encoding encoding; 69 Encoding encoding;
159 70
160 // check if a integer as a string was passed 71 // Check if a integer as a string was passed.
161 if (Int32.TryParse(value, out int codePage)) 72 if (Int32.TryParse(value, out var codePage))
162 { 73 {
163 if (0 == codePage) 74 if (0 == codePage)
164 { 75 {
@@ -198,18 +109,91 @@ namespace WixToolset.Core
198 } 109 }
199 catch (ArgumentException ex) 110 catch (ArgumentException ex)
200 { 111 {
201 // rethrow as NotSupportedException since either can be thrown 112 // Rethrow as NotSupportedException since either can be thrown
202 // if the system does not support the specified code page 113 // if the system does not support the specified code page.
203 throw new NotSupportedException(ex.Message, ex); 114 throw new NotSupportedException(ex.Message, ex);
204 } 115 }
205 } 116 }
206 117
207 /// <summary> 118 /// <summary>
208 /// Verifies if a filename is a valid short filename. 119 /// Verifies if an identifier is a valid binder variable name.
120 /// </summary>
121 /// <param name="variable">Binder variable name to verify.</param>
122 /// <returns>True if the identifier is a valid binder variable name.</returns>
123 public static bool IsValidBinderVariable(string variable)
124 {
125 return TryParseWixVariable(variable, 0, out var parsed) && parsed.Index == 0 && parsed.Length == variable.Length && (parsed.Namespace == "bind" || parsed.Namespace == "wix");
126 }
127
128 /// <summary>
129 /// Verifies if a string contains a valid binder variable name.
130 /// </summary>
131 /// <param name="verify">String to verify.</param>
132 /// <returns>True if the string contains a valid binder variable name.</returns>
133 public static bool ContainsValidBinderVariable(string verify)
134 {
135 return TryParseWixVariable(verify, 0, out var parsed) && (parsed.Namespace == "bind" || parsed.Namespace == "wix");
136 }
137
138 /// <summary>
139 /// Verifies the given string is a valid 4-part version module or bundle version.
209 /// </summary> 140 /// </summary>
210 /// <param name="filename">Filename to verify.</param> 141 /// <param name="version">The version to verify.</param>
211 /// <param name="allowWildcards">true if wildcards are allowed in the filename.</param> 142 /// <returns>True if version is a valid module or bundle version.</returns>
212 /// <returns>True if the filename is a valid short filename</returns> 143 public static bool IsValidFourPartVersion(string version)
144 {
145 if (!Common.IsValidBinderVariable(version))
146 {
147 if (!Version.TryParse(version, out var ver) || 65535 < ver.Major || 65535 < ver.Minor || 65535 < ver.Build || 65535 < ver.Revision)
148 {
149 return false;
150 }
151 }
152
153 return true;
154 }
155
156 public static bool IsValidLongFilename(string filename, bool allowWildcards, bool allowRelative)
157 {
158 if (String.IsNullOrEmpty(filename))
159 {
160 return false;
161 }
162 else if (filename.Length > 259)
163 {
164 return false;
165 }
166
167 // Check for a non-period character (all periods is not legal)
168 var allPeriods = true;
169 foreach (var character in filename)
170 {
171 if ('.' != character)
172 {
173 allPeriods = false;
174 break;
175 }
176 }
177
178 if (allPeriods)
179 {
180 return false;
181 }
182
183 if (allowWildcards)
184 {
185 return filename.IndexOfAny(Common.IllegalWildcardLongFilenameCharacters) == -1;
186 }
187 else if (allowRelative)
188 {
189 return filename.IndexOfAny(Common.IllegalRelativeLongFilenameCharacters) == -1;
190 }
191 else
192 {
193 return filename.IndexOfAny(Common.IllegalLongFilenameCharacters) == -1;
194 }
195 }
196
213 public static bool IsValidShortFilename(string filename, bool allowWildcards) 197 public static bool IsValidShortFilename(string filename, bool allowWildcards)
214 { 198 {
215 if (String.IsNullOrEmpty(filename)) 199 if (String.IsNullOrEmpty(filename))
@@ -291,55 +275,6 @@ namespace WixToolset.Core
291 } 275 }
292 276
293 /// <summary> 277 /// <summary>
294 /// Verifies if an identifier is a valid binder variable name.
295 /// </summary>
296 /// <param name="variable">Binder variable name to verify.</param>
297 /// <returns>True if the identifier is a valid binder variable name.</returns>
298 public static bool IsValidBinderVariable(string variable)
299 {
300 return TryParseWixVariable(variable, 0, out var parsed) && parsed.Index == 0 && parsed.Length == variable.Length && (parsed.Namespace == "bind" || parsed.Namespace == "wix");
301 }
302
303 /// <summary>
304 /// Verifies if a string contains a valid binder variable name.
305 /// </summary>
306 /// <param name="verify">String to verify.</param>
307 /// <returns>True if the string contains a valid binder variable name.</returns>
308 public static bool ContainsValidBinderVariable(string verify)
309 {
310 return TryParseWixVariable(verify, 0, out var parsed) && (parsed.Namespace == "bind" || parsed.Namespace == "wix");
311 }
312
313 /// <summary>
314 /// Verifies the given string is a valid module or bundle version.
315 /// </summary>
316 /// <param name="version">The version to verify.</param>
317 /// <returns>True if version is a valid module or bundle version.</returns>
318 public static bool IsValidModuleOrBundleVersion(string version)
319 {
320 if (!Common.IsValidBinderVariable(version))
321 {
322 Version ver;
323
324 try
325 {
326 ver = new Version(version);
327 }
328 catch (ArgumentException)
329 {
330 return false;
331 }
332
333 if (65535 < ver.Major || 65535 < ver.Minor || 65535 < ver.Build || 65535 < ver.Revision)
334 {
335 return false;
336 }
337 }
338
339 return true;
340 }
341
342 /// <summary>
343 /// Generate a new Windows Installer-friendly guid. 278 /// Generate a new Windows Installer-friendly guid.
344 /// </summary> 279 /// </summary>
345 /// <returns>A new guid.</returns> 280 /// <returns>A new guid.</returns>
@@ -451,14 +386,14 @@ namespace WixToolset.Core
451 /// <param name="markAttribute">If true, add the attribute to each file. If false, remove it.</param> 386 /// <param name="markAttribute">If true, add the attribute to each file. If false, remove it.</param>
452 private static void RecursiveFileAttributes(string path, FileAttributes fileAttribute, bool markAttribute, IMessaging messageHandler) 387 private static void RecursiveFileAttributes(string path, FileAttributes fileAttribute, bool markAttribute, IMessaging messageHandler)
453 { 388 {
454 foreach (string subDirectory in Directory.GetDirectories(path)) 389 foreach (var subDirectory in Directory.GetDirectories(path))
455 { 390 {
456 RecursiveFileAttributes(subDirectory, fileAttribute, markAttribute, messageHandler); 391 RecursiveFileAttributes(subDirectory, fileAttribute, markAttribute, messageHandler);
457 } 392 }
458 393
459 foreach (string filePath in Directory.GetFiles(path)) 394 foreach (var filePath in Directory.GetFiles(path))
460 { 395 {
461 FileAttributes attributes = File.GetAttributes(filePath); 396 var attributes = File.GetAttributes(filePath);
462 if (markAttribute) 397 if (markAttribute)
463 { 398 {
464 attributes = attributes | fileAttribute; // add to list of attributes 399 attributes = attributes | fileAttribute; // add to list of attributes
@@ -506,16 +441,15 @@ namespace WixToolset.Core
506 /// <returns>An array of strings of length 4. The contents are: short target, long target, short source, and long source.</returns> 441 /// <returns>An array of strings of length 4. The contents are: short target, long target, short source, and long source.</returns>
507 /// <remarks> 442 /// <remarks>
508 /// If any particular file name part is not parsed, its set to null in the appropriate location of the returned array of strings. 443 /// If any particular file name part is not parsed, its set to null in the appropriate location of the returned array of strings.
509 /// However, the returned array will always be of length 4. 444 /// Thus the returned array will always be of length 4.
510 /// </remarks> 445 /// </remarks>
511 public static string[] GetNames(string value) 446 public static string[] GetNames(string value)
512 { 447 {
513 string[] names = new string[4]; 448 var targetSeparator = value.IndexOf(':');
514 int targetSeparator = value.IndexOf(':');
515 449
516 // split source and target 450 // split source and target
517 string sourceName = null; 451 string sourceName = null;
518 string targetName = value; 452 var targetName = value;
519 if (0 <= targetSeparator) 453 if (0 <= targetSeparator)
520 { 454 {
521 sourceName = value.Substring(targetSeparator + 1); 455 sourceName = value.Substring(targetSeparator + 1);
@@ -526,7 +460,7 @@ namespace WixToolset.Core
526 string sourceLongName = null; 460 string sourceLongName = null;
527 if (null != sourceName) 461 if (null != sourceName)
528 { 462 {
529 int sourceLongNameSeparator = sourceName.IndexOf('|'); 463 var sourceLongNameSeparator = sourceName.IndexOf('|');
530 if (0 <= sourceLongNameSeparator) 464 if (0 <= sourceLongNameSeparator)
531 { 465 {
532 sourceLongName = sourceName.Substring(sourceLongNameSeparator + 1); 466 sourceLongName = sourceName.Substring(sourceLongNameSeparator + 1);
@@ -535,7 +469,7 @@ namespace WixToolset.Core
535 } 469 }
536 470
537 // split the target short and long names 471 // split the target short and long names
538 int targetLongNameSeparator = targetName.IndexOf('|'); 472 var targetLongNameSeparator = targetName.IndexOf('|');
539 string targetLongName = null; 473 string targetLongName = null;
540 if (0 <= targetLongNameSeparator) 474 if (0 <= targetLongNameSeparator)
541 { 475 {
@@ -543,19 +477,19 @@ namespace WixToolset.Core
543 targetName = targetName.Substring(0, targetLongNameSeparator); 477 targetName = targetName.Substring(0, targetLongNameSeparator);
544 } 478 }
545 479
546 // remove the long source name when its identical to the long source name 480 // Remove the long source name when its identical to the short source name.
547 if (null != sourceName && sourceName == sourceLongName) 481 if (null != sourceName && sourceName == sourceLongName)
548 { 482 {
549 sourceLongName = null; 483 sourceLongName = null;
550 } 484 }
551 485
552 // remove the long target name when its identical to the long target name 486 // Remove the long target name when its identical to the long target name.
553 if (null != targetName && targetName == targetLongName) 487 if (null != targetName && targetName == targetLongName)
554 { 488 {
555 targetLongName = null; 489 targetLongName = null;
556 } 490 }
557 491
558 // remove the source names when they are identical to the target names 492 // Remove the source names when they are identical to the target names.
559 if (sourceName == targetName && sourceLongName == targetLongName) 493 if (sourceName == targetName && sourceLongName == targetLongName)
560 { 494 {
561 sourceName = null; 495 sourceName = null;
@@ -563,28 +497,28 @@ namespace WixToolset.Core
563 } 497 }
564 498
565 // target name(s) 499 // target name(s)
566 if ("." != targetName) 500 if ("." == targetName)
567 { 501 {
568 names[0] = targetName; 502 targetName = null;
569 } 503 }
570 504
571 if (null != targetLongName && "." != targetLongName) 505 if ("." == targetLongName)
572 { 506 {
573 names[1] = targetLongName; 507 targetLongName = null;
574 } 508 }
575 509
576 // source name(s) 510 // source name(s)
577 if (null != sourceName) 511 if ("." == sourceName)
578 { 512 {
579 names[2] = sourceName; 513 sourceName = null;
580 } 514 }
581 515
582 if (null != sourceLongName && "." != sourceLongName) 516 if ("." == sourceLongName)
583 { 517 {
584 names[3] = sourceLongName; 518 sourceLongName = null;
585 } 519 }
586 520
587 return names; 521 return new[] { targetName, targetLongName, sourceName, sourceLongName };
588 } 522 }
589 523
590 /// <summary> 524 /// <summary>
@@ -596,7 +530,7 @@ namespace WixToolset.Core
596 /// <returns>The name.</returns> 530 /// <returns>The name.</returns>
597 public static string GetName(string value, bool source, bool longName) 531 public static string GetName(string value, bool source, bool longName)
598 { 532 {
599 string[] names = GetNames(value); 533 var names = GetNames(value);
600 534
601 if (source) 535 if (source)
602 { 536 {
@@ -674,7 +608,7 @@ namespace WixToolset.Core
674 /// <returns>The attribute's identifier value or a special value if an error occurred.</returns> 608 /// <returns>The attribute's identifier value or a special value if an error occurred.</returns>
675 internal static string GetAttributeIdentifierValue(IMessaging messaging, SourceLineNumber sourceLineNumbers, XAttribute attribute) 609 internal static string GetAttributeIdentifierValue(IMessaging messaging, SourceLineNumber sourceLineNumbers, XAttribute attribute)
676 { 610 {
677 string value = Common.GetAttributeValue(messaging, sourceLineNumbers, attribute, EmptyRule.CanBeWhitespaceOnly); 611 var value = Common.GetAttributeValue(messaging, sourceLineNumbers, attribute, EmptyRule.CanBeWhitespaceOnly);
678 612
679 if (Common.IsIdentifier(value)) 613 if (Common.IsIdentifier(value))
680 { 614 {
@@ -713,8 +647,8 @@ namespace WixToolset.Core
713 { 647 {
714 Debug.Assert(minimum > CompilerConstants.IntegerNotSet && minimum > CompilerConstants.IllegalInteger, "The legal values for this attribute collide with at least one sentinel used during parsing."); 648 Debug.Assert(minimum > CompilerConstants.IntegerNotSet && minimum > CompilerConstants.IllegalInteger, "The legal values for this attribute collide with at least one sentinel used during parsing.");
715 649
716 string value = Common.GetAttributeValue(messaging, sourceLineNumbers, attribute, EmptyRule.CanBeWhitespaceOnly); 650 var value = Common.GetAttributeValue(messaging, sourceLineNumbers, attribute, EmptyRule.CanBeWhitespaceOnly);
717 int integer = CompilerConstants.IllegalInteger; 651 var integer = CompilerConstants.IllegalInteger;
718 652
719 if (0 < value.Length) 653 if (0 < value.Length)
720 { 654 {
@@ -748,8 +682,8 @@ namespace WixToolset.Core
748 /// <returns>The attribute's YesNoType value.</returns> 682 /// <returns>The attribute's YesNoType value.</returns>
749 internal static YesNoType GetAttributeYesNoValue(IMessaging messaging, SourceLineNumber sourceLineNumbers, XAttribute attribute) 683 internal static YesNoType GetAttributeYesNoValue(IMessaging messaging, SourceLineNumber sourceLineNumbers, XAttribute attribute)
750 { 684 {
751 string value = Common.GetAttributeValue(messaging, sourceLineNumbers, attribute, EmptyRule.CanBeWhitespaceOnly); 685 var value = Common.GetAttributeValue(messaging, sourceLineNumbers, attribute, EmptyRule.CanBeWhitespaceOnly);
752 YesNoType yesNo = YesNoType.IllegalValue; 686 var yesNo = YesNoType.IllegalValue;
753 687
754 if ("yes".Equals(value) || "true".Equals(value)) 688 if ("yes".Equals(value) || "true".Equals(value))
755 { 689 {
diff --git a/src/WixToolset.Core/Compiler.cs b/src/WixToolset.Core/Compiler.cs
index f311a5f6..2aa25141 100644
--- a/src/WixToolset.Core/Compiler.cs
+++ b/src/WixToolset.Core/Compiler.cs
@@ -7073,7 +7073,7 @@ namespace WixToolset.Core
7073 Remove = removeFeatures, 7073 Remove = removeFeatures,
7074 MigrateFeatures = migrateFeatures, 7074 MigrateFeatures = migrateFeatures,
7075 IgnoreRemoveFailures = ignoreRemoveFailure, 7075 IgnoreRemoveFailures = ignoreRemoveFailure,
7076 ActionProperty = Common.UpgradeDetectedProperty 7076 ActionProperty = WixUpgradeConstants.UpgradeDetectedProperty
7077 }); 7077 });
7078 7078
7079 if (allowDowngrades) 7079 if (allowDowngrades)
@@ -7094,7 +7094,7 @@ namespace WixToolset.Core
7094 { 7094 {
7095 this.Core.AddSymbol(new LaunchConditionSymbol(sourceLineNumbers) 7095 this.Core.AddSymbol(new LaunchConditionSymbol(sourceLineNumbers)
7096 { 7096 {
7097 Condition = Common.UpgradePreventedCondition, 7097 Condition = WixUpgradeConstants.UpgradePreventedCondition,
7098 Description = downgradeErrorMessage 7098 Description = downgradeErrorMessage
7099 }); 7099 });
7100 } 7100 }
@@ -7109,12 +7109,12 @@ namespace WixToolset.Core
7109 Language = productLanguage, 7109 Language = productLanguage,
7110 OnlyDetect = true, 7110 OnlyDetect = true,
7111 IgnoreRemoveFailures = ignoreRemoveFailure, 7111 IgnoreRemoveFailures = ignoreRemoveFailure,
7112 ActionProperty = Common.DowngradeDetectedProperty 7112 ActionProperty = WixUpgradeConstants.DowngradeDetectedProperty
7113 }); 7113 });
7114 7114
7115 this.Core.AddSymbol(new LaunchConditionSymbol(sourceLineNumbers) 7115 this.Core.AddSymbol(new LaunchConditionSymbol(sourceLineNumbers)
7116 { 7116 {
7117 Condition = Common.DowngradePreventedCondition, 7117 Condition = WixUpgradeConstants.DowngradePreventedCondition,
7118 Description = downgradeErrorMessage 7118 Description = downgradeErrorMessage
7119 }); 7119 });
7120 } 7120 }
diff --git a/src/WixToolset.Core/CompilerCore.cs b/src/WixToolset.Core/CompilerCore.cs
index cfe3082e..ec22a8ec 100644
--- a/src/WixToolset.Core/CompilerCore.cs
+++ b/src/WixToolset.Core/CompilerCore.cs
@@ -297,20 +297,6 @@ namespace WixToolset.Core
297 } 297 }
298 298
299 /// <summary> 299 /// <summary>
300 /// Creates a short file/directory name using an identifier and long file/directory name as input.
301 /// </summary>
302 /// <param name="longName">The long file/directory name.</param>
303 /// <param name="keepExtension">The option to keep the extension on generated short names.</param>
304 /// <param name="allowWildcards">true if wildcards are allowed in the filename.</param>
305 /// <param name="args">Any additional information to include in the hash for the generated short name.</param>
306 /// <returns>The generated 8.3-compliant short file/directory name.</returns>
307 [Obsolete]
308 public string CreateShortName(string longName, bool keepExtension, bool allowWildcards, params string[] args)
309 {
310 return this.parseHelper.CreateShortName(longName, keepExtension, allowWildcards, args);
311 }
312
313 /// <summary>
314 /// Verifies the given string is a valid product version. 300 /// Verifies the given string is a valid product version.
315 /// </summary> 301 /// </summary>
316 /// <param name="version">The product version to verify.</param> 302 /// <param name="version">The product version to verify.</param>
@@ -337,7 +323,7 @@ namespace WixToolset.Core
337 /// <returns>True if version is a valid module or bundle version.</returns> 323 /// <returns>True if version is a valid module or bundle version.</returns>
338 public static bool IsValidModuleOrBundleVersion(string version) 324 public static bool IsValidModuleOrBundleVersion(string version)
339 { 325 {
340 return Common.IsValidModuleOrBundleVersion(version); 326 return Common.IsValidFourPartVersion(version);
341 } 327 }
342 328
343 /// <summary> 329 /// <summary>
@@ -547,15 +533,14 @@ namespace WixToolset.Core
547 { 533 {
548 if (null == attribute) 534 if (null == attribute)
549 { 535 {
550 throw new ArgumentNullException("attribute"); 536 throw new ArgumentNullException(nameof(attribute));
551 } 537 }
552 538
553 string value = this.GetAttributeValue(sourceLineNumbers, attribute); 539 var value = this.GetAttributeValue(sourceLineNumbers, attribute);
554 540
555 try 541 try
556 { 542 {
557 int codePage = Common.GetValidCodePage(value); 543 return Common.GetValidCodePage(value);
558 return codePage;
559 } 544 }
560 catch (NotSupportedException) 545 catch (NotSupportedException)
561 { 546 {
@@ -576,12 +561,12 @@ namespace WixToolset.Core
576 { 561 {
577 if (null == attribute) 562 if (null == attribute)
578 { 563 {
579 throw new ArgumentNullException("attribute"); 564 throw new ArgumentNullException(nameof(attribute));
580 } 565 }
581 566
582 string value = this.GetAttributeValue(sourceLineNumbers, attribute); 567 var value = this.GetAttributeValue(sourceLineNumbers, attribute);
583 568
584 // allow for localization of code page names and values 569 // Allow for localization of code page names and values.
585 if (this.IsValidLocIdentifier(value)) 570 if (this.IsValidLocIdentifier(value))
586 { 571 {
587 return value; 572 return value;
@@ -589,13 +574,13 @@ namespace WixToolset.Core
589 574
590 try 575 try
591 { 576 {
592 int codePage = Common.GetValidCodePage(value, false, onlyAnsi, sourceLineNumbers); 577 var codePage = Common.GetValidCodePage(value, false, onlyAnsi, sourceLineNumbers);
593 return codePage.ToString(CultureInfo.InvariantCulture); 578 return codePage.ToString(CultureInfo.InvariantCulture);
594 } 579 }
595 catch (NotSupportedException) 580 catch (NotSupportedException)
596 { 581 {
597 // not a valid windows code page 582 // Not a valid windows code page.
598 this.Write(ErrorMessages.IllegalCodepageAttribute(sourceLineNumbers, value, attribute.Parent.Name.LocalName, attribute.Name.LocalName)); 583 this.messaging.Write(ErrorMessages.IllegalCodepageAttribute(sourceLineNumbers, value, attribute.Parent.Name.LocalName, attribute.Name.LocalName));
599 } 584 }
600 catch (WixException e) 585 catch (WixException e)
601 { 586 {
@@ -805,7 +790,7 @@ namespace WixToolset.Core
805 790
806 if (0 < value.Length) 791 if (0 < value.Length)
807 { 792 {
808 if (!this.IsValidShortFilename(value, allowWildcards) && !Common.ContainsValidBinderVariable(value)) 793 if (!this.parseHelper.IsValidShortFilename(value, allowWildcards) && !Common.ContainsValidBinderVariable(value))
809 { 794 {
810 this.Write(ErrorMessages.IllegalShortFilename(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value)); 795 this.Write(ErrorMessages.IllegalShortFilename(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value));
811 } 796 }
diff --git a/src/WixToolset.Core/Compiler_Package.cs b/src/WixToolset.Core/Compiler_Package.cs
index 03ba1c40..1dac5399 100644
--- a/src/WixToolset.Core/Compiler_Package.cs
+++ b/src/WixToolset.Core/Compiler_Package.cs
@@ -1024,13 +1024,13 @@ namespace WixToolset.Core
1024 switch (tableName) 1024 switch (tableName)
1025 { 1025 {
1026 case "CreateFolder": 1026 case "CreateFolder":
1027 specialPermissions = Common.FolderPermissions; 1027 specialPermissions = LockPermissionConstants.FolderPermissions;
1028 break; 1028 break;
1029 case "File": 1029 case "File":
1030 specialPermissions = Common.FilePermissions; 1030 specialPermissions = LockPermissionConstants.FilePermissions;
1031 break; 1031 break;
1032 case "Registry": 1032 case "Registry":
1033 specialPermissions = Common.RegistryPermissions; 1033 specialPermissions = LockPermissionConstants.RegistryPermissions;
1034 break; 1034 break;
1035 default: 1035 default:
1036 this.Core.UnexpectedElement(node.Parent, node); 1036 this.Core.UnexpectedElement(node.Parent, node);
@@ -1059,9 +1059,9 @@ namespace WixToolset.Core
1059 break; 1059 break;
1060 default: 1060 default:
1061 var attribValue = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); 1061 var attribValue = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
1062 if (!this.Core.TrySetBitFromName(Common.StandardPermissions, attrib.Name.LocalName, attribValue, bits, 16)) 1062 if (!this.Core.TrySetBitFromName(LockPermissionConstants.StandardPermissions, attrib.Name.LocalName, attribValue, bits, 16))
1063 { 1063 {
1064 if (!this.Core.TrySetBitFromName(Common.GenericPermissions, attrib.Name.LocalName, attribValue, bits, 28)) 1064 if (!this.Core.TrySetBitFromName(LockPermissionConstants.GenericPermissions, attrib.Name.LocalName, attribValue, bits, 28))
1065 { 1065 {
1066 if (!this.Core.TrySetBitFromName(specialPermissions, attrib.Name.LocalName, attribValue, bits, 0)) 1066 if (!this.Core.TrySetBitFromName(specialPermissions, attrib.Name.LocalName, attribValue, bits, 0))
1067 { 1067 {
diff --git a/src/WixToolset.Core/Compiler_Patch.cs b/src/WixToolset.Core/Compiler_Patch.cs
index 998894d8..a2cadd67 100644
--- a/src/WixToolset.Core/Compiler_Patch.cs
+++ b/src/WixToolset.Core/Compiler_Patch.cs
@@ -95,13 +95,13 @@ namespace WixToolset.Core
95 targetProductName = this.Core.GetAttributeValue(sourceLineNumbers, attrib); 95 targetProductName = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
96 break; 96 break;
97 case "ApiPatchingSymbolNoImagehlpFlag": 97 case "ApiPatchingSymbolNoImagehlpFlag":
98 apiPatchingSymbolFlags |= (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) ? (int)PatchSymbolFlagsType.PATCH_SYMBOL_NO_IMAGEHLP : 0; 98 apiPatchingSymbolFlags |= (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) ? (int)PatchSymbolFlags.PatchSymbolNoImagehlp : 0;
99 break; 99 break;
100 case "ApiPatchingSymbolNoFailuresFlag": 100 case "ApiPatchingSymbolNoFailuresFlag":
101 apiPatchingSymbolFlags |= (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) ? (int)PatchSymbolFlagsType.PATCH_SYMBOL_NO_FAILURES : 0; 101 apiPatchingSymbolFlags |= (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) ? (int)PatchSymbolFlags.PatchSymbolNoFailures : 0;
102 break; 102 break;
103 case "ApiPatchingSymbolUndecoratedTooFlag": 103 case "ApiPatchingSymbolUndecoratedTooFlag":
104 apiPatchingSymbolFlags |= (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) ? (int)PatchSymbolFlagsType.PATCH_SYMBOL_UNDECORATED_TOO : 0; 104 apiPatchingSymbolFlags |= (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) ? (int)PatchSymbolFlags.PatchSymbolUndecoratedToo : 0;
105 break; 105 break;
106 case "OptimizePatchSizeForLargeFiles": 106 case "OptimizePatchSizeForLargeFiles":
107 optimizePatchSizeForLargeFiles = (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)); 107 optimizePatchSizeForLargeFiles = (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib));
@@ -275,7 +275,7 @@ namespace WixToolset.Core
275 private int ParseOptimizeCustomActionsElement(XElement node) 275 private int ParseOptimizeCustomActionsElement(XElement node)
276 { 276 {
277 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); 277 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
278 var optimizeCA = OptimizeCA.None; 278 var optimizeCA = OptimizeCAFlags.None;
279 279
280 foreach (var attrib in node.Attributes()) 280 foreach (var attrib in node.Attributes())
281 { 281 {
@@ -286,19 +286,19 @@ namespace WixToolset.Core
286 case "SkipAssignment": 286 case "SkipAssignment":
287 if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) 287 if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
288 { 288 {
289 optimizeCA |= OptimizeCA.SkipAssignment; 289 optimizeCA |= OptimizeCAFlags.SkipAssignment;
290 } 290 }
291 break; 291 break;
292 case "SkipImmediate": 292 case "SkipImmediate":
293 if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) 293 if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
294 { 294 {
295 optimizeCA |= OptimizeCA.SkipImmediate; 295 optimizeCA |= OptimizeCAFlags.SkipImmediate;
296 } 296 }
297 break; 297 break;
298 case "SkipDeferred": 298 case "SkipDeferred":
299 if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) 299 if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
300 { 300 {
301 optimizeCA |= OptimizeCA.SkipDeferred; 301 optimizeCA |= OptimizeCAFlags.SkipDeferred;
302 } 302 }
303 break; 303 break;
304 default: 304 default:
diff --git a/src/WixToolset.Core/ExtensibilityServices/BackendHelper.cs b/src/WixToolset.Core/ExtensibilityServices/BackendHelper.cs
index 7b20286c..3dcc0ce9 100644
--- a/src/WixToolset.Core/ExtensibilityServices/BackendHelper.cs
+++ b/src/WixToolset.Core/ExtensibilityServices/BackendHelper.cs
@@ -3,8 +3,12 @@
3namespace WixToolset.Core.ExtensibilityServices 3namespace WixToolset.Core.ExtensibilityServices
4{ 4{
5 using System; 5 using System;
6 using System.Collections.Generic;
6 using System.IO; 7 using System.IO;
8 using WixToolset.Core.Bind;
7 using WixToolset.Data; 9 using WixToolset.Data;
10 using WixToolset.Data.Symbols;
11 using WixToolset.Data.WindowsInstaller.Rows;
8 using WixToolset.Extensibility.Data; 12 using WixToolset.Extensibility.Data;
9 using WixToolset.Extensibility.Services; 13 using WixToolset.Extensibility.Services;
10 14
@@ -15,12 +19,24 @@ namespace WixToolset.Core.ExtensibilityServices
15 public BackendHelper(IWixToolsetServiceProvider serviceProvider) 19 public BackendHelper(IWixToolsetServiceProvider serviceProvider)
16 { 20 {
17 this.Messaging = serviceProvider.GetService<IMessaging>(); 21 this.Messaging = serviceProvider.GetService<IMessaging>();
18 this.ParseHelper = serviceProvider.GetService<IParseHelper>();
19 } 22 }
20 23
21 private IMessaging Messaging { get; } 24 private IMessaging Messaging { get; }
22 25
23 private IParseHelper ParseHelper { get; } 26 public IFileFacade CreateFileFacade(FileSymbol file, AssemblySymbol assembly)
27 {
28 return new FileFacade(file, assembly);
29 }
30
31 public IFileFacade CreateFileFacade(FileRow fileRow)
32 {
33 return new FileFacade(fileRow);
34 }
35
36 public IFileFacade CreateFileFacadeFromMergeModule(FileSymbol fileSymbol)
37 {
38 return new FileFacade(true, fileSymbol);
39 }
24 40
25 public IFileTransfer CreateFileTransfer(string source, string destination, bool move, SourceLineNumber sourceLineNumbers = null) 41 public IFileTransfer CreateFileTransfer(string source, string destination, bool move, SourceLineNumber sourceLineNumbers = null)
26 { 42 {
@@ -38,6 +54,11 @@ namespace WixToolset.Core.ExtensibilityServices
38 }; 54 };
39 } 55 }
40 56
57 public string CreateGuid()
58 {
59 return Common.GenerateGuid();
60 }
61
41 public string CreateGuid(Guid namespaceGuid, string value) 62 public string CreateGuid(Guid namespaceGuid, string value)
42 { 63 {
43 return Uuid.NewUuid(namespaceGuid, value).ToString("B").ToUpperInvariant(); 64 return Uuid.NewUuid(namespaceGuid, value).ToString("B").ToUpperInvariant();
@@ -52,9 +73,43 @@ namespace WixToolset.Core.ExtensibilityServices
52 }; 73 };
53 } 74 }
54 75
76 public IEnumerable<ITrackedFile> ExtractEmbeddedFiles(IEnumerable<IExpectedExtractFile> embeddedFiles)
77 {
78 var command = new ExtractEmbeddedFilesCommand(this, embeddedFiles);
79 command.Execute();
80
81 return command.TrackedFiles;
82 }
83
84 public string GenerateIdentifier(string prefix, params string[] args)
85 {
86 return Common.GenerateIdentifier(prefix, args);
87 }
88
55 public string GetCanonicalRelativePath(SourceLineNumber sourceLineNumbers, string elementName, string attributeName, string relativePath) 89 public string GetCanonicalRelativePath(SourceLineNumber sourceLineNumbers, string elementName, string attributeName, string relativePath)
56 { 90 {
57 return this.ParseHelper.GetCanonicalRelativePath(sourceLineNumbers, elementName, attributeName, relativePath); 91 return Common.GetCanonicalRelativePath(sourceLineNumbers, elementName, attributeName, relativePath, this.Messaging);
92 }
93
94 public int GetValidCodePage(string value, bool allowNoChange = false, bool onlyAnsi = false, SourceLineNumber sourceLineNumbers = null)
95 {
96 return Common.GetValidCodePage(value, allowNoChange, onlyAnsi, sourceLineNumbers);
97 }
98
99 public string GetMsiFileName(string value, bool source, bool longName)
100 {
101 return Common.GetName(value, source, longName);
102 }
103
104 public void ResolveDelayedFields(IEnumerable<IDelayedField> delayedFields, Dictionary<string, string> variableCache)
105 {
106 var command = new ResolveDelayedFieldsCommand(this.Messaging, delayedFields, variableCache);
107 command.Execute();
108 }
109
110 public string[] SplitMsiFileName(string value)
111 {
112 return Common.GetNames(value);
58 } 113 }
59 114
60 public ITrackedFile TrackFile(string path, TrackedFileType type, SourceLineNumber sourceLineNumbers = null) 115 public ITrackedFile TrackFile(string path, TrackedFileType type, SourceLineNumber sourceLineNumbers = null)
@@ -62,6 +117,31 @@ namespace WixToolset.Core.ExtensibilityServices
62 return new TrackedFile(path, type, sourceLineNumbers); 117 return new TrackedFile(path, type, sourceLineNumbers);
63 } 118 }
64 119
120 public bool IsValidBinderVariable(string variable)
121 {
122 return Common.IsValidBinderVariable(variable);
123 }
124
125 public bool IsValidFourPartVersion(string version)
126 {
127 return Common.IsValidFourPartVersion(version);
128 }
129
130 public bool IsValidIdentifier(string id)
131 {
132 return Common.IsIdentifier(id);
133 }
134
135 public bool IsValidLongFilename(string filename, bool allowWildcards, bool allowRelative)
136 {
137 return Common.IsValidLongFilename(filename, allowWildcards, allowRelative);
138 }
139
140 public bool IsValidShortFilename(string filename, bool allowWildcards)
141 {
142 return Common.IsValidShortFilename(filename, allowWildcards);
143 }
144
65 private string GetValidatedFullPath(SourceLineNumber sourceLineNumbers, string path) 145 private string GetValidatedFullPath(SourceLineNumber sourceLineNumbers, string path)
66 { 146 {
67 try 147 try
diff --git a/src/WixToolset.Core/Bind/FileFacade.cs b/src/WixToolset.Core/ExtensibilityServices/FileFacade.cs
index d1e5ae60..f85d4842 100644
--- a/src/WixToolset.Core/Bind/FileFacade.cs
+++ b/src/WixToolset.Core/ExtensibilityServices/FileFacade.cs
@@ -1,6 +1,6 @@
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
3namespace WixToolset.Core.Bind 3namespace WixToolset.Core.ExtensibilityServices
4{ 4{
5 using System; 5 using System;
6 using System.Collections.Generic; 6 using System.Collections.Generic;
@@ -8,9 +8,9 @@ namespace WixToolset.Core.Bind
8 using WixToolset.Data.Symbols; 8 using WixToolset.Data.Symbols;
9 using WixToolset.Data.WindowsInstaller; 9 using WixToolset.Data.WindowsInstaller;
10 using WixToolset.Data.WindowsInstaller.Rows; 10 using WixToolset.Data.WindowsInstaller.Rows;
11 using WixToolset.Extensibility.Data;
11 12
12#pragma warning disable 1591 // TODO: this shouldn't be public, need interface in Extensibility 13 internal class FileFacade : IFileFacade
13 public class FileFacade
14 { 14 {
15 public FileFacade(FileSymbol file, AssemblySymbol assembly) 15 public FileFacade(FileSymbol file, AssemblySymbol assembly)
16 { 16 {
diff --git a/src/WixToolset.Core/ExtensibilityServices/ParseHelper.cs b/src/WixToolset.Core/ExtensibilityServices/ParseHelper.cs
index 7894ce8e..3c040b35 100644
--- a/src/WixToolset.Core/ExtensibilityServices/ParseHelper.cs
+++ b/src/WixToolset.Core/ExtensibilityServices/ParseHelper.cs
@@ -6,9 +6,6 @@ namespace WixToolset.Core.ExtensibilityServices
6 using System.Collections.Generic; 6 using System.Collections.Generic;
7 using System.Diagnostics; 7 using System.Diagnostics;
8 using System.Globalization; 8 using System.Globalization;
9 using System.IO;
10 using System.Security.Cryptography;
11 using System.Text;
12 using System.Xml.Linq; 9 using System.Xml.Linq;
13 using WixToolset.Data; 10 using WixToolset.Data;
14 using WixToolset.Data.Symbols; 11 using WixToolset.Data.Symbols;
@@ -292,56 +289,6 @@ namespace WixToolset.Core.ExtensibilityServices
292 return section.AddSymbol(symbolDefinition.CreateSymbol(sourceLineNumbers, identifier)); 289 return section.AddSymbol(symbolDefinition.CreateSymbol(sourceLineNumbers, identifier));
293 } 290 }
294 291
295 public string CreateShortName(string longName, bool keepExtension, bool allowWildcards, params string[] args)
296 {
297 // canonicalize the long name if its not a localization identifier (they are case-sensitive)
298 if (!this.IsValidLocIdentifier(longName))
299 {
300 longName = longName.ToLowerInvariant();
301 }
302
303 // collect all the data
304 var strings = new List<string>(1 + args.Length);
305 strings.Add(longName);
306 strings.AddRange(args);
307
308 // prepare for hashing
309 var stringData = String.Join("|", strings);
310 var data = Encoding.UTF8.GetBytes(stringData);
311
312 // hash the data
313 byte[] hash;
314 using (var sha1 = new SHA1CryptoServiceProvider())
315 {
316 hash = sha1.ComputeHash(data);
317 }
318
319 // generate the short file/directory name without an extension
320 var shortName = new StringBuilder(Convert.ToBase64String(hash));
321 shortName.Remove(8, shortName.Length - 8).Replace('+', '-').Replace('/', '_');
322
323 if (keepExtension)
324 {
325 var extension = Path.GetExtension(longName);
326
327 if (4 < extension.Length)
328 {
329 extension = extension.Substring(0, 4);
330 }
331
332 shortName.Append(extension);
333
334 // check the generated short name to ensure its still legal (the extension may not be legal)
335 if (!this.IsValidShortFilename(shortName.ToString(), allowWildcards))
336 {
337 // remove the extension (by truncating the generated file name back to the generated characters)
338 shortName.Length -= extension.Length;
339 }
340 }
341
342 return shortName.ToString().ToLowerInvariant();
343 }
344
345 public void EnsureTable(IntermediateSection section, SourceLineNumber sourceLineNumbers, TableDefinition tableDefinition) 292 public void EnsureTable(IntermediateSection section, SourceLineNumber sourceLineNumbers, TableDefinition tableDefinition)
346 { 293 {
347 section.AddSymbol(new WixEnsureTableSymbol(sourceLineNumbers) 294 section.AddSymbol(new WixEnsureTableSymbol(sourceLineNumbers)
@@ -673,23 +620,7 @@ namespace WixToolset.Core.ExtensibilityServices
673 620
674 public string GetCanonicalRelativePath(SourceLineNumber sourceLineNumbers, string elementName, string attributeName, string relativePath) 621 public string GetCanonicalRelativePath(SourceLineNumber sourceLineNumbers, string elementName, string attributeName, string relativePath)
675 { 622 {
676 const string root = @"C:\"; 623 return Common.GetCanonicalRelativePath(sourceLineNumbers, elementName, attributeName, relativePath, this.Messaging);
677 if (!Path.IsPathRooted(relativePath))
678 {
679 var normalizedPath = Path.GetFullPath(root + relativePath);
680 if (normalizedPath.StartsWith(root))
681 {
682 var canonicalizedPath = normalizedPath.Substring(root.Length);
683 if (canonicalizedPath != relativePath)
684 {
685 this.Messaging.Write(WarningMessages.PathCanonicalized(sourceLineNumbers, elementName, attributeName, relativePath, canonicalizedPath));
686 }
687 return canonicalizedPath;
688 }
689 }
690
691 this.Messaging.Write(ErrorMessages.PayloadMustBeRelativeToCache(sourceLineNumbers, elementName, attributeName, relativePath));
692 return relativePath;
693 } 624 }
694 625
695 public SourceLineNumber GetSourceLineNumbers(XElement element) 626 public SourceLineNumber GetSourceLineNumbers(XElement element)
@@ -723,46 +654,10 @@ namespace WixToolset.Core.ExtensibilityServices
723 654
724 public bool IsValidLongFilename(string filename, bool allowWildcards, bool allowRelative) 655 public bool IsValidLongFilename(string filename, bool allowWildcards, bool allowRelative)
725 { 656 {
726 if (String.IsNullOrEmpty(filename)) 657 return Common.IsValidLongFilename(filename, allowWildcards, allowRelative);
727 {
728 return false;
729 }
730 else if (filename.Length > 259)
731 {
732 return false;
733 }
734
735 // Check for a non-period character (all periods is not legal)
736 var allPeriods = true;
737 foreach (var character in filename)
738 {
739 if ('.' != character)
740 {
741 allPeriods = false;
742 break;
743 }
744 }
745
746 if (allPeriods)
747 {
748 return false;
749 }
750
751 if (allowWildcards)
752 {
753 return filename.IndexOfAny(Common.IllegalWildcardLongFilenameCharacters) == -1;
754 }
755 else if (allowRelative)
756 {
757 return filename.IndexOfAny(Common.IllegalRelativeLongFilenameCharacters) == -1;
758 }
759 else
760 {
761 return filename.IndexOfAny(Common.IllegalLongFilenameCharacters) == -1;
762 }
763 } 658 }
764 659
765 public bool IsValidShortFilename(string filename, bool allowWildcards = false) 660 public bool IsValidShortFilename(string filename, bool allowWildcards)
766 { 661 {
767 return Common.IsValidShortFilename(filename, allowWildcards); 662 return Common.IsValidShortFilename(filename, allowWildcards);
768 } 663 }
diff --git a/src/WixToolset.Core/ExtensibilityServices/WixBranding.cs b/src/WixToolset.Core/ExtensibilityServices/WixBranding.cs
new file mode 100644
index 00000000..56300400
--- /dev/null
+++ b/src/WixToolset.Core/ExtensibilityServices/WixBranding.cs
@@ -0,0 +1,124 @@
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
3using System.Resources;
4
5[assembly: NeutralResourcesLanguage("en-US")]
6
7namespace WixToolset.Core.ExtensibilityServices
8{
9 using System;
10 using System.Diagnostics;
11 using System.IO;
12 using System.Reflection;
13 using WixToolset.Extensibility.Services;
14
15 /// <summary>
16 /// Branding strings.
17 /// </summary>
18 internal class WixBranding : IWixBranding
19 {
20 /// <summary>
21 /// News URL for the distribution.
22 /// </summary>
23 public static string NewsUrl = "http://wixtoolset.org/news/";
24
25 /// <summary>
26 /// Short product name for the distribution.
27 /// </summary>
28 public static string ShortProduct = "WiX Toolset";
29
30 /// <summary>
31 /// Support URL for the distribution.
32 /// </summary>
33 public static string SupportUrl = "http://wixtoolset.org/";
34
35 /// <summary>
36 /// Telemetry URL format for the distribution.
37 /// </summary>
38 public static string TelemetryUrlFormat = "http://wixtoolset.org/telemetry/v{0}/?r={1}";
39
40 /// <summary>
41 /// VS Extensions Landing page Url for the distribution.
42 /// </summary>
43 public static string VSExtensionsLandingUrl = "http://wixtoolset.org/releases/";
44
45 public string GetCreatingApplication()
46 {
47 return this.ReplacePlaceholders("[AssemblyProduct] ([FileVersion])");
48 }
49
50 public string ReplacePlaceholders(string original, Assembly assembly = null)
51 {
52 if (assembly == null)
53 {
54 assembly = typeof(WixBranding).Assembly;
55 }
56
57 var commonVersionPath = Path.Combine(Path.GetDirectoryName(typeof(WixBranding).Assembly.Location), "wixver.dll");
58 if (File.Exists(commonVersionPath))
59 {
60 var commonFileVersion = FileVersionInfo.GetVersionInfo(commonVersionPath);
61
62 original = original.Replace("[FileCopyright]", commonFileVersion.LegalCopyright);
63 original = original.Replace("[FileVersion]", commonFileVersion.FileVersion);
64 }
65
66 var fileVersion = FileVersionInfo.GetVersionInfo(assembly.Location);
67
68 original = original.Replace("[FileComments]", fileVersion.Comments);
69 original = original.Replace("[FileCopyright]", fileVersion.LegalCopyright);
70 original = original.Replace("[FileProductName]", fileVersion.ProductName);
71 original = original.Replace("[FileVersion]", fileVersion.FileVersion);
72
73 if (original.Contains("[FileVersionMajorMinor]"))
74 {
75 var version = new Version(fileVersion.FileVersion);
76 original = original.Replace("[FileVersionMajorMinor]", String.Concat(version.Major, ".", version.Minor));
77 }
78
79 if (TryGetAttribute(assembly, out AssemblyCompanyAttribute company))
80 {
81 original = original.Replace("[AssemblyCompany]", company.Company);
82 }
83
84 if (TryGetAttribute(assembly, out AssemblyCopyrightAttribute copyright))
85 {
86 original = original.Replace("[AssemblyCopyright]", copyright.Copyright);
87 }
88
89 if (TryGetAttribute(assembly, out AssemblyDescriptionAttribute description))
90 {
91 original = original.Replace("[AssemblyDescription]", description.Description);
92 }
93
94 if (TryGetAttribute(assembly, out AssemblyProductAttribute product))
95 {
96 original = original.Replace("[AssemblyProduct]", product.Product);
97 }
98
99 if (TryGetAttribute(assembly, out AssemblyTitleAttribute title))
100 {
101 original = original.Replace("[AssemblyTitle]", title.Title);
102 }
103
104 original = original.Replace("[NewsUrl]", NewsUrl);
105 original = original.Replace("[ShortProduct]", ShortProduct);
106 original = original.Replace("[SupportUrl]", SupportUrl);
107
108 return original;
109 }
110
111 private static bool TryGetAttribute<T>(Assembly assembly, out T attribute) where T : Attribute
112 {
113 attribute = null;
114
115 var customAttributes = assembly.GetCustomAttributes(typeof(T), false);
116 if (null != customAttributes && 0 < customAttributes.Length)
117 {
118 attribute = customAttributes[0] as T;
119 }
120
121 return null != attribute;
122 }
123 }
124}
diff --git a/src/WixToolset.Core/LocalizationParser.cs b/src/WixToolset.Core/LocalizationParser.cs
index a0cf38a9..aaf4c425 100644
--- a/src/WixToolset.Core/LocalizationParser.cs
+++ b/src/WixToolset.Core/LocalizationParser.cs
@@ -30,10 +30,10 @@ namespace WixToolset.Core
30 30
31 public Localization ParseLocalization(XDocument document) 31 public Localization ParseLocalization(XDocument document)
32 { 32 {
33 XElement root = document.Root; 33 var root = document.Root;
34 Localization localization = null; 34 Localization localization = null;
35 35
36 SourceLineNumber sourceLineNumbers = SourceLineNumber.CreateFromXObject(root); 36 var sourceLineNumbers = SourceLineNumber.CreateFromXObject(root);
37 if (LocalizationParser.XmlElementName == root.Name.LocalName) 37 if (LocalizationParser.XmlElementName == root.Name.LocalName)
38 { 38 {
39 if (LocalizationParser.WxlNamespace == root.Name.Namespace) 39 if (LocalizationParser.WxlNamespace == root.Name.Namespace)
@@ -85,11 +85,11 @@ namespace WixToolset.Core
85 /// <param name="node">Element to parse.</param> 85 /// <param name="node">Element to parse.</param>
86 private static Localization ParseWixLocalizationElement(IMessaging messaging, XElement node) 86 private static Localization ParseWixLocalizationElement(IMessaging messaging, XElement node)
87 { 87 {
88 int codepage = -1; 88 var sourceLineNumbers = SourceLineNumber.CreateFromXObject(node);
89 var codepage = -1;
89 string culture = null; 90 string culture = null;
90 SourceLineNumber sourceLineNumbers = SourceLineNumber.CreateFromXObject(node);
91 91
92 foreach (XAttribute attrib in node.Attributes()) 92 foreach (var attrib in node.Attributes())
93 { 93 {
94 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || LocalizationParser.WxlNamespace == attrib.Name.Namespace) 94 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || LocalizationParser.WxlNamespace == attrib.Name.Namespace)
95 { 95 {
@@ -115,10 +115,10 @@ namespace WixToolset.Core
115 } 115 }
116 } 116 }
117 117
118 Dictionary<string, BindVariable> variables = new Dictionary<string, BindVariable>(); 118 var variables = new Dictionary<string, BindVariable>();
119 Dictionary<string, LocalizedControl> localizedControls = new Dictionary<string, LocalizedControl>(); 119 var localizedControls = new Dictionary<string, LocalizedControl>();
120 120
121 foreach (XElement child in node.Elements()) 121 foreach (var child in node.Elements())
122 { 122 {
123 if (LocalizationParser.WxlNamespace == child.Name.Namespace) 123 if (LocalizationParser.WxlNamespace == child.Name.Namespace)
124 { 124 {
@@ -155,10 +155,10 @@ namespace WixToolset.Core
155 private static void ParseString(IMessaging messaging, XElement node, IDictionary<string, BindVariable> variables) 155 private static void ParseString(IMessaging messaging, XElement node, IDictionary<string, BindVariable> variables)
156 { 156 {
157 string id = null; 157 string id = null;
158 bool overridable = false; 158 var overridable = false;
159 SourceLineNumber sourceLineNumbers = SourceLineNumber.CreateFromXObject(node); 159 var sourceLineNumbers = SourceLineNumber.CreateFromXObject(node);
160 160
161 foreach (XAttribute attrib in node.Attributes()) 161 foreach (var attrib in node.Attributes())
162 { 162 {
163 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || LocalizationParser.WxlNamespace == attrib.Name.Namespace) 163 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || LocalizationParser.WxlNamespace == attrib.Name.Namespace)
164 { 164 {
@@ -184,7 +184,7 @@ namespace WixToolset.Core
184 } 184 }
185 } 185 }
186 186
187 string value = Common.GetInnerText(node); 187 var value = Common.GetInnerText(node);
188 188
189 if (null == id) 189 if (null == id)
190 { 190 {
@@ -228,7 +228,7 @@ namespace WixToolset.Core
228 var rightAligned = false; 228 var rightAligned = false;
229 var leftScroll = false; 229 var leftScroll = false;
230 230
231 foreach (XAttribute attrib in node.Attributes()) 231 foreach (var attrib in node.Attributes())
232 { 232 {
233 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || LocalizationParser.WxlNamespace == attrib.Name.Namespace) 233 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || LocalizationParser.WxlNamespace == attrib.Name.Namespace)
234 { 234 {
diff --git a/src/WixToolset.Core/OptimizeCA.cs b/src/WixToolset.Core/OptimizeCA.cs
deleted file mode 100644
index 0d7b5e1a..00000000
--- a/src/WixToolset.Core/OptimizeCA.cs
+++ /dev/null
@@ -1,33 +0,0 @@
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
3namespace WixToolset.Core
4{
5 using System;
6
7 /// <summary>
8 /// Values for the OptimizeCA MsiPatchMetdata property, which indicates whether custom actions can be skipped when applying the patch.
9 /// </summary>
10 [Flags]
11 public enum OptimizeCA // TODO: review where to place this data so it can not be exposed by WixToolset.Core
12 {
13 /// <summary>
14 /// No custom actions are skipped.
15 /// </summary>
16 None = 0,
17
18 /// <summary>
19 /// Skip property (type 51) and directory (type 35) assignment custom actions.
20 /// </summary>
21 SkipAssignment = 1,
22
23 /// <summary>
24 /// Skip immediate custom actions that are not property or directory assignment custom actions.
25 /// </summary>
26 SkipImmediate = 2,
27
28 /// <summary>
29 /// Skip custom actions that run within the script.
30 /// </summary>
31 SkipDeferred = 4,
32 }
33}
diff --git a/src/WixToolset.Core/PatchSymbolFlagsType.cs b/src/WixToolset.Core/PatchSymbolFlagsType.cs
deleted file mode 100644
index e751fd18..00000000
--- a/src/WixToolset.Core/PatchSymbolFlagsType.cs
+++ /dev/null
@@ -1,34 +0,0 @@
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
3namespace WixToolset.Core
4{
5 using System;
6
7 /// <summary>
8 /// The following flags are used with PATCH_OPTION_DATA SymbolOptionFlags:
9 /// </summary>
10 [Flags]
11 public enum PatchSymbolFlagsType : uint
12 {
13 /// <summary>
14 /// don't use imagehlp.dll
15 /// </summary>
16 PATCH_SYMBOL_NO_IMAGEHLP = 0x00000001,
17 /// <summary>
18 /// don't fail patch due to imagehlp failures
19 /// </summary>
20 PATCH_SYMBOL_NO_FAILURES = 0x00000002,
21 /// <summary>
22 /// after matching decorated symbols, try to match remaining by undecorated names
23 /// </summary>
24 PATCH_SYMBOL_UNDECORATED_TOO = 0x00000004,
25 /// <summary>
26 /// (used internally)
27 /// </summary>
28 PATCH_SYMBOL_RESERVED1 = 0x80000000,
29 /// <summary>
30 ///
31 /// </summary>
32 MaxValue = PATCH_SYMBOL_NO_IMAGEHLP | PATCH_SYMBOL_NO_FAILURES | PATCH_SYMBOL_UNDECORATED_TOO
33 }
34}
diff --git a/src/WixToolset.Core/ResolvedCabinet.cs b/src/WixToolset.Core/ResolvedCabinet.cs
index 9304b413..be04831f 100644
--- a/src/WixToolset.Core/ResolvedCabinet.cs
+++ b/src/WixToolset.Core/ResolvedCabinet.cs
@@ -7,7 +7,7 @@ namespace WixToolset.Core
7 /// <summary> 7 /// <summary>
8 /// Data returned from build file manager ResolveCabinet callback. 8 /// Data returned from build file manager ResolveCabinet callback.
9 /// </summary> 9 /// </summary>
10 public class ResolvedCabinet : IResolvedCabinet 10 internal class ResolvedCabinet : IResolvedCabinet
11 { 11 {
12 /// <summary> 12 /// <summary>
13 /// Gets or sets the build option for the resolved cabinet. 13 /// Gets or sets the build option for the resolved cabinet.
diff --git a/src/WixToolset.Core/WixDistribution.cs b/src/WixToolset.Core/WixDistribution.cs
deleted file mode 100644
index 4ceb8982..00000000
--- a/src/WixToolset.Core/WixDistribution.cs
+++ /dev/null
@@ -1,109 +0,0 @@
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
3using System;
4using System.Diagnostics;
5using System.Reflection;
6using System.Resources;
7
8[assembly: NeutralResourcesLanguage("en-US")]
9
10namespace WixToolset
11{
12 /// <summary>
13 /// Distribution specific strings.
14 /// </summary>
15 internal static class WixDistribution
16 {
17 /// <summary>
18 /// News URL for the distribution.
19 /// </summary>
20 public static string NewsUrl = "http://wixtoolset.org/news/";
21
22 /// <summary>
23 /// Short product name for the distribution.
24 /// </summary>
25 public static string ShortProduct = "WiX Toolset";
26
27 /// <summary>
28 /// Support URL for the distribution.
29 /// </summary>
30 public static string SupportUrl = "http://wixtoolset.org/";
31
32 /// <summary>
33 /// Telemetry URL format for the distribution.
34 /// </summary>
35 public static string TelemetryUrlFormat = "http://wixtoolset.org/telemetry/v{0}/?r={1}";
36
37 /// <summary>
38 /// VS Extensions Landing page Url for the distribution.
39 /// </summary>
40 public static string VSExtensionsLandingUrl = "http://wixtoolset.org/releases/";
41
42 public static string ReplacePlaceholders(string original, Assembly assembly)
43 {
44 if (null != assembly)
45 {
46 FileVersionInfo fileVersion = FileVersionInfo.GetVersionInfo(assembly.Location);
47
48 original = original.Replace("[FileComments]", fileVersion.Comments);
49 original = original.Replace("[FileCopyright]", fileVersion.LegalCopyright);
50 original = original.Replace("[FileProductName]", fileVersion.ProductName);
51 original = original.Replace("[FileVersion]", fileVersion.FileVersion);
52
53 if (original.Contains("[FileVersionMajorMinor]"))
54 {
55 Version version = new Version(fileVersion.FileVersion);
56 original = original.Replace("[FileVersionMajorMinor]", String.Concat(version.Major, ".", version.Minor));
57 }
58
59 AssemblyCompanyAttribute company;
60 if (WixDistribution.TryGetAttribute(assembly, out company))
61 {
62 original = original.Replace("[AssemblyCompany]", company.Company);
63 }
64
65 AssemblyCopyrightAttribute copyright;
66 if (WixDistribution.TryGetAttribute(assembly, out copyright))
67 {
68 original = original.Replace("[AssemblyCopyright]", copyright.Copyright);
69 }
70
71 AssemblyDescriptionAttribute description;
72 if (WixDistribution.TryGetAttribute(assembly, out description))
73 {
74 original = original.Replace("[AssemblyDescription]", description.Description);
75 }
76
77 AssemblyProductAttribute product;
78 if (WixDistribution.TryGetAttribute(assembly, out product))
79 {
80 original = original.Replace("[AssemblyProduct]", product.Product);
81 }
82
83 AssemblyTitleAttribute title;
84 if (WixDistribution.TryGetAttribute(assembly, out title))
85 {
86 original = original.Replace("[AssemblyTitle]", title.Title);
87 }
88 }
89
90 original = original.Replace("[NewsUrl]", WixDistribution.NewsUrl);
91 original = original.Replace("[ShortProduct]", WixDistribution.ShortProduct);
92 original = original.Replace("[SupportUrl]", WixDistribution.SupportUrl);
93 return original;
94 }
95
96 private static bool TryGetAttribute<T>(Assembly assembly, out T attribute) where T : Attribute
97 {
98 attribute = null;
99
100 object[] customAttributes = assembly.GetCustomAttributes(typeof(T), false);
101 if (null != customAttributes && 0 < customAttributes.Length)
102 {
103 attribute = customAttributes[0] as T;
104 }
105
106 return null != attribute;
107 }
108 }
109}
diff --git a/src/WixToolset.Core/WixToolsetServiceProvider.cs b/src/WixToolset.Core/WixToolsetServiceProvider.cs
index 646b21fa..d4f186de 100644
--- a/src/WixToolset.Core/WixToolsetServiceProvider.cs
+++ b/src/WixToolset.Core/WixToolsetServiceProvider.cs
@@ -25,6 +25,7 @@ namespace WixToolset.Core
25 this.AddService((provider, singletons) => AddSingleton<IPreprocessHelper>(singletons, new PreprocessHelper(provider))); 25 this.AddService((provider, singletons) => AddSingleton<IPreprocessHelper>(singletons, new PreprocessHelper(provider)));
26 this.AddService((provider, singletons) => AddSingleton<IBackendHelper>(singletons, new BackendHelper(provider))); 26 this.AddService((provider, singletons) => AddSingleton<IBackendHelper>(singletons, new BackendHelper(provider)));
27 this.AddService((provider, singletons) => AddSingleton<IPathResolver>(singletons, new PathResolver())); 27 this.AddService((provider, singletons) => AddSingleton<IPathResolver>(singletons, new PathResolver()));
28 this.AddService((provider, singletons) => AddSingleton<IWixBranding>(singletons, new WixBranding()));
28 29
29 // Transients. 30 // Transients.
30 this.AddService<ICommandLineArguments>((provider, singletons) => new CommandLineArguments(provider)); 31 this.AddService<ICommandLineArguments>((provider, singletons) => new CommandLineArguments(provider));