From 2c365356b6b0383c1aadc06ebc20efcaa78ed492 Mon Sep 17 00:00:00 2001 From: Mike Richmond Date: Fri, 22 Jul 2016 14:41:24 -0700 Subject: [PATCH] Adding UpdatableHelp checks. --- .../msh/ConsoleHostUserInterfaceSecurity.cs | 53 +--- .../engine/PropertyAccessor.cs | 284 ++++++++++++------ .../engine/hostifaces/LocalPipeline.cs | 38 +-- .../help/UpdatableHelpSystem.cs | 86 +----- 4 files changed, 216 insertions(+), 245 deletions(-) diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterfaceSecurity.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterfaceSecurity.cs index bff6255942..15c63ce7a5 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterfaceSecurity.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterfaceSecurity.cs @@ -173,56 +173,19 @@ namespace Microsoft.PowerShell #if CORECLR // on Nano there is no other way to prompt except by using console return true; #else - string PolicyKeyName = Utils.GetRegistryConfigurationPrefix(); - const string PromptValueName = "ConsolePrompting"; - bool promptUsingConsole = false; - RegistryKey key; - - // Open the registry key that holds the configuration setting - try + PropertyAccessor propertyAccessor = PropertyAccessorFactory.GetPropertyAccessor(); + Exception exception = null; + bool promptUsingConsole = propertyAccessor.GetConsolePrompting(ref exception); + if (null != exception) { - key = Registry.LocalMachine.OpenSubKey(PolicyKeyName); + s_tracer.TraceError("Could not read CredUI registry key: " + exception.Message); + return false; } - catch (System.Security.SecurityException) + else { - s_tracer.TraceError("User doesn't have access to read CredUI registry key."); + s_tracer.WriteLine("DetermineCredUIPolicy: policy == {0}", promptUsingConsole); return promptUsingConsole; } - - if (key == null) - { - return promptUsingConsole; - } - - // Get the configuration setting - try - { - object consolePromptingKey = key.GetValue(PromptValueName); - if (consolePromptingKey != null) { promptUsingConsole = Convert.ToBoolean(consolePromptingKey.ToString(), CultureInfo.InvariantCulture); } - } - catch (System.Security.SecurityException e) - { - s_tracer.TraceError("Could not read CredUI registry key: " + e.Message); - if (key != null) { key.Dispose(); } // No RegistryKey.Close() on CoreCLR - return promptUsingConsole; - } - catch (InvalidCastException e) - { - s_tracer.TraceError("Could not parse CredUI registry key: " + e.Message); - if (key != null) { key.Dispose(); } // No RegistryKey.Close() on CoreCLR - return promptUsingConsole; - } - catch (FormatException e) - { - s_tracer.TraceError("Could not parse CredUI registry key: " + e.Message); - if (key != null) { key.Dispose(); } // No RegistryKey.Close() on CoreCLR - return promptUsingConsole; - } - - s_tracer.WriteLine("DetermineCredUIPolicy: policy == {0}", promptUsingConsole); - - if (key != null) { key.Dispose(); } // No RegistryKey.Close() on CoreCLR - return promptUsingConsole; #endif } } diff --git a/src/System.Management.Automation/engine/PropertyAccessor.cs b/src/System.Management.Automation/engine/PropertyAccessor.cs index ed72e1d87e..88e46cf412 100644 --- a/src/System.Management.Automation/engine/PropertyAccessor.cs +++ b/src/System.Management.Automation/engine/PropertyAccessor.cs @@ -4,9 +4,10 @@ using System.Xml; using System.IO; using System.Text; using System.Reflection; +using System.Globalization; +using System.Threading; using System.Management.Automation; -using System.Threading; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -66,7 +67,7 @@ namespace System.Management.Automation /// Proposed value = Existing value, otherwise 10. /// /// Max stack size in MB. If not set, defaults to 10 MB. - internal abstract int GetPipeLineMaxStackSizeMb(); + internal abstract int GetPipeLineMaxStackSizeMb(int defaultValue); internal abstract void SetPipeLineMaxStackSizeMb(int maxStackSize); @@ -75,7 +76,7 @@ namespace System.Management.Automation /// Proposed value = existing default. Probably "1" /// /// Whether console prompting should happen. - internal abstract bool GetConsolePrompting(); + internal abstract bool GetConsolePrompting(ref Exception exception); internal abstract void SetConsolePrompting(bool shouldPrompt); /// @@ -91,8 +92,8 @@ namespace System.Management.Automation /// Proposed value = blank.This should be supported though /// /// - internal abstract string GetDefaultSourcePath(PropertyScope scope); - internal abstract void SetDefaultSourcePath(PropertyScope scope, string defaultPath); + internal abstract string GetDefaultSourcePath(); + internal abstract void SetDefaultSourcePath(string defaultPath); } internal class PropertyAccessorFactory @@ -129,12 +130,12 @@ namespace System.Management.Automation { private string psHomeConfigDirectory; private string appDataConfigDirectory; - private static string configDirectoryName = "Configuration"; - private static string execPolicyFileName = "ExecutionPolicy.json"; - private static string maxStackSizeFileName = "PipeLineMaxStackSizeMB.json"; - private static string consolePromptingFileName = "ConsolePrompting.json"; - private static string updateHelpPromptFileName = "UpdateHelpPrompt.json"; - private static string updatableHelpSourcePathFileName = "UpdatableHelpDefaultSourcePath.json"; + private const string configDirectoryName = "Configuration"; + private const string execPolicyFileName = "ExecutionPolicy.json"; + private const string maxStackSizeFileName = "PipeLineMaxStackSizeMB.json"; + private const string consolePromptingFileName = "ConsolePrompting.json"; + private const string updateHelpPromptFileName = "UpdateHelpPrompt.json"; + private const string updatableHelpSourcePathFileName = "UpdatableHelpDefaultSourcePath.json"; internal JsonConfigFileAccessor() { @@ -235,11 +236,11 @@ namespace System.Management.Automation /// } /// /// Max stack size in MB. If not set, defaults to 10 MB. - internal override int GetPipeLineMaxStackSizeMb() + internal override int GetPipeLineMaxStackSizeMb(int defaultValue) { string fileName = Path.Combine(psHomeConfigDirectory, maxStackSizeFileName); - int maxStackSize = 10; + int maxStackSize = defaultValue; int rawMaxStackSize = ReadValueFromFile(fileName, "PipeLineMaxStackSizeMB"); if (0 != rawMaxStackSize) @@ -265,7 +266,7 @@ namespace System.Management.Automation /// } /// /// Whether console prompting should happen. - internal override bool GetConsolePrompting() + internal override bool GetConsolePrompting(ref Exception exception) { string fileName = Path.Combine(psHomeConfigDirectory, consolePromptingFileName); return ReadValueFromFile(fileName, "ConsolePrompting"); @@ -309,17 +310,9 @@ namespace System.Management.Automation /// } /// /// - internal override string GetDefaultSourcePath(PropertyScope scope) + internal override string GetDefaultSourcePath() { - string scopeDirectory = psHomeConfigDirectory; - - // Defaults to system wide. - if (PropertyScope.CurrentUser == scope) - { - scopeDirectory = appDataConfigDirectory; - } - - string fileName = Path.Combine(scopeDirectory, updatableHelpSourcePathFileName); + string fileName = Path.Combine(psHomeConfigDirectory, updatableHelpSourcePathFileName); string rawExecPolicy = ReadValueFromFile(fileName, "DefaultSourcePath"); @@ -331,17 +324,9 @@ namespace System.Management.Automation return String.Empty; } - internal override void SetDefaultSourcePath(PropertyScope scope, string defaultPath) + internal override void SetDefaultSourcePath(string defaultPath) { - string scopeDirectory = psHomeConfigDirectory; - - // Defaults to system wide. - if (PropertyScope.CurrentUser == scope) - { - scopeDirectory = appDataConfigDirectory; - } - - string fileName = Path.Combine(scopeDirectory, updatableHelpSourcePathFileName); + string fileName = Path.Combine(psHomeConfigDirectory, updatableHelpSourcePathFileName); WriteValueToFile(fileName, "DefaultSourcePath", defaultPath); } @@ -613,6 +598,12 @@ namespace System.Management.Automation internal class RegistryAccessor : PropertyAccessor { + private const string DisablePromptToUpdateHelpRegPath = "Software\\Microsoft\\PowerShell"; + private const string DisablePromptToUpdateHelpRegPath32 = "Software\\Wow6432Node\\Microsoft\\PowerShell"; + private const string DisablePromptToUpdateHelpRegKey = "DisablePromptToUpdateHelp"; + private const string DefaultSourcePathRegPath = "Software\\Policies\\Microsoft\\Windows\\PowerShell\\UpdatableHelp"; + private const string DefaultSourcePathRegKey = "DefaultSourcePath"; + internal RegistryAccessor() { } @@ -638,19 +629,15 @@ namespace System.Management.Automation internal override string GetMachineExecutionPolicy(PropertyScope scope, string shellId) { string regKeyName = Utils.GetRegistryConfigurationPath(shellId); + RegistryKey scopedKey = Registry.LocalMachine; - if (PropertyScope.SystemWide == scope) + // Override if set to another value; + if (PropertyScope.CurrentUser == scope) { - return GetHklmString(regKeyName, "ExecutionPolicy"); - } - else if (PropertyScope.CurrentUser == scope) - { - return GetHkcuString(regKeyName, "ExecutionPolicy"); - } - else - { - return null; + scopedKey = Registry.CurrentUser; } + + return GetRegistryString(scopedKey, regKeyName, "ExecutionPolicy"); } internal override void SetMachineExecutionPolicy(PropertyScope scope, string shellId, string executionPolicy) @@ -694,24 +681,48 @@ namespace System.Management.Automation } } - internal override int GetPipeLineMaxStackSizeMb() + internal override int GetPipeLineMaxStackSizeMb(int defaultValue) { - return 0; + string regKeyName = Utils.GetRegistryConfigurationPrefix(); + + int? tempInt = GetRegistryDword(Registry.LocalMachine, regKeyName, "PipelineMaxStackSizeMB"); + + return (tempInt.HasValue ? tempInt.Value : defaultValue); } + internal override void SetPipeLineMaxStackSizeMb(int maxStackSize) - { } + { + string regKeyName = Utils.GetRegistryConfigurationPrefix(); + SetRegistryDword(Registry.LocalMachine, regKeyName, "PipelineMaxStackSizeMB", maxStackSize); + } /// /// Existing Key = HKLM\SOFTWARE\Microsoft\PowerShell\1\ShellIds /// Proposed value = existing default. Probably "1" /// /// Whether console prompting should happen. - internal override bool GetConsolePrompting() + internal override bool GetConsolePrompting(ref Exception exception) { - return true; + string policyKeyName = Utils.GetRegistryConfigurationPrefix(); + string tempPrompt = GetRegistryString(Registry.LocalMachine, policyKeyName, "ConsolePrompting", ref exception); + + if (null != tempPrompt) + { + // TODO: It is difficult to tell from the original code how this value is actually stored in the registry. + // I am inferring that it is a "true" or "false" string based on the original code. + return Convert.ToBoolean(tempPrompt, CultureInfo.InvariantCulture); + } + else + { + return false; + } } + internal override void SetConsolePrompting(bool shouldPrompt) - { } + { + string policyKeyName = Utils.GetRegistryConfigurationPrefix(); + SetRegistryString(Registry.LocalMachine, policyKeyName, "ConsolePrompting", shouldPrompt.ToString()); + } /// /// Existing Key = HKLM\SOFTWARE\Microsoft\PowerShell @@ -720,28 +731,146 @@ namespace System.Management.Automation /// Boolean indicating whether Update-Help should prompt internal override bool GetDisablePromptToUpdateHelp() { - return true; + using (RegistryKey hklm = Registry.LocalMachine.OpenSubKey(DisablePromptToUpdateHelpRegPath)) + { + if (hklm != null) + { + object disablePromptToUpdateHelp = hklm.GetValue(DisablePromptToUpdateHelpRegKey, null, RegistryValueOptions.None); + + if (disablePromptToUpdateHelp == null) + { + return true; + } + else + { + int result; + + if (LanguagePrimitives.TryConvertTo(disablePromptToUpdateHelp, out result)) + { + return (result != 1); + } + + return true; + } + } + else + { + return true; + } + } } + internal override void SetDisablePromptToUpdateHelp(bool prompt) - { } + { + int valueToSet = prompt ? 1 : 0; + try + { + using (RegistryKey hklm = Registry.LocalMachine.OpenSubKey(DisablePromptToUpdateHelpRegPath, true)) + { + if (hklm != null) + { + hklm.SetValue(DisablePromptToUpdateHelpRegKey, valueToSet, RegistryValueKind.DWord); + } + } + + using (RegistryKey hklm = Registry.LocalMachine.OpenSubKey(DisablePromptToUpdateHelpRegPath32, true)) + { + if (hklm != null) + { + hklm.SetValue(DisablePromptToUpdateHelpRegKey, valueToSet, RegistryValueKind.DWord); + } + } + } + catch (UnauthorizedAccessException) {} + catch (System.Security.SecurityException) {} + } /// /// Existing Key = HKCU and HKLM\Software\Policies\Microsoft\Windows\PowerShell\UpdatableHelp /// Proposed value = blank.This should be supported though /// /// - internal override string GetDefaultSourcePath(PropertyScope scope) + internal override string GetDefaultSourcePath() { - return string.Empty; + return GetRegistryString(Registry.LocalMachine, DefaultSourcePathRegPath, DefaultSourcePathRegKey); } - internal override void SetDefaultSourcePath(PropertyScope scope, string defaultPath) - { } - private string GetHklmString(string pathToKey, string valueName) + internal override void SetDefaultSourcePath(string defaultPath) + { + SetRegistryString(Registry.LocalMachine, DefaultSourcePathRegPath, DefaultSourcePathRegKey, defaultPath); + } + + private int? GetRegistryDword(RegistryKey rootKey, string pathToKey, string valueName) { try { - using (RegistryKey regKey = Registry.LocalMachine.OpenSubKey(pathToKey)) + using (RegistryKey regKey = rootKey.OpenSubKey(pathToKey)) + { + if (null == regKey) + { + // Key not found + return null; + } + + // verify the value kind as a string + RegistryValueKind kind = regKey.GetValueKind(valueName); + + if (kind == RegistryValueKind.DWord) + { + return regKey.GetValue(valueName) as int?; + } + else + { + // The function expected a DWORD, but got another type. This is a coding error or a registry key typing error. + return null; + } + } + } + catch (ObjectDisposedException) { } + catch (System.Security.SecurityException) { } + catch (ArgumentException) { } + catch (System.IO.IOException) { } + catch (UnauthorizedAccessException) { } + catch (FormatException) { } + catch (OverflowException) { } + catch (InvalidCastException) { } + + return null; + } + + private void SetRegistryDword(RegistryKey rootKey, string pathToKey, string valueName, int value) + { + try + { + using (RegistryKey regKey = rootKey.OpenSubKey(pathToKey)) + { + if (null != regKey) + { + regKey.SetValue(valueName, value, RegistryValueKind.DWord); + } + } + } + catch (ObjectDisposedException) { } + catch (System.Security.SecurityException) { } + catch (ArgumentException) { } + catch (System.IO.IOException) { } + catch (UnauthorizedAccessException) { } + catch (FormatException) { } + catch (OverflowException) { } + catch (InvalidCastException) { } + } + + private string GetRegistryString(RegistryKey rootKey, string pathToKey, string valueName) + { + Exception e = null; + return GetRegistryString(rootKey, pathToKey, valueName, ref e); + } + + private string GetRegistryString(RegistryKey rootKey, string pathToKey, string valueName, ref Exception exception) + { + try + { + using (RegistryKey regKey = rootKey.OpenSubKey(pathToKey)) { if (null == regKey) { @@ -764,42 +893,27 @@ namespace System.Management.Automation } } } - catch (ObjectDisposedException) { } - catch (System.Security.SecurityException) { } - catch (ArgumentException) { } - catch (System.IO.IOException) { } - catch (UnauthorizedAccessException) { } - catch (FormatException) { } - catch (OverflowException) { } - catch (InvalidCastException) { } + catch (ObjectDisposedException e) { exception = e; } + catch (System.Security.SecurityException e) { exception = e; } + catch (ArgumentException e) { exception = e; } + catch (System.IO.IOException e) { exception = e; } + catch (UnauthorizedAccessException e) { exception = e; } + catch (FormatException e) { exception = e; } + catch (OverflowException e) { exception = e; } + catch (InvalidCastException e) { exception = e; } return null; } - private string GetHkcuString(string pathToKey, string valueName) + private string SetRegistryString(RegistryKey rootKey, string pathToKey, string valueName, string value) { try { - using (RegistryKey regKey = Registry.CurrentUser.OpenSubKey(pathToKey)) + using (RegistryKey key = rootKey.CreateSubKey(pathToKey)) { - if (null == regKey) + if (null != key) { - // Key not found - return null; - } - - // verify the value kind as a string - RegistryValueKind kind = regKey.GetValueKind(valueName); - - if (kind == RegistryValueKind.ExpandString || - kind == RegistryValueKind.String) - { - return regKey.GetValue(valueName) as string; - } - else - { - // The function expected a string, but got another type. This is a coding error or a registry key typing error. - return null; + key.SetValue(valueName, value, RegistryValueKind.String); } } } diff --git a/src/System.Management.Automation/engine/hostifaces/LocalPipeline.cs b/src/System.Management.Automation/engine/hostifaces/LocalPipeline.cs index 468734b335..6ff6f7a1e3 100644 --- a/src/System.Management.Automation/engine/hostifaces/LocalPipeline.cs +++ b/src/System.Management.Automation/engine/hostifaces/LocalPipeline.cs @@ -254,7 +254,9 @@ namespace System.Management.Automation.Runspaces { get { - int i = ReadRegistryInt("PipelineMaxStackSizeMB", 10); + PropertyAccessor propertyAccessor = PropertyAccessorFactory.GetPropertyAccessor(); + int i = propertyAccessor.GetPipeLineMaxStackSizeMb(10); + if (i < 10) i = 10; // minimum 10MB else if (i > 100) @@ -531,40 +533,6 @@ namespace System.Management.Automation.Runspaces return flowControlException; } - // NTRAID#Windows Out Of Band Releases-915506-2005/09/09 - // Removed HandleUnexpectedExceptions infrastructure - - internal static int ReadRegistryInt(string policyValueName, int defaultValue) - { - RegistryKey key; - try - { - key = Registry.LocalMachine.OpenSubKey(Utils.GetRegistryConfigurationPrefix()); - } - catch (System.Security.SecurityException) - { - return defaultValue; - } - if (null == key) - return defaultValue; - - object temp; - try - { - temp = key.GetValue(policyValueName); - } - catch (System.Security.SecurityException) - { - return defaultValue; - } - if (!(temp is int)) - { - return defaultValue; - } - int i = (int)temp; - return i; - } - // NTRAID#Windows Out Of Band Releases-915506-2005/09/09 // Removed HandleUnexpectedExceptions infrastructure /// diff --git a/src/System.Management.Automation/help/UpdatableHelpSystem.cs b/src/System.Management.Automation/help/UpdatableHelpSystem.cs index fc7111cbc9..0776fb8a15 100644 --- a/src/System.Management.Automation/help/UpdatableHelpSystem.cs +++ b/src/System.Management.Automation/help/UpdatableHelpSystem.cs @@ -238,12 +238,6 @@ namespace System.Management.Automation.Help /// internal class UpdatableHelpSystem : IDisposable { - internal const string DisablePromptToUpdateHelpRegPath = "Software\\Microsoft\\PowerShell"; - internal const string DisablePromptToUpdateHelpRegPath32 = "Software\\Wow6432Node\\Microsoft\\PowerShell"; - internal const string DisablePromptToUpdateHelpRegKey = "DisablePromptToUpdateHelp"; - internal const string DefaultSourcePathRegPath = "Software\\Policies\\Microsoft\\Windows\\PowerShell\\UpdatableHelp"; - internal const string DefaultSourcePathRegKey = "DefaultSourcePath"; - #if CORECLR private TimeSpan _defaultTimeout; #else @@ -1599,27 +1593,8 @@ namespace System.Management.Automation.Help /// internal string GetDefaultSourcePath() { - try - { - using (RegistryKey hklm = Registry.LocalMachine.OpenSubKey(DefaultSourcePathRegPath)) - { - if (hklm != null) - { - object defaultSourcePath = hklm.GetValue(DefaultSourcePathRegKey, null, RegistryValueOptions.None); - - if (defaultSourcePath != null) - { - return defaultSourcePath as string; - } - } - } - } - catch (SecurityException) - { - return null; - } - - return null; + PropertyAccessor propertyAccessor = PropertyAccessorFactory.GetPropertyAccessor(); + return propertyAccessor.GetDefaultSourcePath(); } /// @@ -1627,32 +1602,8 @@ namespace System.Management.Automation.Help /// internal static void SetDisablePromptToUpdateHelp() { - try - { - using (RegistryKey hklm = Registry.LocalMachine.OpenSubKey(DisablePromptToUpdateHelpRegPath, true)) - { - if (hklm != null) - { - hklm.SetValue(DisablePromptToUpdateHelpRegKey, 1, RegistryValueKind.DWord); - } - } - - using (RegistryKey hklm = Registry.LocalMachine.OpenSubKey(DisablePromptToUpdateHelpRegPath32, true)) - { - if (hklm != null) - { - hklm.SetValue(DisablePromptToUpdateHelpRegKey, 1, RegistryValueKind.DWord); - } - } - } - catch (UnauthorizedAccessException) - { - // Ignore AccessDenied related exceptions - } - catch (SecurityException) - { - // Ignore AccessDenied related exceptions - } + PropertyAccessor propertyAccessor = PropertyAccessorFactory.GetPropertyAccessor(); + propertyAccessor.SetDisablePromptToUpdateHelp(true); } /// @@ -1668,33 +1619,8 @@ namespace System.Management.Automation.Help return false; } - using (RegistryKey hklm = Registry.LocalMachine.OpenSubKey(DisablePromptToUpdateHelpRegPath)) - { - if (hklm != null) - { - object disablePromptToUpdateHelp = hklm.GetValue(DisablePromptToUpdateHelpRegKey, null, RegistryValueOptions.None); - - if (disablePromptToUpdateHelp == null) - { - return true; - } - else - { - int result; - - if (LanguagePrimitives.TryConvertTo(disablePromptToUpdateHelp, out result)) - { - return (result != 1); - } - - return true; - } - } - else - { - return true; - } - } + PropertyAccessor propertyAccessor = PropertyAccessorFactory.GetPropertyAccessor(); + return propertyAccessor.GetDisablePromptToUpdateHelp(); } catch (SecurityException) {