internal String GetResourceString(String key) { if (key == null || key.Length == 0) { BCLDebug.Assert(false, "Environment::GetResourceString with null or empty key. Bug in caller, or weird recursive loading problem?"); return("[Resource lookup failed - null or empty resource name]"); } // We have a somewhat common potential for infinite // loops with mscorlib's ResourceManager. If "potentially dangerous" // code throws an exception, we will get into an infinite loop // inside the ResourceManager and this "potentially dangerous" code. // Potentially dangerous code includes the IO package, CultureInfo, // parts of the loader, some parts of Reflection, Security (including // custom user-written permissions that may parse an XML file at // class load time), assembly load event handlers, etc. Essentially, // this is not a bounded set of code, and we need to fix the problem. // Fortunately, this is limited to mscorlib's error lookups and is NOT // a general problem for all user code using the ResourceManager. // The solution is to make sure only one thread at a time can call // GetResourceString. Also, since resource lookups can be // reentrant, if the same thread comes into GetResourceString // twice looking for the exact same resource name before // returning, we're going into an infinite loop and we should // return a bogus string. GetResourceStringUserData userData = new GetResourceStringUserData(this, key); RuntimeHelpers.TryCode tryCode = new RuntimeHelpers.TryCode(GetResourceStringCode); RuntimeHelpers.CleanupCode cleanupCode = new RuntimeHelpers.CleanupCode(GetResourceStringBackoutCode); RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(tryCode, cleanupCode, userData); return(userData.m_retVal); }
private void GetResourceStringCode(object userDataIn) { GetResourceStringUserData data = (GetResourceStringUserData)userDataIn; Environment.ResourceHelper resourceHelper = data.m_resourceHelper; string key = data.m_key; CultureInfo culture = data.m_culture; Monitor.Enter(resourceHelper, ref data.m_lockWasTaken); if (((resourceHelper.currentlyLoading != null) && (resourceHelper.currentlyLoading.Count > 0)) && resourceHelper.currentlyLoading.Contains(key)) { try { new StackTrace(true).ToString(StackTrace.TraceFormat.NoResourceLookup); } catch (StackOverflowException) { } catch (NullReferenceException) { } catch (OutOfMemoryException) { } data.m_retVal = "[Resource lookup failed - infinite recursion or critical failure detected.]"; } else { if (resourceHelper.currentlyLoading == null) { resourceHelper.currentlyLoading = new Stack(4); } if (!resourceHelper.resourceManagerInited) { RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { RuntimeHelpers.RunClassConstructor(typeof(ResourceManager).TypeHandle); RuntimeHelpers.RunClassConstructor(typeof(ResourceReader).TypeHandle); RuntimeHelpers.RunClassConstructor(typeof(RuntimeResourceSet).TypeHandle); RuntimeHelpers.RunClassConstructor(typeof(BinaryReader).TypeHandle); resourceHelper.resourceManagerInited = true; } } resourceHelper.currentlyLoading.Push(key); if (resourceHelper.SystemResMgr == null) { resourceHelper.SystemResMgr = new ResourceManager(this.m_name, typeof(object).Assembly); } string str2 = resourceHelper.SystemResMgr.GetString(key, null); resourceHelper.currentlyLoading.Pop(); data.m_retVal = str2; } }
internal string GetResourceString(string key, CultureInfo culture) { if ((key == null) || (key.Length == 0)) { return("[Resource lookup failed - null or empty resource name]"); } GetResourceStringUserData userData = new GetResourceStringUserData(this, key, culture); RuntimeHelpers.TryCode code = new RuntimeHelpers.TryCode(this.GetResourceStringCode); RuntimeHelpers.CleanupCode backoutCode = new RuntimeHelpers.CleanupCode(this.GetResourceStringBackoutCode); RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(code, backoutCode, userData); return(userData.m_retVal); }
private void GetResourceStringBackoutCode(object userDataIn, bool exceptionThrown) { GetResourceStringUserData data = (GetResourceStringUserData)userDataIn; Environment.ResourceHelper resourceHelper = data.m_resourceHelper; if (exceptionThrown && data.m_lockWasTaken) { resourceHelper.SystemResMgr = null; resourceHelper.currentlyLoading = null; } if (data.m_lockWasTaken) { Monitor.Exit(resourceHelper); } }
private void GetResourceStringBackoutCode(Object userDataIn, bool exceptionThrown) { GetResourceStringUserData userData = (GetResourceStringUserData)userDataIn; ResourceHelper rh = userData.m_resourceHelper; if (exceptionThrown) { if (userData.m_lockWasTaken) { // Backout code - throw away potentially corrupt state rh.SystemResMgr = null; rh.currentlyLoading = null; } } // Release the lock, if we took it. if (userData.m_lockWasTaken) { Monitor.Exit(rh); } }
internal String GetResourceString(String key, CultureInfo culture) { if (key == null || key.Length == 0) { Contract.Assert(false, "Environment::GetResourceString with null or empty key. Bug in caller, or weird recursive loading problem?"); return "[Resource lookup failed - null or empty resource name]"; } #if FEATURE_SPLIT_RESOURCES if (UseFallback()) { return null; } #endif // FEATURE_SPLIT_RESOURCES // We have a somewhat common potential for infinite // loops with mscorlib's ResourceManager. If "potentially dangerous" // code throws an exception, we will get into an infinite loop // inside the ResourceManager and this "potentially dangerous" code. // Potentially dangerous code includes the IO package, CultureInfo, // parts of the loader, some parts of Reflection, Security (including // custom user-written permissions that may parse an XML file at // class load time), assembly load event handlers, etc. Essentially, // this is not a bounded set of code, and we need to fix the problem. // Fortunately, this is limited to mscorlib's error lookups and is NOT // a general problem for all user code using the ResourceManager. // The solution is to make sure only one thread at a time can call // GetResourceString. Also, since resource lookups can be // reentrant, if the same thread comes into GetResourceString // twice looking for the exact same resource name before // returning, we're going into an infinite loop and we should // return a bogus string. GetResourceStringUserData userData = new GetResourceStringUserData(this, key, culture); RuntimeHelpers.TryCode tryCode = new RuntimeHelpers.TryCode(GetResourceStringCode); RuntimeHelpers.CleanupCode cleanupCode = new RuntimeHelpers.CleanupCode(GetResourceStringBackoutCode); RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(tryCode, cleanupCode, userData); return userData.m_retVal; }
private void GetResourceStringCode(Object userDataIn) { GetResourceStringUserData userData = (GetResourceStringUserData)userDataIn; ResourceHelper rh = userData.m_resourceHelper; String key = userData.m_key; Monitor.ReliableEnter(rh, ref userData.m_lockWasTaken); // Are we recursively looking up the same resource? if (rh.currentlyLoading != null && rh.currentlyLoading.Count > 0 && rh.currentlyLoading.Contains(key)) { // This is often a bug in the BCL, security, NLS+ code, // or the loader somewhere. However, this could also // be a setup problem - check whether mscorlib & // mscorwks are both of the same build flavor. String stackTrace = "[Couldn't get a stack trace]"; try { StackTrace st = new StackTrace(true); // Don't attempt to localize strings in this stack trace, otherwise it could cause // infinite recursion. This stack trace is used for an Assert message only, and // so the lack of localization should not be an issue. stackTrace = st.ToString(System.Diagnostics.StackTrace.TraceFormat.NoResourceLookup); } catch (StackOverflowException) {} catch (NullReferenceException) {} catch (OutOfMemoryException) {} BCLDebug.Assert(false, "Infinite recursion during resource lookup. Resource name: " + key + "\r\n" + stackTrace); // Note: can't append the key name, since that may require // an extra allocation... userData.m_retVal = "[Resource lookup failed - infinite recursion or critical failure detected.]"; return; } if (rh.currentlyLoading == null) { rh.currentlyLoading = new Stack(4); } // Call class constructors preemptively, so that we cannot get into an infinite // loop constructing a TypeInitializationException. If this were omitted, // we could get the Infinite recursion assert above by failing type initialization // between the Push and Pop calls below. if (!rh.resourceManagerInited) { // process-critical code here. No ThreadAbortExceptions // can be thrown here. Other exceptions percolate as normal. RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { RuntimeHelpers.RunClassConstructor(typeof(ResourceManager).TypeHandle); RuntimeHelpers.RunClassConstructor(typeof(ResourceReader).TypeHandle); RuntimeHelpers.RunClassConstructor(typeof(RuntimeResourceSet).TypeHandle); RuntimeHelpers.RunClassConstructor(typeof(BinaryReader).TypeHandle); rh.resourceManagerInited = true; } } rh.currentlyLoading.Push(key); if (rh.SystemResMgr == null) { rh.SystemResMgr = new ResourceManager("mscorlib", typeof(Object).Assembly); } String s = rh.SystemResMgr.GetString(key, null); rh.currentlyLoading.Pop(); BCLDebug.Assert(s != null, "Managed resource string lookup failed. Was your resource name misspelled? Did you rebuild mscorlib after adding a resource to resources.txt? Debug this w/ cordbg and bug whoever owns the code that called rhironment.GetResourceString. Resource name was: \"" + key + "\""); userData.m_retVal = s; }
internal string GetResourceString(string key, CultureInfo culture) { if ((key == null) || (key.Length == 0)) { return "[Resource lookup failed - null or empty resource name]"; } GetResourceStringUserData userData = new GetResourceStringUserData(this, key, culture); RuntimeHelpers.TryCode code = new RuntimeHelpers.TryCode(this.GetResourceStringCode); RuntimeHelpers.CleanupCode backoutCode = new RuntimeHelpers.CleanupCode(this.GetResourceStringBackoutCode); RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(code, backoutCode, userData); return userData.m_retVal; }