summaryrefslogtreecommitdiff
path: root/src/mscorlib/src/System/Runtime/Versioning
diff options
context:
space:
mode:
Diffstat (limited to 'src/mscorlib/src/System/Runtime/Versioning')
-rw-r--r--src/mscorlib/src/System/Runtime/Versioning/BinaryCompatibility.cs485
-rw-r--r--src/mscorlib/src/System/Runtime/Versioning/CompatibilitySwitch.cs61
-rw-r--r--src/mscorlib/src/System/Runtime/Versioning/ComponentGuaranteesAttribute.cs44
-rw-r--r--src/mscorlib/src/System/Runtime/Versioning/NonVersionableAttribute.cs33
-rw-r--r--src/mscorlib/src/System/Runtime/Versioning/ResourceAttributes.cs237
-rw-r--r--src/mscorlib/src/System/Runtime/Versioning/TargetFrameworkAttribute.cs45
-rw-r--r--src/mscorlib/src/System/Runtime/Versioning/TargetFrameworkId.cs28
7 files changed, 933 insertions, 0 deletions
diff --git a/src/mscorlib/src/System/Runtime/Versioning/BinaryCompatibility.cs b/src/mscorlib/src/System/Runtime/Versioning/BinaryCompatibility.cs
new file mode 100644
index 0000000000..99e30b5488
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/Versioning/BinaryCompatibility.cs
@@ -0,0 +1,485 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+** Purpose: This class is used to determine which binary compatibility
+** behaviors are enabled at runtime. A type for
+** tracking which target Framework an app was built against, or an
+** appdomain-wide setting from the host telling us which .NET
+** Framework version we should emulate.
+**
+**
+===========================================================*/
+using System;
+using System.Diagnostics.Contracts;
+using System.Globalization;
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.Versioning
+{
+ // Provides a simple way to test whether an application was built against specific .NET Framework
+ // flavors and versions, with the intent of allowing Framework developers to mimic behavior of older
+ // Framework releases. This allows us to make behavioral breaking changes in a binary compatible way,
+ // for an application. This works at the per-AppDomain level, not process nor per-Assembly.
+ //
+ // To opt into newer behavior, applications must specify a TargetFrameworkAttribute on their assembly
+ // saying what version they targeted, or a host must set this when creating an AppDomain. Note
+ // that command line apps don't have this attribute!
+ //
+ // To use this class:
+ // Developers need to figure out whether they're working on the phone, desktop, or Silverlight, and
+ // what version they are introducing a breaking change in. Pick one predicate below, and use that
+ // to decide whether to run the new or old behavior. Example:
+ //
+ // if (BinaryCompatibility.TargetsAtLeast_Phone_V7_1) {
+ // // new behavior for phone 7.1 and other releases where we will integrate this change, like .NET Framework 4.5
+ // }
+ // else {
+ // // Legacy behavior
+ // }
+ //
+ // If you are making a breaking change in one specific branch that won't be integrated normally to
+ // all other branches (ie, say you're making breaking changes to Windows Phone 8 after .NET Framework v4.5
+ // has locked down for release), then add in specific predicates for each relevant platform.
+ //
+ // Maintainers of this class:
+ // Revisit the table once per release, perhaps at the end of the last coding milestone, to verify a
+ // default policy saying whether all quirks from a particular flavor & release should be enabled in
+ // other releases (ie, should all Windows Phone 8.0 quirks be enabled in .NET Framework v5)?
+ //
+ // History:
+ // Here is the order in which releases were made along with some basic integration information. The idea
+ // is to track what set of compatibility features are present in each other.
+ // While we cannot guarantee this list is perfectly linear (ie, a feature could be implemented in the last
+ // few weeks before shipping and make it into only one of three concommittent releases due to triaging),
+ // this is a good high level summary of code flow.
+ //
+ // Desktop Silverlight Windows Phone
+ // .NET Framework 3.0 -> Silverlight 2
+ // .NET Framework 3.5
+ // Silverlight 3
+ // Silverlight 4
+ // .NET Framework 4 Phone 8.0
+ // .NET Framework 4.5 Phone 8.1
+ // .NET Framework 4.5.1 Phone 8.1
+ //
+ // (Note: Windows Phone 7.0 was built using the .NET Compact Framework, which forked around v1 or v1.1)
+ //
+ // Compatibility Policy decisions:
+ // If we cannot determine that an app was built for a newer .NET Framework (ie, the app has no
+ // TargetFrameworkAttribute), then quirks will be enabled to emulate older behavior.
+ // As such, your test code should define the TargetFrameworkAttribute (which VS does for you)
+ // if you want to see the new behavior!
+ [FriendAccessAllowed]
+ internal static class BinaryCompatibility
+ {
+ // Use this for new behavior introduced in the phone branch. It will do the right thing for desktop & SL.
+ [FriendAccessAllowed]
+ internal static bool TargetsAtLeast_Phone_V7_1 { [FriendAccessAllowed] get { return s_map.TargetsAtLeast_Phone_V7_1; } }
+
+ [FriendAccessAllowed]
+ internal static bool TargetsAtLeast_Phone_V8_0 { [FriendAccessAllowed] get { return s_map.TargetsAtLeast_Phone_V8_0; } }
+
+ // Use this for new behavior introduced in the Desktop branch. It will do the right thing for Phone & SL.
+ [FriendAccessAllowed]
+ internal static bool TargetsAtLeast_Desktop_V4_5 { [FriendAccessAllowed] get { return s_map.TargetsAtLeast_Desktop_V4_5; } }
+ [FriendAccessAllowed]
+ internal static bool TargetsAtLeast_Desktop_V4_5_1 { [FriendAccessAllowed] get { return s_map.TargetsAtLeast_Desktop_V4_5_1; } }
+ [FriendAccessAllowed]
+ internal static bool TargetsAtLeast_Desktop_V4_5_2 { [FriendAccessAllowed] get { return s_map.TargetsAtLeast_Desktop_V4_5_2; } }
+ [FriendAccessAllowed]
+ internal static bool TargetsAtLeast_Desktop_V4_5_3 { [FriendAccessAllowed] get { return s_map.TargetsAtLeast_Desktop_V4_5_3; } }
+ [FriendAccessAllowed]
+ internal static bool TargetsAtLeast_Desktop_V4_5_4 { [FriendAccessAllowed] get { return s_map.TargetsAtLeast_Desktop_V4_5_4; } }
+
+ [FriendAccessAllowed]
+ internal static bool TargetsAtLeast_Desktop_V5_0 { [FriendAccessAllowed] get { return s_map.TargetsAtLeast_Desktop_V5_0; } }
+
+ // Use this for new behavior introduced in the Silverlight branch. It will do the right thing for desktop & Phone.
+ [FriendAccessAllowed]
+ internal static bool TargetsAtLeast_Silverlight_V4 { [FriendAccessAllowed] get { return s_map.TargetsAtLeast_Silverlight_V4; } }
+ [FriendAccessAllowed]
+ internal static bool TargetsAtLeast_Silverlight_V5 { [FriendAccessAllowed] get { return s_map.TargetsAtLeast_Silverlight_V5; } }
+ [FriendAccessAllowed]
+ internal static bool TargetsAtLeast_Silverlight_V6 { [FriendAccessAllowed] get { return s_map.TargetsAtLeast_Silverlight_V6; } }
+
+ [FriendAccessAllowed]
+ internal static TargetFrameworkId AppWasBuiltForFramework {
+ [FriendAccessAllowed]
+ get {
+ Contract.Ensures(Contract.Result<TargetFrameworkId>() > TargetFrameworkId.NotYetChecked);
+
+ if (s_AppWasBuiltForFramework == TargetFrameworkId.NotYetChecked)
+ ReadTargetFrameworkId();
+
+ return s_AppWasBuiltForFramework;
+ }
+ }
+
+ // Version number is major * 10000 + minor * 100 + build (ie, 4.5.1.0 would be version 40501).
+ [FriendAccessAllowed]
+ internal static int AppWasBuiltForVersion {
+ [FriendAccessAllowed]
+ get {
+ Contract.Ensures(Contract.Result<int>() > 0 || s_AppWasBuiltForFramework == TargetFrameworkId.Unspecified);
+
+ if (s_AppWasBuiltForFramework == TargetFrameworkId.NotYetChecked)
+ ReadTargetFrameworkId();
+
+ Contract.Assert(s_AppWasBuiltForFramework != TargetFrameworkId.Unrecognized);
+
+ return s_AppWasBuiltForVersion;
+ }
+ }
+
+ #region private
+ private static TargetFrameworkId s_AppWasBuiltForFramework;
+ // Version number is major * 10000 + minor * 100 + build (ie, 4.5.1.0 would be version 40501).
+ private static int s_AppWasBuiltForVersion;
+
+ readonly static BinaryCompatibilityMap s_map = new BinaryCompatibilityMap();
+
+ // For parsing a target Framework moniker, from the FrameworkName class
+ private const char c_componentSeparator = ',';
+ private const char c_keyValueSeparator = '=';
+ private const char c_versionValuePrefix = 'v';
+ private const String c_versionKey = "Version";
+ private const String c_profileKey = "Profile";
+
+ /// <summary>
+ /// BinaryCompatibilityMap is basically a bitvector. There is a boolean field for each of the
+ /// properties in BinaryCompatibility
+ /// </summary>
+ private sealed class BinaryCompatibilityMap
+ {
+ // A bit for each property
+ internal bool TargetsAtLeast_Phone_V7_1;
+ internal bool TargetsAtLeast_Phone_V8_0;
+ internal bool TargetsAtLeast_Phone_V8_1;
+ internal bool TargetsAtLeast_Desktop_V4_5;
+ internal bool TargetsAtLeast_Desktop_V4_5_1;
+ internal bool TargetsAtLeast_Desktop_V4_5_2;
+ internal bool TargetsAtLeast_Desktop_V4_5_3;
+ internal bool TargetsAtLeast_Desktop_V4_5_4;
+ internal bool TargetsAtLeast_Desktop_V5_0;
+ internal bool TargetsAtLeast_Silverlight_V4;
+ internal bool TargetsAtLeast_Silverlight_V5;
+ internal bool TargetsAtLeast_Silverlight_V6;
+
+ internal BinaryCompatibilityMap()
+ {
+ AddQuirksForFramework(AppWasBuiltForFramework, AppWasBuiltForVersion);
+ }
+
+ // The purpose of this method is to capture information about integrations & behavioral compatibility
+ // between our multiple different release vehicles. IE, if a behavior shows up in Silverlight version 5,
+ // does it show up in the .NET Framework version 4.5 and Windows Phone 8?
+ // Version number is major * 10000 + minor * 100 + build (ie, 4.5.1.0 would be version 40501).
+ private void AddQuirksForFramework(TargetFrameworkId builtAgainstFramework, int buildAgainstVersion)
+ {
+ Contract.Requires(buildAgainstVersion > 0 || builtAgainstFramework == TargetFrameworkId.Unspecified);
+
+ switch (builtAgainstFramework)
+ {
+ case TargetFrameworkId.NetFramework:
+ case TargetFrameworkId.NetCore: // Treat Windows 8 tailored apps as normal desktop apps - same product
+ if (buildAgainstVersion >= 50000)
+ TargetsAtLeast_Desktop_V5_0 = true;
+
+ // Potential 4.5 servicing releases
+ if (buildAgainstVersion >= 40504)
+ TargetsAtLeast_Desktop_V4_5_4 = true;
+ if (buildAgainstVersion >= 40503)
+ TargetsAtLeast_Desktop_V4_5_3 = true;
+ if (buildAgainstVersion >= 40502)
+ TargetsAtLeast_Desktop_V4_5_2 = true;
+ if (buildAgainstVersion >= 40501)
+ TargetsAtLeast_Desktop_V4_5_1 = true;
+
+ if (buildAgainstVersion >= 40500)
+ {
+ TargetsAtLeast_Desktop_V4_5 = true;
+ // On XX/XX/XX we integrated all changes from the phone V7_1 into the branch from which contains Desktop V4_5, thus
+ // Any application built for V4_5 (or above) should have all the quirks for Phone V7_1 turned on.
+ AddQuirksForFramework(TargetFrameworkId.Phone, 70100);
+ // All Silverlight 5 behavior should be in the .NET Framework version 4.5
+ AddQuirksForFramework(TargetFrameworkId.Silverlight, 50000);
+ }
+ break;
+
+ case TargetFrameworkId.Phone:
+ if (buildAgainstVersion >= 80000)
+ {
+ // This is for Apollo apps. For Apollo apps we don't want to enable any of the 4.5 or 4.5.1 quirks
+ TargetsAtLeast_Phone_V8_0 = true;
+ //TargetsAtLeast_Desktop_V4_5 = true;
+ }
+ if (buildAgainstVersion >= 80100)
+ {
+ // For WindowsPhone 8.1 and SL 8.1 scenarios we want to enable both 4.5 and 4.5.1 quirks.
+ TargetsAtLeast_Desktop_V4_5 = true;
+ TargetsAtLeast_Desktop_V4_5_1 = true;
+ }
+
+ if (buildAgainstVersion >= 710)
+ TargetsAtLeast_Phone_V7_1 = true;
+ break;
+
+ case TargetFrameworkId.Silverlight:
+ if (buildAgainstVersion >= 40000)
+ TargetsAtLeast_Silverlight_V4 = true;
+
+ if (buildAgainstVersion >= 50000)
+ TargetsAtLeast_Silverlight_V5 = true;
+
+ if (buildAgainstVersion >= 60000)
+ {
+ TargetsAtLeast_Silverlight_V6 = true;
+ }
+ break;
+
+ case TargetFrameworkId.Unspecified:
+ break;
+
+ case TargetFrameworkId.NotYetChecked:
+ case TargetFrameworkId.Unrecognized:
+ Contract.Assert(false, "Bad framework kind");
+ break;
+ default:
+ Contract.Assert(false, "Error: we introduced a new Target Framework but did not update our binary compatibility map");
+ break;
+ }
+ }
+ }
+
+ #region String Parsing
+
+ // If this doesn't work, perhaps we could fall back to parsing the metadata version number.
+ private static bool ParseTargetFrameworkMonikerIntoEnum(String targetFrameworkMoniker, out TargetFrameworkId targetFramework, out int targetFrameworkVersion)
+ {
+ Contract.Requires(!String.IsNullOrEmpty(targetFrameworkMoniker));
+
+ targetFramework = TargetFrameworkId.NotYetChecked;
+ targetFrameworkVersion = 0;
+
+ String identifier = null;
+ String profile = null;
+ ParseFrameworkName(targetFrameworkMoniker, out identifier, out targetFrameworkVersion, out profile);
+
+ switch (identifier)
+ {
+ case ".NETFramework":
+ targetFramework = TargetFrameworkId.NetFramework;
+ break;
+
+ case ".NETPortable":
+ targetFramework = TargetFrameworkId.Portable;
+ break;
+
+ case ".NETCore":
+ targetFramework = TargetFrameworkId.NetCore;
+ break;
+
+ case "WindowsPhone":
+ if (targetFrameworkVersion >= 80100)
+ {
+ // A TFM of the form WindowsPhone,Version=v8.1 corresponds to SL 8.1 scenario
+ // and gets the same quirks as WindowsPhoneApp\v8.1 store apps.
+ targetFramework = TargetFrameworkId.Phone;
+ }
+ else
+ {
+ // There is no TFM for Apollo or below and hence we assign the targetFramework to Unspecified.
+ targetFramework = TargetFrameworkId.Unspecified;
+ }
+ break;
+
+ case "WindowsPhoneApp":
+ targetFramework = TargetFrameworkId.Phone;
+ break;
+
+ case "Silverlight":
+ targetFramework = TargetFrameworkId.Silverlight;
+ // Windows Phone 7 is Silverlight,Version=v4.0,Profile=WindowsPhone
+ // Windows Phone 7.1 is Silverlight,Version=v4.0,Profile=WindowsPhone71
+ if (!String.IsNullOrEmpty(profile))
+ {
+ if (profile == "WindowsPhone")
+ {
+ targetFramework = TargetFrameworkId.Phone;
+ targetFrameworkVersion = 70000;
+ }
+ else if (profile == "WindowsPhone71")
+ {
+ targetFramework = TargetFrameworkId.Phone;
+ targetFrameworkVersion = 70100;
+ }
+ else if (profile == "WindowsPhone8")
+ {
+ targetFramework = TargetFrameworkId.Phone;
+ targetFrameworkVersion = 80000;
+ }
+ else if (profile.StartsWith("WindowsPhone", StringComparison.Ordinal))
+ {
+ Contract.Assert(false, "This is a phone app, but we can't tell what version this is!");
+ targetFramework = TargetFrameworkId.Unrecognized;
+ targetFrameworkVersion = 70100;
+ }
+ else
+ {
+ Contract.Assert(false, String.Format(CultureInfo.InvariantCulture, "Unrecognized Silverlight profile \"{0}\". What is this, an XBox app?", profile));
+ targetFramework = TargetFrameworkId.Unrecognized;
+ }
+ }
+ break;
+
+ default:
+ Contract.Assert(false, String.Format(CultureInfo.InvariantCulture, "Unrecognized Target Framework Moniker in our Binary Compatibility class. Framework name: \"{0}\"", targetFrameworkMoniker));
+ targetFramework = TargetFrameworkId.Unrecognized;
+ break;
+ }
+
+ return true;
+ }
+
+ // This code was a constructor copied from the FrameworkName class, which is located in System.dll.
+ // Parses strings in the following format: "<identifier>, Version=[v|V]<version>, Profile=<profile>"
+ // - The identifier and version is required, profile is optional
+ // - Only three components are allowed.
+ // - The version string must be in the System.Version format; an optional "v" or "V" prefix is allowed
+ private static void ParseFrameworkName(String frameworkName, out String identifier, out int version, out String profile)
+ {
+ if (frameworkName == null)
+ {
+ throw new ArgumentNullException("frameworkName");
+ }
+ if (frameworkName.Length == 0)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_StringZeroLength"), "frameworkName");
+ }
+ Contract.EndContractBlock();
+
+ String[] components = frameworkName.Split(c_componentSeparator);
+ version = 0;
+
+ // Identifer and Version are required, Profile is optional.
+ if (components.Length < 2 || components.Length > 3)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_FrameworkNameTooShort"), "frameworkName");
+ }
+
+ //
+ // 1) Parse the "Identifier", which must come first. Trim any whitespace
+ //
+ identifier = components[0].Trim();
+
+ if (identifier.Length == 0)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_FrameworkNameInvalid"), "frameworkName");
+ }
+
+ bool versionFound = false;
+ profile = null;
+
+ //
+ // The required "Version" and optional "Profile" component can be in any order
+ //
+ for (int i = 1; i < components.Length; i++)
+ {
+ // Get the key/value pair separated by '='
+ string[] keyValuePair = components[i].Split(c_keyValueSeparator);
+
+ if (keyValuePair.Length != 2)
+ {
+ throw new ArgumentException(Environment.GetResourceString("SR.Argument_FrameworkNameInvalid"), "frameworkName");
+ }
+
+ // Get the key and value, trimming any whitespace
+ string key = keyValuePair[0].Trim();
+ string value = keyValuePair[1].Trim();
+
+ //
+ // 2) Parse the required "Version" key value
+ //
+ if (key.Equals(c_versionKey, StringComparison.OrdinalIgnoreCase))
+ {
+ versionFound = true;
+
+ // Allow the version to include a 'v' or 'V' prefix...
+ if (value.Length > 0 && (value[0] == c_versionValuePrefix || value[0] == 'V'))
+ {
+ value = value.Substring(1);
+ }
+ Version realVersion = new Version(value);
+ // The version class will represent some unset values as -1 internally (instead of 0).
+ version = realVersion.Major * 10000;
+ if (realVersion.Minor > 0)
+ version += realVersion.Minor * 100;
+ if (realVersion.Build > 0)
+ version += realVersion.Build;
+ }
+ //
+ // 3) Parse the optional "Profile" key value
+ //
+ else if (key.Equals(c_profileKey, StringComparison.OrdinalIgnoreCase))
+ {
+ if (!String.IsNullOrEmpty(value))
+ {
+ profile = value;
+ }
+ }
+ else
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_FrameworkNameInvalid"), "frameworkName");
+ }
+ }
+
+ if (!versionFound)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_FrameworkNameMissingVersion"), "frameworkName");
+ }
+ }
+
+ [System.Security.SecuritySafeCritical]
+ private static void ReadTargetFrameworkId()
+ {
+ String targetFrameworkName = AppDomain.CurrentDomain.GetTargetFrameworkName();
+
+ var overrideValue = System.Runtime.Versioning.CompatibilitySwitch.GetValueInternal("TargetFrameworkMoniker");
+ if (!string.IsNullOrEmpty(overrideValue))
+ {
+ targetFrameworkName = overrideValue;
+ }
+
+ // Write to a local then to _targetFramework, after writing the version number.
+ TargetFrameworkId fxId;
+ int fxVersion = 0;
+ if (targetFrameworkName == null)
+ {
+#if FEATURE_CORECLR
+ // if we don't have a value for targetFrameworkName we need to figure out if we should give the newest behavior or not.
+ if (CompatibilitySwitches.UseLatestBehaviorWhenTFMNotSpecified)
+ {
+ fxId = TargetFrameworkId.NetFramework;
+ fxVersion = 50000; // We are going to default to the latest value for version that we have in our code.
+ }
+ else
+#endif
+ fxId = TargetFrameworkId.Unspecified;
+ }
+ else if (!ParseTargetFrameworkMonikerIntoEnum(targetFrameworkName, out fxId, out fxVersion))
+ fxId = TargetFrameworkId.Unrecognized;
+
+ s_AppWasBuiltForFramework = fxId;
+ s_AppWasBuiltForVersion = fxVersion;
+ }
+ #endregion String Parsing
+
+ #endregion private
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/Versioning/CompatibilitySwitch.cs b/src/mscorlib/src/System/Runtime/Versioning/CompatibilitySwitch.cs
new file mode 100644
index 0000000000..b06c42437c
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/Versioning/CompatibilitySwitch.cs
@@ -0,0 +1,61 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+using System;
+using System.Globalization;
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.Versioning
+{
+ public static class CompatibilitySwitch
+ {
+ /* This class contains 3 sets of api:
+ * 1. internal apis : These apis are supposed to be used by mscorlib.dll and other assemblies which use the <runtime> section in config
+ * These apis query for the value of quirk not only in windows quirk DB but also in runtime section of config files,
+ * registry and environment vars.
+ * 2. public apis : These apis are supposed to be used by FX assemblies which do not read the runtime section of config files and have
+ * have their own section in config files or do not use configs at all.
+ *
+ * 3. specialized apis: These apis are defined in order to retrieve a specific value defined in CLR Config. That value can have specific look-up rules
+ * for the order and location of the config sources used.
+ *
+ * These apis are for internal use only for FX assmeblies. It has not been decided if they can be used by OOB components due to EULA restrictions
+ */
+ [System.Security.SecurityCritical]
+ public static bool IsEnabled(string compatibilitySwitchName)
+ {
+ return IsEnabledInternalCall(compatibilitySwitchName, true);
+ }
+
+ [System.Security.SecurityCritical]
+ public static string GetValue(string compatibilitySwitchName)
+ {
+ // This is used by AppContext.TryGetSwitch to check switch overrides in the Windows Quirk DB
+ // If this method is updated to check other locations than the DB, please ensure compat with
+ // the AppContext class.
+ return GetValueInternalCall(compatibilitySwitchName, true);
+ }
+
+ [System.Security.SecurityCritical]
+ internal static bool IsEnabledInternal(string compatibilitySwitchName)
+ {
+ return IsEnabledInternalCall(compatibilitySwitchName, false);
+ }
+
+ [System.Security.SecurityCritical]
+ internal static string GetValueInternal(string compatibilitySwitchName)
+ {
+ return GetValueInternalCall(compatibilitySwitchName, false);
+ }
+
+ [System.Security.SecurityCritical]
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ internal static extern string GetAppContextOverridesInternalCall();
+
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ private static extern bool IsEnabledInternalCall(string compatibilitySwitchName, bool onlyDB);
+
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ private static extern string GetValueInternalCall(string compatibilitySwitchName, bool onlyDB);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/Versioning/ComponentGuaranteesAttribute.cs b/src/mscorlib/src/System/Runtime/Versioning/ComponentGuaranteesAttribute.cs
new file mode 100644
index 0000000000..0f906d518a
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/Versioning/ComponentGuaranteesAttribute.cs
@@ -0,0 +1,44 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: Tracking whether a component signs up for a
+** a strong contract spanning multiple versions.
+**
+===========================================================*/
+using System;
+
+namespace System.Runtime.Versioning {
+
+ [Flags]
+ [Serializable]
+ public enum ComponentGuaranteesOptions
+ {
+ None = 0,
+ Exchange = 0x1,
+ Stable = 0x2,
+ SideBySide = 0x4,
+ }
+
+ [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class |
+ AttributeTargets.Struct | AttributeTargets.Interface | AttributeTargets.Delegate |
+ AttributeTargets.Enum | AttributeTargets.Method | AttributeTargets.Property |
+ AttributeTargets.Constructor | AttributeTargets.Event,
+ AllowMultiple = false, Inherited = false)]
+ public sealed class ComponentGuaranteesAttribute : Attribute {
+ private ComponentGuaranteesOptions _guarantees;
+
+ public ComponentGuaranteesAttribute(ComponentGuaranteesOptions guarantees)
+ {
+ _guarantees = guarantees;
+ }
+
+ public ComponentGuaranteesOptions Guarantees {
+ get { return _guarantees; }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/Versioning/NonVersionableAttribute.cs b/src/mscorlib/src/System/Runtime/Versioning/NonVersionableAttribute.cs
new file mode 100644
index 0000000000..0a9845d9c2
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/Versioning/NonVersionableAttribute.cs
@@ -0,0 +1,33 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Class: NonVersionableAttribute
+**
+**
+** The [NonVersionable] attribute is applied to indicate that the implementation
+** of a particular member or layout of a struct cannot be changed for given platform in incompatible way.
+** This allows cross-module inlining of methods and data structures whose implementation
+** is never changed in ReadyToRun native images. Any changes to such members or types would be
+** breaking changes for ReadyToRun.
+**
+===========================================================*/
+using System;
+using System.Diagnostics;
+
+namespace System.Runtime.Versioning {
+
+ // This Conditional is here to strip the annotations for targets where ReadyToRun is not supported.
+ // If this attribute is ever made public, this Conditional should be removed.
+ [Conditional("FEATURE_READYTORUN")]
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Constructor,
+ AllowMultiple = false, Inherited = false)]
+ sealed class NonVersionableAttribute : Attribute {
+
+ public NonVersionableAttribute()
+ {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/Versioning/ResourceAttributes.cs b/src/mscorlib/src/System/Runtime/Versioning/ResourceAttributes.cs
new file mode 100644
index 0000000000..78a9ddbd07
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/Versioning/ResourceAttributes.cs
@@ -0,0 +1,237 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Purpose: Resource annotation rules.
+**
+===========================================================*/
+using System;
+using System.Diagnostics;
+using System.Globalization;
+using System.Runtime.CompilerServices;
+using System.Text;
+using Microsoft.Win32;
+using System.Diagnostics.Contracts;
+
+namespace System.Runtime.Versioning
+{
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Constructor, Inherited = false)]
+ [Conditional("RESOURCE_ANNOTATION_WORK")]
+ public sealed class ResourceConsumptionAttribute : Attribute
+ {
+ private ResourceScope _consumptionScope;
+ private ResourceScope _resourceScope;
+
+ public ResourceConsumptionAttribute(ResourceScope resourceScope)
+ {
+ _resourceScope = resourceScope;
+ _consumptionScope = _resourceScope;
+ }
+
+ public ResourceConsumptionAttribute(ResourceScope resourceScope, ResourceScope consumptionScope)
+ {
+ _resourceScope = resourceScope;
+ _consumptionScope = consumptionScope;
+ }
+
+ public ResourceScope ResourceScope {
+ get { return _resourceScope; }
+ }
+
+ public ResourceScope ConsumptionScope {
+ get { return _consumptionScope; }
+ }
+ }
+
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Constructor, Inherited = false)]
+ [Conditional("RESOURCE_ANNOTATION_WORK")]
+ public sealed class ResourceExposureAttribute : Attribute
+ {
+ private ResourceScope _resourceExposureLevel;
+
+ public ResourceExposureAttribute(ResourceScope exposureLevel)
+ {
+ _resourceExposureLevel = exposureLevel;
+ }
+
+ public ResourceScope ResourceExposureLevel {
+ get { return _resourceExposureLevel; }
+ }
+ }
+
+
+ // Default visibility is Public, which isn't specified in this enum.
+ // Public == the lack of Private or Assembly
+ // Does this actually work? Need to investigate that.
+ [Flags]
+ public enum ResourceScope
+ {
+ None = 0,
+ // Resource type
+ Machine = 0x1,
+ Process = 0x2,
+ AppDomain = 0x4,
+ Library = 0x8,
+ // Visibility
+ Private = 0x10, // Private to this one class.
+ Assembly = 0x20, // Assembly-level, like C#'s "internal"
+ }
+
+
+ [Flags]
+ internal enum SxSRequirements
+ {
+ None = 0,
+ AppDomainID = 0x1,
+ ProcessID = 0x2,
+ CLRInstanceID = 0x4, // for multiple CLR's within the process
+ AssemblyName = 0x8,
+ TypeName = 0x10
+ }
+
+ public static class VersioningHelper
+ {
+ // These depend on the exact values given to members of the ResourceScope enum.
+ private const ResourceScope ResTypeMask = ResourceScope.Machine | ResourceScope.Process | ResourceScope.AppDomain | ResourceScope.Library;
+ private const ResourceScope VisibilityMask = ResourceScope.Private | ResourceScope.Assembly;
+
+ [System.Security.SecuritySafeCritical]
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ private static extern int GetRuntimeId();
+
+ public static String MakeVersionSafeName(String name, ResourceScope from, ResourceScope to)
+ {
+ return MakeVersionSafeName(name, from, to, null);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static String MakeVersionSafeName(String name, ResourceScope from, ResourceScope to, Type type)
+ {
+ ResourceScope fromResType = from & ResTypeMask;
+ ResourceScope toResType = to & ResTypeMask;
+ if (fromResType > toResType)
+ throw new ArgumentException(Environment.GetResourceString("Argument_ResourceScopeWrongDirection", fromResType, toResType), "from");
+
+ SxSRequirements requires = GetRequirements(to, from);
+
+ if ((requires & (SxSRequirements.AssemblyName | SxSRequirements.TypeName)) != 0 && type == null)
+ throw new ArgumentNullException("type", Environment.GetResourceString("ArgumentNull_TypeRequiredByResourceScope"));
+
+ // Add in process ID, CLR base address, and appdomain ID's. Also, use a character identifier
+ // to ensure that these can never accidentally overlap (ie, you create enough appdomains and your
+ // appdomain ID might equal your process ID).
+ StringBuilder safeName = new StringBuilder(name);
+ char separator = '_';
+ if ((requires & SxSRequirements.ProcessID) != 0) {
+ safeName.Append(separator);
+ safeName.Append('p');
+ safeName.Append(Win32Native.GetCurrentProcessId());
+ }
+ if ((requires & SxSRequirements.CLRInstanceID) != 0) {
+ String clrID = GetCLRInstanceString();
+ safeName.Append(separator);
+ safeName.Append('r');
+ safeName.Append(clrID);
+ }
+ if ((requires & SxSRequirements.AppDomainID) != 0) {
+ safeName.Append(separator);
+ safeName.Append("ad");
+ safeName.Append(AppDomain.CurrentDomain.Id);
+ }
+ if ((requires & SxSRequirements.TypeName) != 0) {
+ safeName.Append(separator);
+ safeName.Append(type.Name);
+ }
+ if ((requires & SxSRequirements.AssemblyName) != 0) {
+ safeName.Append(separator);
+ safeName.Append(type.Assembly.FullName);
+ }
+ return safeName.ToString();
+ }
+
+ private static String GetCLRInstanceString()
+ {
+ int id = GetRuntimeId();
+ return id.ToString(CultureInfo.InvariantCulture);
+ }
+
+ private static SxSRequirements GetRequirements(ResourceScope consumeAsScope, ResourceScope calleeScope)
+ {
+ SxSRequirements requires = SxSRequirements.None;
+
+ switch(calleeScope & ResTypeMask) {
+ case ResourceScope.Machine:
+ switch(consumeAsScope & ResTypeMask) {
+ case ResourceScope.Machine:
+ // No work
+ break;
+
+ case ResourceScope.Process:
+ requires |= SxSRequirements.ProcessID;
+ break;
+
+ case ResourceScope.AppDomain:
+ requires |= SxSRequirements.AppDomainID | SxSRequirements.CLRInstanceID | SxSRequirements.ProcessID;
+ break;
+
+ default:
+ throw new ArgumentException(Environment.GetResourceString("Argument_BadResourceScopeTypeBits", consumeAsScope), "consumeAsScope");
+ }
+ break;
+
+ case ResourceScope.Process:
+ if ((consumeAsScope & ResourceScope.AppDomain) != 0)
+ requires |= SxSRequirements.AppDomainID | SxSRequirements.CLRInstanceID;
+ break;
+
+ case ResourceScope.AppDomain:
+ // No work
+ break;
+
+ default:
+ throw new ArgumentException(Environment.GetResourceString("Argument_BadResourceScopeTypeBits", calleeScope), "calleeScope");
+ }
+
+ switch(calleeScope & VisibilityMask) {
+ case ResourceScope.None: // Public - implied
+ switch(consumeAsScope & VisibilityMask) {
+ case ResourceScope.None: // Public - implied
+ // No work
+ break;
+
+ case ResourceScope.Assembly:
+ requires |= SxSRequirements.AssemblyName;
+ break;
+
+ case ResourceScope.Private:
+ requires |= SxSRequirements.TypeName | SxSRequirements.AssemblyName;
+ break;
+
+ default:
+ throw new ArgumentException(Environment.GetResourceString("Argument_BadResourceScopeVisibilityBits", consumeAsScope), "consumeAsScope");
+ }
+ break;
+
+ case ResourceScope.Assembly:
+ if ((consumeAsScope & ResourceScope.Private) != 0)
+ requires |= SxSRequirements.TypeName;
+ break;
+
+ case ResourceScope.Private:
+ // No work
+ break;
+
+ default:
+ throw new ArgumentException(Environment.GetResourceString("Argument_BadResourceScopeVisibilityBits", calleeScope), "calleeScope");
+ }
+
+ if (consumeAsScope == calleeScope) {
+ Contract.Assert(requires == SxSRequirements.None, "Computed a strange set of required resource scoping. It's probably wrong.");
+ }
+
+ return requires;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/Versioning/TargetFrameworkAttribute.cs b/src/mscorlib/src/System/Runtime/Versioning/TargetFrameworkAttribute.cs
new file mode 100644
index 0000000000..dbf98c08d8
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/Versioning/TargetFrameworkAttribute.cs
@@ -0,0 +1,45 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+/*============================================================
+**
+**
+**
+** Purpose: Identifies which SKU and version of the .NET
+** Framework that a particular library was compiled against.
+** Emitted by VS, and can help catch deployment problems.
+**
+===========================================================*/
+using System;
+using System.Diagnostics.Contracts;
+
+namespace System.Runtime.Versioning {
+
+ [AttributeUsageAttribute(AttributeTargets.Assembly, AllowMultiple = false, Inherited = false)]
+ public sealed class TargetFrameworkAttribute : Attribute {
+ private String _frameworkName; // A target framework moniker
+ private String _frameworkDisplayName;
+
+ // The frameworkName parameter is intended to be the string form of a FrameworkName instance.
+ public TargetFrameworkAttribute(String frameworkName)
+ {
+ if (frameworkName == null)
+ throw new ArgumentNullException("frameworkName");
+ Contract.EndContractBlock();
+ _frameworkName = frameworkName;
+ }
+
+ // The target framework moniker that this assembly was compiled against.
+ // Use the FrameworkName class to interpret target framework monikers.
+ public String FrameworkName {
+ get { return _frameworkName; }
+ }
+
+ public String FrameworkDisplayName {
+ get { return _frameworkDisplayName; }
+ set { _frameworkDisplayName = value; }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/Versioning/TargetFrameworkId.cs b/src/mscorlib/src/System/Runtime/Versioning/TargetFrameworkId.cs
new file mode 100644
index 0000000000..0a5e668a92
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/Versioning/TargetFrameworkId.cs
@@ -0,0 +1,28 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Purpose: Describe the target framework of the application or AppDomain.
+**
+===========================================================*/
+using System;
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.Versioning
+{
+ // What type of .NET Framework was this application compiled against?
+ [FriendAccessAllowed]
+ internal enum TargetFrameworkId
+ {
+ NotYetChecked = 0,
+ Unrecognized = 1, // Unknown type, such as a new SKU (like watches or cars)
+ Unspecified = 2, // The TargetFrameworkAttribute was created in v4.0. And apps compiled outside VS will not have this attribute.
+ NetFramework = 3, // Desktop - Client or Server or ServerCore.
+ Portable = 4, // Portable Library v1 Note: We do not expect people to build executables against portable libraries!
+ NetCore = 5, // .NET Core = Windows 8 Immersive and Portable Library v2+
+ Silverlight = 6, // Silverlight but not the Phone
+ Phone = 7, // Windows Phone 7 or higher
+ }
+}