[bcl] Updates referencesource to 4.7.1
[mono-project.git] / mcs / class / referencesource / mscorlib / system / AppContext / AppContextDefaultValues.DesktopOverrides.cs
blob1f5434cc9856f441d846c06be78a937437c62e22
1 // ==++==
2 //
3 // Copyright (c) Microsoft Corporation. All rights reserved.
4 //
5 // ==--==
7 using Microsoft.Win32;
8 using Microsoft.Win32.SafeHandles;
9 using System;
10 using System.Collections.Generic;
11 using System.Diagnostics;
12 using System.Security;
14 namespace System
16 internal static partial class AppContextDefaultValues
18 /// <summary>
19 /// This method is going to parse the <paramref name="overrides"/> parameter and set the values corresponding to them
20 /// in the AppContext object
21 /// </summary>
22 [SecuritySafeCritical]
23 static partial void PopulateOverrideValuesPartial()
25 // Retrieve the value from EE config.
26 string overrides = System.Runtime.Versioning.CompatibilitySwitch.GetAppContextOverridesInternalCall();
28 // If we have no override values, do nothing.
29 if (string.IsNullOrEmpty(overrides))
30 return;
32 bool encounteredEquals = false, encounteredCharsInKey = false, encounteredCharsInValue = false;
33 int previousSemicolonPos = -1, firstEqualsPos = -1;
35 // Iterate over the string one character at a time until we reach the end of the string.
36 for (int currentPos = 0; currentPos <= overrides.Length; currentPos++)
38 // If the current position is either ';' or 'end-of-string' then we potentially have a key=value pair
39 if (currentPos == overrides.Length || overrides[currentPos] == ';')
41 // We only have a key=value pair if we encountered an equals, characters in the key and in the value
42 // portion of the pair.
43 if (encounteredEquals && encounteredCharsInKey && encounteredCharsInValue)
45 // We compute the indexes in the string for key and value
46 int firstCharOfKey = previousSemicolonPos + 1; //+1 because we don't take the ';' char
47 int lenghtOfKey = firstEqualsPos - previousSemicolonPos - 1; //-1 because we don't take the '=' char
48 string name = overrides.Substring(firstCharOfKey, lenghtOfKey);
50 int firstCharOfValue = firstEqualsPos + 1; // +1 because we don't count the '='
51 int lengthOfValue = currentPos - firstEqualsPos - 1; // -1 because we don't count the '='
52 string value = overrides.Substring(firstCharOfValue, lengthOfValue);
54 // apply the value only if it parses as a boolean
55 bool switchValue;
56 if (bool.TryParse(value, out switchValue))
58 // If multiple switches have the same name, the last value that we find will win.
59 AppContext.DefineSwitchOverride(name, switchValue);
62 previousSemicolonPos = currentPos;
64 // We need to reset these flags once we encounter a ';'
65 encounteredCharsInKey = encounteredCharsInValue = encounteredEquals = false;
67 else if (overrides[currentPos] == '=')
69 // if the current character is '=' then we should flag it and remember it
70 if (!encounteredEquals)
72 encounteredEquals = true;
73 firstEqualsPos = currentPos;
76 else
78 // We need to know if the key or value contain any characters (other than ';' and '=');
79 if (encounteredEquals)
81 encounteredCharsInValue = true;
83 else
85 encounteredCharsInKey = true;
91 // Note -- partial methods cannot return a value so we use refs to return information
92 [SecuritySafeCritical]
93 static partial void TryGetSwitchOverridePartial(string switchName, ref bool overrideFound, ref bool overrideValue)
95 string valueFromConfig = null;
96 bool boolFromConfig;
97 overrideFound = false;
99 // Read the value from the registry if we can (ie. the key exists)
100 if (s_errorReadingRegistry != true)
102 // try to read it from the registry key and return null if the switch name is not found
103 valueFromConfig = GetSwitchValueFromRegistry(switchName);
106 // Note: valueFromConfig will be null only if the key is not found.
107 // Read the value from the Shim database.
108 if (valueFromConfig == null)
110 // We are only going to check the Shim Database for an override in this case
111 valueFromConfig = System.Runtime.Versioning.CompatibilitySwitch.GetValue(switchName);
114 if (valueFromConfig != null && bool.TryParse(valueFromConfig, out boolFromConfig))
116 // If we found a valid override value, we need to let the caller know that.
117 overrideValue = boolFromConfig;
118 overrideFound = true;
122 private volatile static bool s_errorReadingRegistry;
123 [SecuritySafeCritical]
124 private static string GetSwitchValueFromRegistry(string switchName)
127 // We are using P/Invokes directly instead of using the RegistryKey class to avoid pulling in the
128 // globalization stack that is required by RegistryKey.
130 const string REG_KEY_APPCONTEXT = @"SOFTWARE\Microsoft\.NETFramework\AppContext";
133 using (SafeRegistryHandle hklm = new SafeRegistryHandle((IntPtr)RegistryHive.LocalMachine, true))
135 SafeRegistryHandle hkey = null;
137 if (Win32Native.RegOpenKeyEx(hklm, REG_KEY_APPCONTEXT, 0, Win32Native.KEY_READ, out hkey) == 0)
139 int size = 6 * sizeof(char); // "false".Length+1 * sizeof (char) as the API expects byte count and not char count.
140 int type = 0;
141 System.Text.StringBuilder keyBuffer = new System.Text.StringBuilder((int)size);
142 if (Win32Native.RegQueryValueEx(hkey, switchName, null, ref type, keyBuffer, ref size) == 0)
144 return keyBuffer.ToString();
147 else
149 // If we could not open the AppContext key, don't try it again.
150 s_errorReadingRegistry = true;
154 catch
156 // If there was an error, flag it so that we don't try this again.
157 s_errorReadingRegistry = true;
159 return null;