diff options
Diffstat (limited to 'src/mscorlib/src/System/Resources/ManifestBasedResourceGroveler.cs')
-rw-r--r-- | src/mscorlib/src/System/Resources/ManifestBasedResourceGroveler.cs | 677 |
1 files changed, 677 insertions, 0 deletions
diff --git a/src/mscorlib/src/System/Resources/ManifestBasedResourceGroveler.cs b/src/mscorlib/src/System/Resources/ManifestBasedResourceGroveler.cs new file mode 100644 index 0000000000..5fd0daad09 --- /dev/null +++ b/src/mscorlib/src/System/Resources/ManifestBasedResourceGroveler.cs @@ -0,0 +1,677 @@ +// 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: Searches for resources in Assembly manifest, used +** for assembly-based resource lookup. +** +** +===========================================================*/ +namespace System.Resources { + + using System; + using System.Collections; + using System.Collections.Generic; + using System.Globalization; + using System.IO; + using System.Reflection; + using System.Runtime.InteropServices; + using System.Runtime.CompilerServices; + using System.Runtime.Versioning; + using System.Text; + using System.Threading; + using System.Diagnostics.Contracts; + using Microsoft.Win32; + +#if !FEATURE_CORECLR + using System.Diagnostics.Tracing; +#endif + + // + // Note: this type is integral to the construction of exception objects, + // and sometimes this has to be done in low memory situtations (OOM) or + // to create TypeInitializationExceptions due to failure of a static class + // constructor. This type needs to be extremely careful and assume that + // any type it references may have previously failed to construct, so statics + // belonging to that type may not be initialized. FrameworkEventSource.Log + // is one such example. + // + internal class ManifestBasedResourceGroveler : IResourceGroveler + { + + private ResourceManager.ResourceManagerMediator _mediator; + + public ManifestBasedResourceGroveler(ResourceManager.ResourceManagerMediator mediator) + { + // here and below: convert asserts to preconditions where appropriate when we get + // contracts story in place. + Contract.Requires(mediator != null, "mediator shouldn't be null; check caller"); + _mediator = mediator; + } + + [System.Security.SecuritySafeCritical] + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public ResourceSet GrovelForResourceSet(CultureInfo culture, Dictionary<String, ResourceSet> localResourceSets, bool tryParents, bool createIfNotExists, ref StackCrawlMark stackMark) + { + Contract.Assert(culture != null, "culture shouldn't be null; check caller"); + Contract.Assert(localResourceSets != null, "localResourceSets shouldn't be null; check caller"); + + ResourceSet rs = null; + Stream stream = null; + RuntimeAssembly satellite = null; + + // 1. Fixups for ultimate fallbacks + CultureInfo lookForCulture = UltimateFallbackFixup(culture); + + // 2. Look for satellite assembly or main assembly, as appropriate + if (lookForCulture.HasInvariantCultureName && _mediator.FallbackLoc == UltimateResourceFallbackLocation.MainAssembly) + { + // don't bother looking in satellites in this case + satellite = _mediator.MainAssembly; + } +#if RESOURCE_SATELLITE_CONFIG + // If our config file says the satellite isn't here, don't ask for it. + else if (!lookForCulture.HasInvariantCultureName && !_mediator.TryLookingForSatellite(lookForCulture)) + { + satellite = null; + } +#endif + else + { + satellite = GetSatelliteAssembly(lookForCulture, ref stackMark); + + if (satellite == null) + { + bool raiseException = (culture.HasInvariantCultureName && (_mediator.FallbackLoc == UltimateResourceFallbackLocation.Satellite)); + // didn't find satellite, give error if necessary + if (raiseException) + { + HandleSatelliteMissing(); + } + } + } + + // get resource file name we'll search for. Note, be careful if you're moving this statement + // around because lookForCulture may be modified from originally requested culture above. + String fileName = _mediator.GetResourceFileName(lookForCulture); + + // 3. If we identified an assembly to search; look in manifest resource stream for resource file + if (satellite != null) + { + // Handle case in here where someone added a callback for assembly load events. + // While no other threads have called into GetResourceSet, our own thread can! + // At that point, we could already have an RS in our hash table, and we don't + // want to add it twice. + lock (localResourceSets) + { + if (localResourceSets.TryGetValue(culture.Name, out rs)) + { +#if !FEATURE_CORECLR + if (FrameworkEventSource.IsInitialized) + { + FrameworkEventSource.Log.ResourceManagerFoundResourceSetInCacheUnexpected(_mediator.BaseName, _mediator.MainAssembly, culture.Name); + } +#endif + } + } + + stream = GetManifestResourceStream(satellite, fileName, ref stackMark); + } + +#if !FEATURE_CORECLR + if (FrameworkEventSource.IsInitialized) + { + if (stream != null) + { + FrameworkEventSource.Log.ResourceManagerStreamFound(_mediator.BaseName, _mediator.MainAssembly, culture.Name, satellite, fileName); + } + else + { + FrameworkEventSource.Log.ResourceManagerStreamNotFound(_mediator.BaseName, _mediator.MainAssembly, culture.Name, satellite, fileName); + } + } +#endif + + // 4a. Found a stream; create a ResourceSet if possible + if (createIfNotExists && stream != null && rs == null) + { +#if !FEATURE_CORECLR + if (FrameworkEventSource.IsInitialized) + { + FrameworkEventSource.Log.ResourceManagerCreatingResourceSet(_mediator.BaseName, _mediator.MainAssembly, culture.Name, fileName); + } +#endif + rs = CreateResourceSet(stream, satellite); + } + else if (stream == null && tryParents) + { + // 4b. Didn't find stream; give error if necessary + bool raiseException = culture.HasInvariantCultureName; + if (raiseException) + { + HandleResourceStreamMissing(fileName); + } + } + +#if !FEATURE_CORECLR + if (!createIfNotExists && stream != null && rs == null) + { + if (FrameworkEventSource.IsInitialized) + { + FrameworkEventSource.Log.ResourceManagerNotCreatingResourceSet(_mediator.BaseName, _mediator.MainAssembly, culture.Name); + } + } +#endif + + return rs; + } + +#if !FEATURE_CORECLR + // Returns whether or not the main assembly contains a particular resource + // file in it's assembly manifest. Used to verify that the neutral + // Culture's .resources file is present in the main assembly + public bool HasNeutralResources(CultureInfo culture, String defaultResName) + { + String resName = defaultResName; + if (_mediator.LocationInfo != null && _mediator.LocationInfo.Namespace != null) + resName = _mediator.LocationInfo.Namespace + Type.Delimiter + defaultResName; + String[] resourceFiles = _mediator.MainAssembly.GetManifestResourceNames(); + foreach(String s in resourceFiles) + if (s.Equals(resName)) + return true; + return false; + } +#endif + + private CultureInfo UltimateFallbackFixup(CultureInfo lookForCulture) + { + + CultureInfo returnCulture = lookForCulture; + + // If our neutral resources were written in this culture AND we know the main assembly + // does NOT contain neutral resources, don't probe for this satellite. + if (lookForCulture.Name == _mediator.NeutralResourcesCulture.Name && + _mediator.FallbackLoc == UltimateResourceFallbackLocation.MainAssembly) + { +#if !FEATURE_CORECLR + if (FrameworkEventSource.IsInitialized) + { + FrameworkEventSource.Log.ResourceManagerNeutralResourcesSufficient(_mediator.BaseName, _mediator.MainAssembly, lookForCulture.Name); + } +#endif + + returnCulture = CultureInfo.InvariantCulture; + } + else if (lookForCulture.HasInvariantCultureName && _mediator.FallbackLoc == UltimateResourceFallbackLocation.Satellite) + { + returnCulture = _mediator.NeutralResourcesCulture; + } + + return returnCulture; + + } + + [System.Security.SecurityCritical] + internal static CultureInfo GetNeutralResourcesLanguage(Assembly a, ref UltimateResourceFallbackLocation fallbackLocation) + { + Contract.Assert(a != null, "assembly != null"); + string cultureName = null; + short fallback = 0; + if (GetNeutralResourcesLanguageAttribute(((RuntimeAssembly)a).GetNativeHandle(), + JitHelpers.GetStringHandleOnStack(ref cultureName), + out fallback)) { + if ((UltimateResourceFallbackLocation)fallback < UltimateResourceFallbackLocation.MainAssembly || (UltimateResourceFallbackLocation)fallback > UltimateResourceFallbackLocation.Satellite) { + throw new ArgumentException(Environment.GetResourceString("Arg_InvalidNeutralResourcesLanguage_FallbackLoc", fallback)); + } + fallbackLocation = (UltimateResourceFallbackLocation)fallback; + } + else { +#if !FEATURE_CORECLR + if (FrameworkEventSource.IsInitialized) { + FrameworkEventSource.Log.ResourceManagerNeutralResourceAttributeMissing(a); + } +#endif + fallbackLocation = UltimateResourceFallbackLocation.MainAssembly; + return CultureInfo.InvariantCulture; + } + + try + { + CultureInfo c = CultureInfo.GetCultureInfo(cultureName); + return c; + } + catch (ArgumentException e) + { // we should catch ArgumentException only. + // Note we could go into infinite loops if mscorlib's + // NeutralResourcesLanguageAttribute is mangled. If this assert + // fires, please fix the build process for the BCL directory. + if (a == typeof(Object).Assembly) + { + Contract.Assert(false, System.CoreLib.Name+"'s NeutralResourcesLanguageAttribute is a malformed culture name! name: \"" + cultureName + "\" Exception: " + e); + return CultureInfo.InvariantCulture; + } + + throw new ArgumentException(Environment.GetResourceString("Arg_InvalidNeutralResourcesLanguage_Asm_Culture", a.ToString(), cultureName), e); + } + } + + // Constructs a new ResourceSet for a given file name. The logic in + // here avoids a ReflectionPermission check for our RuntimeResourceSet + // for perf and working set reasons. + // Use the assembly to resolve assembly manifest resource references. + // Note that is can be null, but probably shouldn't be. + // This method could use some refactoring. One thing at a time. + [System.Security.SecurityCritical] + internal ResourceSet CreateResourceSet(Stream store, Assembly assembly) + { + Contract.Assert(store != null, "I need a Stream!"); + // Check to see if this is a Stream the ResourceManager understands, + // and check for the correct resource reader type. + if (store.CanSeek && store.Length > 4) + { + long startPos = store.Position; + + // not disposing because we want to leave stream open + BinaryReader br = new BinaryReader(store); + + // Look for our magic number as a little endian Int32. + int bytes = br.ReadInt32(); + if (bytes == ResourceManager.MagicNumber) + { + int resMgrHeaderVersion = br.ReadInt32(); + String readerTypeName = null, resSetTypeName = null; + if (resMgrHeaderVersion == ResourceManager.HeaderVersionNumber) + { + br.ReadInt32(); // We don't want the number of bytes to skip. + readerTypeName = System.CoreLib.FixupCoreLibName(br.ReadString()); + resSetTypeName = System.CoreLib.FixupCoreLibName(br.ReadString()); + } + else if (resMgrHeaderVersion > ResourceManager.HeaderVersionNumber) + { + // Assume that the future ResourceManager headers will + // have two strings for us - the reader type name and + // resource set type name. Read those, then use the num + // bytes to skip field to correct our position. + int numBytesToSkip = br.ReadInt32(); + long endPosition = br.BaseStream.Position + numBytesToSkip; + + readerTypeName = System.CoreLib.FixupCoreLibName(br.ReadString()); + resSetTypeName = System.CoreLib.FixupCoreLibName(br.ReadString()); + + br.BaseStream.Seek(endPosition, SeekOrigin.Begin); + } + else + { + // resMgrHeaderVersion is older than this ResMgr version. + // We should add in backwards compatibility support here. + + throw new NotSupportedException(Environment.GetResourceString("NotSupported_ObsoleteResourcesFile", _mediator.MainAssembly.GetSimpleName())); + } + + store.Position = startPos; + // Perf optimization - Don't use Reflection for our defaults. + // Note there are two different sets of strings here - the + // assembly qualified strings emitted by ResourceWriter, and + // the abbreviated ones emitted by InternalResGen. + if (CanUseDefaultResourceClasses(readerTypeName, resSetTypeName)) + { + RuntimeResourceSet rs; +#if LOOSELY_LINKED_RESOURCE_REFERENCE + rs = new RuntimeResourceSet(store, assembly); +#else + rs = new RuntimeResourceSet(store); +#endif // LOOSELY_LINKED_RESOURCE_REFERENCE + return rs; + } + else + { + // we do not want to use partial binding here. + Type readerType = Type.GetType(readerTypeName, true); + Object[] args = new Object[1]; + args[0] = store; + IResourceReader reader = (IResourceReader)Activator.CreateInstance(readerType, args); + + Object[] resourceSetArgs = +#if LOOSELY_LINKED_RESOURCE_REFERENCE + new Object[2]; +#else + new Object[1]; +#endif // LOOSELY_LINKED_RESOURCE_REFERENCE + resourceSetArgs[0] = reader; +#if LOOSELY_LINKED_RESOURCE_REFERENCE + resourceSetArgs[1] = assembly; +#endif // LOOSELY_LINKED_RESOURCE_REFERENCE + Type resSetType; + if (_mediator.UserResourceSet == null) + { + Contract.Assert(resSetTypeName != null, "We should have a ResourceSet type name from the custom resource file here."); + resSetType = Type.GetType(resSetTypeName, true, false); + } + else + resSetType = _mediator.UserResourceSet; + ResourceSet rs = (ResourceSet)Activator.CreateInstance(resSetType, + BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.CreateInstance, + null, + resourceSetArgs, + null, + null); + return rs; + } + } + else + { + store.Position = startPos; + } + + } + + if (_mediator.UserResourceSet == null) + { + // Explicitly avoid CreateInstance if possible, because it + // requires ReflectionPermission to call private & protected + // constructors. +#if LOOSELY_LINKED_RESOURCE_REFERENCE + return new RuntimeResourceSet(store, assembly); +#else + return new RuntimeResourceSet(store); +#endif // LOOSELY_LINKED_RESOURCE_REFERENCE + } + else + { + Object[] args = new Object[2]; + args[0] = store; + args[1] = assembly; + try + { + ResourceSet rs = null; + // Add in a check for a constructor taking in an assembly first. + try + { + rs = (ResourceSet)Activator.CreateInstance(_mediator.UserResourceSet, args); + return rs; + } + catch (MissingMethodException) { } + + args = new Object[1]; + args[0] = store; + rs = (ResourceSet)Activator.CreateInstance(_mediator.UserResourceSet, args); +#if LOOSELY_LINKED_RESOURCE_REFERENCE + rs.Assembly = assembly; +#endif // LOOSELY_LINKED_RESOURCE_REFERENCE + return rs; + } + catch (MissingMethodException e) + { + throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ResMgrBadResSet_Type", _mediator.UserResourceSet.AssemblyQualifiedName), e); + } + } + } + + [System.Security.SecurityCritical] + private Stream GetManifestResourceStream(RuntimeAssembly satellite, String fileName, ref StackCrawlMark stackMark) + { + Contract.Requires(satellite != null, "satellite shouldn't be null; check caller"); + Contract.Requires(fileName != null, "fileName shouldn't be null; check caller"); + + // If we're looking in the main assembly AND if the main assembly was the person who + // created the ResourceManager, skip a security check for private manifest resources. + bool canSkipSecurityCheck = (_mediator.MainAssembly == satellite) + && (_mediator.CallingAssembly == _mediator.MainAssembly); + + Stream stream = satellite.GetManifestResourceStream(_mediator.LocationInfo, fileName, canSkipSecurityCheck, ref stackMark); + if (stream == null) + { + stream = CaseInsensitiveManifestResourceStreamLookup(satellite, fileName); + } + + return stream; + } + + // Looks up a .resources file in the assembly manifest using + // case-insensitive lookup rules. Yes, this is slow. The metadata + // dev lead refuses to make all assembly manifest resource lookups case-insensitive, + // even optionally case-insensitive. + [System.Security.SecurityCritical] + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + private Stream CaseInsensitiveManifestResourceStreamLookup(RuntimeAssembly satellite, String name) + { + Contract.Requires(satellite != null, "satellite shouldn't be null; check caller"); + Contract.Requires(name != null, "name shouldn't be null; check caller"); + + StringBuilder sb = new StringBuilder(); + if (_mediator.LocationInfo != null) + { + String nameSpace = _mediator.LocationInfo.Namespace; + if (nameSpace != null) + { + sb.Append(nameSpace); + if (name != null) + sb.Append(Type.Delimiter); + } + } + sb.Append(name); + + String givenName = sb.ToString(); + CompareInfo comparer = CultureInfo.InvariantCulture.CompareInfo; + String canonicalName = null; + foreach (String existingName in satellite.GetManifestResourceNames()) + { + if (comparer.Compare(existingName, givenName, CompareOptions.IgnoreCase) == 0) + { + if (canonicalName == null) + { + canonicalName = existingName; + } + else + { + throw new MissingManifestResourceException(Environment.GetResourceString("MissingManifestResource_MultipleBlobs", givenName, satellite.ToString())); + } + } + } + +#if !FEATURE_CORECLR + if (FrameworkEventSource.IsInitialized) + { + if (canonicalName != null) + { + FrameworkEventSource.Log.ResourceManagerCaseInsensitiveResourceStreamLookupSucceeded(_mediator.BaseName, _mediator.MainAssembly, satellite.GetSimpleName(), givenName); + } + else + { + FrameworkEventSource.Log.ResourceManagerCaseInsensitiveResourceStreamLookupFailed(_mediator.BaseName, _mediator.MainAssembly, satellite.GetSimpleName(), givenName); + } + } +#endif + + if (canonicalName == null) + { + return null; + } + // If we're looking in the main assembly AND if the main + // assembly was the person who created the ResourceManager, + // skip a security check for private manifest resources. + bool canSkipSecurityCheck = _mediator.MainAssembly == satellite && _mediator.CallingAssembly == _mediator.MainAssembly; + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + Stream s = satellite.GetManifestResourceStream(canonicalName, ref stackMark, canSkipSecurityCheck); + // GetManifestResourceStream will return null if we don't have + // permission to read this stream from the assembly. For example, + // if the stream is private and we're trying to access it from another + // assembly (ie, ResMgr in mscorlib accessing anything else), we + // require Reflection TypeInformation permission to be able to read + // this. +#if !FEATURE_CORECLR + if (s!=null) { + if (FrameworkEventSource.IsInitialized) + { + FrameworkEventSource.Log.ResourceManagerManifestResourceAccessDenied(_mediator.BaseName, _mediator.MainAssembly, satellite.GetSimpleName(), canonicalName); + } + } +#endif + return s; + } + + [System.Security.SecurityCritical] + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + private RuntimeAssembly GetSatelliteAssembly(CultureInfo lookForCulture, ref StackCrawlMark stackMark) + { + if (!_mediator.LookedForSatelliteContractVersion) + { + _mediator.SatelliteContractVersion = _mediator.ObtainSatelliteContractVersion(_mediator.MainAssembly); + _mediator.LookedForSatelliteContractVersion = true; + } + + RuntimeAssembly satellite = null; + String satAssemblyName = GetSatelliteAssemblyName(); + + // Look up the satellite assembly, but don't let problems + // like a partially signed satellite assembly stop us from + // doing fallback and displaying something to the user. + // Yet also somehow log this error for a developer. + try + { + satellite = _mediator.MainAssembly.InternalGetSatelliteAssembly(satAssemblyName, lookForCulture, _mediator.SatelliteContractVersion, false, ref stackMark); + } + + // Jun 08: for cases other than ACCESS_DENIED, we'll assert instead of throw to give release builds more opportunity to fallback. + + catch (FileLoadException fle) + { + // Ignore cases where the loader gets an access + // denied back from the OS. This showed up for + // href-run exe's at one point. + int hr = fle._HResult; + if (hr != Win32Native.MakeHRFromErrorCode(Win32Native.ERROR_ACCESS_DENIED)) + { + Contract.Assert(false, "[This assert catches satellite assembly build/deployment problems - report this message to your build lab & loc engineer]" + Environment.NewLine + "GetSatelliteAssembly failed for culture " + lookForCulture.Name + " and version " + (_mediator.SatelliteContractVersion == null ? _mediator.MainAssembly.GetVersion().ToString() : _mediator.SatelliteContractVersion.ToString()) + " of assembly " + _mediator.MainAssembly.GetSimpleName() + " with error code 0x" + hr.ToString("X", CultureInfo.InvariantCulture) + Environment.NewLine + "Exception: " + fle); + } + } + + // Don't throw for zero-length satellite assemblies, for compat with v1 + catch (BadImageFormatException bife) + { + Contract.Assert(false, "[This assert catches satellite assembly build/deployment problems - report this message to your build lab & loc engineer]" + Environment.NewLine + "GetSatelliteAssembly failed for culture " + lookForCulture.Name + " and version " + (_mediator.SatelliteContractVersion == null ? _mediator.MainAssembly.GetVersion().ToString() : _mediator.SatelliteContractVersion.ToString()) + " of assembly " + _mediator.MainAssembly.GetSimpleName() + Environment.NewLine + "Exception: " + bife); + } + +#if !FEATURE_CORECLR + if (FrameworkEventSource.IsInitialized) + { + if (satellite != null) + { + FrameworkEventSource.Log.ResourceManagerGetSatelliteAssemblySucceeded(_mediator.BaseName, _mediator.MainAssembly, lookForCulture.Name, satAssemblyName); + } + else + { + FrameworkEventSource.Log.ResourceManagerGetSatelliteAssemblyFailed(_mediator.BaseName, _mediator.MainAssembly, lookForCulture.Name, satAssemblyName); + } + } +#endif + + return satellite; + } + + // Perf optimization - Don't use Reflection for most cases with + // our .resources files. This makes our code run faster and we can + // creating a ResourceReader via Reflection. This would incur + // a security check (since the link-time check on the constructor that + // takes a String is turned into a full demand with a stack walk) + // and causes partially trusted localized apps to fail. + private bool CanUseDefaultResourceClasses(String readerTypeName, String resSetTypeName) + { + Contract.Assert(readerTypeName != null, "readerTypeName shouldn't be null; check caller"); + Contract.Assert(resSetTypeName != null, "resSetTypeName shouldn't be null; check caller"); + + if (_mediator.UserResourceSet != null) + return false; + + // Ignore the actual version of the ResourceReader and + // RuntimeResourceSet classes. Let those classes deal with + // versioning themselves. + AssemblyName mscorlib = new AssemblyName(ResourceManager.MscorlibName); + + if (readerTypeName != null) + { + if (!ResourceManager.CompareNames(readerTypeName, ResourceManager.ResReaderTypeName, mscorlib)) + return false; + } + + if (resSetTypeName != null) + { + if (!ResourceManager.CompareNames(resSetTypeName, ResourceManager.ResSetTypeName, mscorlib)) + return false; + } + + return true; + } + + [System.Security.SecurityCritical] + private String GetSatelliteAssemblyName() + { + String satAssemblyName = _mediator.MainAssembly.GetSimpleName(); + satAssemblyName += ".resources"; + return satAssemblyName; + } + + [System.Security.SecurityCritical] + private void HandleSatelliteMissing() + { + String satAssemName = _mediator.MainAssembly.GetSimpleName() + ".resources.dll"; + if (_mediator.SatelliteContractVersion != null) + { + satAssemName += ", Version=" + _mediator.SatelliteContractVersion.ToString(); + } + + AssemblyName an = new AssemblyName(); + an.SetPublicKey(_mediator.MainAssembly.GetPublicKey()); + byte[] token = an.GetPublicKeyToken(); + + int iLen = token.Length; + StringBuilder publicKeyTok = new StringBuilder(iLen * 2); + for (int i = 0; i < iLen; i++) + { + publicKeyTok.Append(token[i].ToString("x", CultureInfo.InvariantCulture)); + } + satAssemName += ", PublicKeyToken=" + publicKeyTok; + + String missingCultureName = _mediator.NeutralResourcesCulture.Name; + if (missingCultureName.Length == 0) + { + missingCultureName = "<invariant>"; + } + throw new MissingSatelliteAssemblyException(Environment.GetResourceString("MissingSatelliteAssembly_Culture_Name", _mediator.NeutralResourcesCulture, satAssemName), missingCultureName); + } + + [System.Security.SecurityCritical] // auto-generated + private void HandleResourceStreamMissing(String fileName) + { + // Keep people from bothering me about resources problems + if (_mediator.MainAssembly == typeof(Object).Assembly && _mediator.BaseName.Equals(System.CoreLib.Name)) + { + // This would break CultureInfo & all our exceptions. + Contract.Assert(false, "Couldn't get " + System.CoreLib.Name+ResourceManager.ResFileExtension + " from "+System.CoreLib.Name+"'s assembly" + Environment.NewLine + Environment.NewLine + "Are you building the runtime on your machine? Chances are the BCL directory didn't build correctly. Type 'build -c' in the BCL directory. If you get build errors, look at buildd.log. If you then can't figure out what's wrong (and you aren't changing the assembly-related metadata code), ask a BCL dev.\n\nIf you did NOT build the runtime, you shouldn't be seeing this and you've found a bug."); + + // We cannot continue further - simply FailFast. + string mesgFailFast = System.CoreLib.Name + ResourceManager.ResFileExtension + " couldn't be found! Large parts of the BCL won't work!"; + System.Environment.FailFast(mesgFailFast); + } + // We really don't think this should happen - we always + // expect the neutral locale's resources to be present. + String resName = String.Empty; + if (_mediator.LocationInfo != null && _mediator.LocationInfo.Namespace != null) + resName = _mediator.LocationInfo.Namespace + Type.Delimiter; + resName += fileName; + throw new MissingManifestResourceException(Environment.GetResourceString("MissingManifestResource_NoNeutralAsm", resName, _mediator.MainAssembly.GetSimpleName())); + } + + [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] + [System.Security.SecurityCritical] // Our security team doesn't yet allow safe-critical P/Invoke methods. + [System.Security.SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool GetNeutralResourcesLanguageAttribute(RuntimeAssembly assemblyHandle, StringHandleOnStack cultureName, out short fallbackLocation); + } +} |