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;
}