3 // Copyright (c) Microsoft Corporation. All rights reserved.
6 /*============================================================
8 ** Class: ManifestBasedResourceGroveler
10 ** <OWNER>[....]</OWNER>
13 ** Purpose: Searches for resources in Assembly manifest, used
14 ** for assembly-based resource lookup.
17 ===========================================================*/
18 namespace System.Resources {
21 using System.Collections;
22 using System.Collections.Generic;
23 using System.Globalization;
25 using System.Reflection;
26 using System.Runtime.InteropServices;
27 using System.Runtime.CompilerServices;
28 using System.Runtime.Versioning;
30 using System.Threading;
31 using System.Diagnostics.Contracts;
32 using Microsoft.Win32;
35 using System.Diagnostics.Tracing;
39 // Note: this type is integral to the construction of exception objects,
40 // and sometimes this has to be done in low memory situtations (OOM) or
41 // to create TypeInitializationExceptions due to failure of a static class
42 // constructor. This type needs to be extremely careful and assume that
43 // any type it references may have previously failed to construct, so statics
44 // belonging to that type may not be initialized. FrameworkEventSource.Log
45 // is one such example.
47 internal class ManifestBasedResourceGroveler : IResourceGroveler
50 private ResourceManager.ResourceManagerMediator _mediator;
52 public ManifestBasedResourceGroveler(ResourceManager.ResourceManagerMediator mediator)
54 // here and below: convert asserts to preconditions where appropriate when we get
55 // contracts story in place.
56 Contract.Requires(mediator != null, "mediator shouldn't be null; check caller");
60 [System.Security.SecuritySafeCritical]
61 [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
62 public ResourceSet GrovelForResourceSet(CultureInfo culture, Dictionary<String, ResourceSet> localResourceSets, bool tryParents, bool createIfNotExists, ref StackCrawlMark stackMark)
64 Contract.Assert(culture != null, "culture shouldn't be null; check caller");
65 Contract.Assert(localResourceSets != null, "localResourceSets shouldn't be null; check caller");
67 ResourceSet rs = null;
69 RuntimeAssembly satellite = null;
71 // 1. Fixups for ultimate fallbacks
72 CultureInfo lookForCulture = UltimateFallbackFixup(culture);
74 // 2. Look for satellite assembly or main assembly, as appropriate
75 if (lookForCulture.HasInvariantCultureName && _mediator.FallbackLoc == UltimateResourceFallbackLocation.MainAssembly)
77 // don't bother looking in satellites in this case
78 satellite = _mediator.MainAssembly;
80 #if RESOURCE_SATELLITE_CONFIG
81 // If our config file says the satellite isn't here, don't ask for it.
82 else if (!lookForCulture.HasInvariantCultureName && !_mediator.TryLookingForSatellite(lookForCulture))
89 satellite = GetSatelliteAssembly(lookForCulture, ref stackMark);
91 if (satellite == null)
93 bool raiseException = (culture.HasInvariantCultureName && (_mediator.FallbackLoc == UltimateResourceFallbackLocation.Satellite));
94 // didn't find satellite, give error if necessary
97 HandleSatelliteMissing();
102 // get resource file name we'll search for. Note, be careful if you're moving this statement
103 // around because lookForCulture may be modified from originally requested culture above.
104 String fileName = _mediator.GetResourceFileName(lookForCulture);
106 // 3. If we identified an assembly to search; look in manifest resource stream for resource file
107 if (satellite != null)
109 // Handle case in here where someone added a callback for assembly load events.
110 // While no other threads have called into GetResourceSet, our own thread can!
111 // At that point, we could already have an RS in our hash table, and we don't
112 // want to add it twice.
113 lock (localResourceSets)
115 if (localResourceSets.TryGetValue(culture.Name, out rs))
117 #if !FEATURE_CORECLR && !MONO
118 if (FrameworkEventSource.IsInitialized)
120 FrameworkEventSource.Log.ResourceManagerFoundResourceSetInCacheUnexpected(_mediator.BaseName, _mediator.MainAssembly, culture.Name);
126 stream = GetManifestResourceStream(satellite, fileName, ref stackMark);
129 #if !FEATURE_CORECLR && !MONO
130 if (FrameworkEventSource.IsInitialized)
134 FrameworkEventSource.Log.ResourceManagerStreamFound(_mediator.BaseName, _mediator.MainAssembly, culture.Name, satellite, fileName);
138 FrameworkEventSource.Log.ResourceManagerStreamNotFound(_mediator.BaseName, _mediator.MainAssembly, culture.Name, satellite, fileName);
143 // 4a. Found a stream; create a ResourceSet if possible
144 if (createIfNotExists && stream != null && rs == null)
146 #if !FEATURE_CORECLR && !MONO
147 if (FrameworkEventSource.IsInitialized)
149 FrameworkEventSource.Log.ResourceManagerCreatingResourceSet(_mediator.BaseName, _mediator.MainAssembly, culture.Name, fileName);
152 rs = CreateResourceSet(stream, satellite);
154 else if (stream == null && tryParents)
156 // 4b. Didn't find stream; give error if necessary
157 bool raiseException = culture.HasInvariantCultureName;
160 HandleResourceStreamMissing(fileName);
164 #if !FEATURE_CORECLR && !MONO
165 if (!createIfNotExists && stream != null && rs == null)
167 if (FrameworkEventSource.IsInitialized)
169 FrameworkEventSource.Log.ResourceManagerNotCreatingResourceSet(_mediator.BaseName, _mediator.MainAssembly, culture.Name);
178 // Returns whether or not the main assembly contains a particular resource
179 // file in it's assembly manifest. Used to verify that the neutral
180 // Culture's .resources file is present in the main assembly
181 public bool HasNeutralResources(CultureInfo culture, String defaultResName)
183 String resName = defaultResName;
184 if (_mediator.LocationInfo != null && _mediator.LocationInfo.Namespace != null)
185 resName = _mediator.LocationInfo.Namespace + Type.Delimiter + defaultResName;
186 String[] resourceFiles = _mediator.MainAssembly.GetManifestResourceNames();
187 foreach(String s in resourceFiles)
188 if (s.Equals(resName))
194 private CultureInfo UltimateFallbackFixup(CultureInfo lookForCulture)
197 CultureInfo returnCulture = lookForCulture;
199 // If our neutral resources were written in this culture AND we know the main assembly
200 // does NOT contain neutral resources, don't probe for this satellite.
201 if (lookForCulture.Name == _mediator.NeutralResourcesCulture.Name &&
202 _mediator.FallbackLoc == UltimateResourceFallbackLocation.MainAssembly)
204 #if !FEATURE_CORECLR && !MONO
205 if (FrameworkEventSource.IsInitialized)
207 FrameworkEventSource.Log.ResourceManagerNeutralResourcesSufficient(_mediator.BaseName, _mediator.MainAssembly, lookForCulture.Name);
211 returnCulture = CultureInfo.InvariantCulture;
213 else if (lookForCulture.HasInvariantCultureName && _mediator.FallbackLoc == UltimateResourceFallbackLocation.Satellite)
215 returnCulture = _mediator.NeutralResourcesCulture;
218 return returnCulture;
222 [System.Security.SecurityCritical]
223 internal static CultureInfo GetNeutralResourcesLanguage(Assembly a, ref UltimateResourceFallbackLocation fallbackLocation)
226 #if FEATURE_LEGACYNETCF
227 // Windows Phone 7.0/7.1 ignore NeutralResourceLanguage attribute and
228 // defaults fallbackLocation to MainAssembly
229 if (CompatibilitySwitches.IsAppEarlierThanWindowsPhone8)
231 fallbackLocation = UltimateResourceFallbackLocation.MainAssembly;
232 return CultureInfo.InvariantCulture;
236 Contract.Assert(a != null, "assembly != null");
237 string cultureName = null;
241 if (GetNeutralResourcesLanguageAttribute(a, ref cultureName, ref fallback)) {
243 if (GetNeutralResourcesLanguageAttribute(((RuntimeAssembly)a).GetNativeHandle(),
244 JitHelpers.GetStringHandleOnStack(ref cultureName),
247 if ((UltimateResourceFallbackLocation)fallback < UltimateResourceFallbackLocation.MainAssembly || (UltimateResourceFallbackLocation)fallback > UltimateResourceFallbackLocation.Satellite) {
248 throw new ArgumentException(Environment.GetResourceString("Arg_InvalidNeutralResourcesLanguage_FallbackLoc", fallback));
250 fallbackLocation = (UltimateResourceFallbackLocation)fallback;
253 #if !FEATURE_CORECLR && !MONO
254 if (FrameworkEventSource.IsInitialized) {
255 FrameworkEventSource.Log.ResourceManagerNeutralResourceAttributeMissing(a);
258 fallbackLocation = UltimateResourceFallbackLocation.MainAssembly;
259 return CultureInfo.InvariantCulture;
264 CultureInfo c = CultureInfo.GetCultureInfo(cultureName);
267 catch (ArgumentException e)
268 { // we should catch ArgumentException only.
269 // Note we could go into infinite loops if mscorlib's
270 // NeutralResourcesLanguageAttribute is mangled. If this assert
271 // fires, please fix the build process for the BCL directory.
272 if (a == typeof(Object).Assembly)
274 Contract.Assert(false, "mscorlib's NeutralResourcesLanguageAttribute is a malformed culture name! name: \"" + cultureName + "\" Exception: " + e);
275 return CultureInfo.InvariantCulture;
278 throw new ArgumentException(Environment.GetResourceString("Arg_InvalidNeutralResourcesLanguage_Asm_Culture", a.ToString(), cultureName), e);
282 // Constructs a new ResourceSet for a given file name. The logic in
283 // here avoids a ReflectionPermission check for our RuntimeResourceSet
284 // for perf and working set reasons.
285 // Use the assembly to resolve assembly manifest resource references.
286 // Note that is can be null, but probably shouldn't be.
287 // This method could use some refactoring. One thing at a time.
288 [System.Security.SecurityCritical]
289 internal ResourceSet CreateResourceSet(Stream store, Assembly assembly)
291 Contract.Assert(store != null, "I need a Stream!");
292 // Check to see if this is a Stream the ResourceManager understands,
293 // and check for the correct resource reader type.
294 if (store.CanSeek && store.Length > 4)
296 long startPos = store.Position;
298 // not disposing because we want to leave stream open
299 BinaryReader br = new BinaryReader(store);
301 // Look for our magic number as a little endian Int32.
302 int bytes = br.ReadInt32();
303 if (bytes == ResourceManager.MagicNumber)
305 int resMgrHeaderVersion = br.ReadInt32();
306 String readerTypeName = null, resSetTypeName = null;
307 if (resMgrHeaderVersion == ResourceManager.HeaderVersionNumber)
309 br.ReadInt32(); // We don't want the number of bytes to skip.
310 readerTypeName = br.ReadString();
311 resSetTypeName = br.ReadString();
313 else if (resMgrHeaderVersion > ResourceManager.HeaderVersionNumber)
315 // Assume that the future ResourceManager headers will
316 // have two strings for us - the reader type name and
317 // resource set type name. Read those, then use the num
318 // bytes to skip field to correct our position.
319 int numBytesToSkip = br.ReadInt32();
320 long endPosition = br.BaseStream.Position + numBytesToSkip;
322 readerTypeName = br.ReadString();
323 resSetTypeName = br.ReadString();
325 br.BaseStream.Seek(endPosition, SeekOrigin.Begin);
329 // resMgrHeaderVersion is older than this ResMgr version.
330 // We should add in backwards compatibility support here.
332 throw new NotSupportedException(Environment.GetResourceString("NotSupported_ObsoleteResourcesFile", _mediator.MainAssembly.GetSimpleName()));
335 store.Position = startPos;
336 // Perf optimization - Don't use Reflection for our defaults.
337 // Note there are two different sets of strings here - the
338 // assembly qualified strings emitted by ResourceWriter, and
339 // the abbreviated ones emitted by InternalResGen.
340 if (CanUseDefaultResourceClasses(readerTypeName, resSetTypeName))
342 RuntimeResourceSet rs;
343 #if LOOSELY_LINKED_RESOURCE_REFERENCE
344 rs = new RuntimeResourceSet(store, assembly);
346 rs = new RuntimeResourceSet(store);
347 #endif // LOOSELY_LINKED_RESOURCE_REFERENCE
352 // we do not want to use partial binding here.
353 Type readerType = Type.GetType(readerTypeName, true);
354 Object[] args = new Object[1];
356 IResourceReader reader = (IResourceReader)Activator.CreateInstance(readerType, args);
358 Object[] resourceSetArgs =
359 #if LOOSELY_LINKED_RESOURCE_REFERENCE
363 #endif // LOOSELY_LINKED_RESOURCE_REFERENCE
364 resourceSetArgs[0] = reader;
365 #if LOOSELY_LINKED_RESOURCE_REFERENCE
366 resourceSetArgs[1] = assembly;
367 #endif // LOOSELY_LINKED_RESOURCE_REFERENCE
369 if (_mediator.UserResourceSet == null)
371 Contract.Assert(resSetTypeName != null, "We should have a ResourceSet type name from the custom resource file here.");
372 resSetType = Type.GetType(resSetTypeName, true, false);
375 resSetType = _mediator.UserResourceSet;
376 ResourceSet rs = (ResourceSet)Activator.CreateInstance(resSetType,
377 BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.CreateInstance,
387 store.Position = startPos;
392 if (_mediator.UserResourceSet == null)
394 // Explicitly avoid CreateInstance if possible, because it
395 // requires ReflectionPermission to call private & protected
397 #if LOOSELY_LINKED_RESOURCE_REFERENCE
398 return new RuntimeResourceSet(store, assembly);
400 return new RuntimeResourceSet(store);
401 #endif // LOOSELY_LINKED_RESOURCE_REFERENCE
405 Object[] args = new Object[2];
410 ResourceSet rs = null;
411 // Add in a check for a constructor taking in an assembly first.
414 rs = (ResourceSet)Activator.CreateInstance(_mediator.UserResourceSet, args);
417 catch (MissingMethodException) { }
419 args = new Object[1];
421 rs = (ResourceSet)Activator.CreateInstance(_mediator.UserResourceSet, args);
422 #if LOOSELY_LINKED_RESOURCE_REFERENCE
423 rs.Assembly = assembly;
424 #endif // LOOSELY_LINKED_RESOURCE_REFERENCE
427 catch (MissingMethodException e)
429 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ResMgrBadResSet_Type", _mediator.UserResourceSet.AssemblyQualifiedName), e);
434 [System.Security.SecurityCritical]
435 private Stream GetManifestResourceStream(RuntimeAssembly satellite, String fileName, ref StackCrawlMark stackMark)
437 Contract.Requires(satellite != null, "satellite shouldn't be null; check caller");
438 Contract.Requires(fileName != null, "fileName shouldn't be null; check caller");
440 // If we're looking in the main assembly AND if the main assembly was the person who
441 // created the ResourceManager, skip a security check for private manifest resources.
442 bool canSkipSecurityCheck = (_mediator.MainAssembly == satellite)
443 && (_mediator.CallingAssembly == _mediator.MainAssembly);
445 Stream stream = satellite.GetManifestResourceStream(_mediator.LocationInfo, fileName, canSkipSecurityCheck, ref stackMark);
448 stream = CaseInsensitiveManifestResourceStreamLookup(satellite, fileName);
454 // Looks up a .resources file in the assembly manifest using
455 // case-insensitive lookup rules. Yes, this is slow. The metadata
456 // dev lead refuses to make all assembly manifest resource lookups case-insensitive,
457 // even optionally case-insensitive.
458 [System.Security.SecurityCritical]
459 [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
460 private Stream CaseInsensitiveManifestResourceStreamLookup(RuntimeAssembly satellite, String name)
462 Contract.Requires(satellite != null, "satellite shouldn't be null; check caller");
463 Contract.Requires(name != null, "name shouldn't be null; check caller");
465 StringBuilder sb = new StringBuilder();
466 if (_mediator.LocationInfo != null)
468 String nameSpace = _mediator.LocationInfo.Namespace;
469 if (nameSpace != null)
471 sb.Append(nameSpace);
473 sb.Append(Type.Delimiter);
478 String givenName = sb.ToString();
479 CompareInfo comparer = CultureInfo.InvariantCulture.CompareInfo;
480 String canonicalName = null;
481 foreach (String existingName in satellite.GetManifestResourceNames())
483 if (comparer.Compare(existingName, givenName, CompareOptions.IgnoreCase) == 0)
485 if (canonicalName == null)
487 canonicalName = existingName;
491 throw new MissingManifestResourceException(Environment.GetResourceString("MissingManifestResource_MultipleBlobs", givenName, satellite.ToString()));
496 #if !FEATURE_CORECLR && !MONO
497 if (FrameworkEventSource.IsInitialized)
499 if (canonicalName != null)
501 FrameworkEventSource.Log.ResourceManagerCaseInsensitiveResourceStreamLookupSucceeded(_mediator.BaseName, _mediator.MainAssembly, satellite.GetSimpleName(), givenName);
505 FrameworkEventSource.Log.ResourceManagerCaseInsensitiveResourceStreamLookupFailed(_mediator.BaseName, _mediator.MainAssembly, satellite.GetSimpleName(), givenName);
510 if (canonicalName == null)
514 // If we're looking in the main assembly AND if the main
515 // assembly was the person who created the ResourceManager,
516 // skip a security check for private manifest resources.
517 bool canSkipSecurityCheck = _mediator.MainAssembly == satellite && _mediator.CallingAssembly == _mediator.MainAssembly;
518 StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
519 Stream s = satellite.GetManifestResourceStream(canonicalName, ref stackMark, canSkipSecurityCheck);
520 // GetManifestResourceStream will return null if we don't have
521 // permission to read this stream from the assembly. For example,
522 // if the stream is private and we're trying to access it from another
523 // assembly (ie, ResMgr in mscorlib accessing anything else), we
524 // require Reflection TypeInformation permission to be able to read
530 #if !FEATURE_CORECLR && !MONO
532 if (FrameworkEventSource.IsInitialized)
534 FrameworkEventSource.Log.ResourceManagerManifestResourceAccessDenied(_mediator.BaseName, _mediator.MainAssembly, satellite.GetSimpleName(), canonicalName);
541 [System.Security.SecurityCritical]
542 [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
543 private RuntimeAssembly GetSatelliteAssembly(CultureInfo lookForCulture, ref StackCrawlMark stackMark)
545 if (!_mediator.LookedForSatelliteContractVersion)
547 _mediator.SatelliteContractVersion = _mediator.ObtainSatelliteContractVersion(_mediator.MainAssembly);
548 _mediator.LookedForSatelliteContractVersion = true;
551 RuntimeAssembly satellite = null;
552 String satAssemblyName = GetSatelliteAssemblyName();
554 // Look up the satellite assembly, but don't let problems
555 // like a partially signed satellite assembly stop us from
556 // doing fallback and displaying something to the user.
557 // Yet also somehow log this error for a developer.
560 satellite = _mediator.MainAssembly.InternalGetSatelliteAssembly(satAssemblyName, lookForCulture, _mediator.SatelliteContractVersion, false, ref stackMark);
563 // Jun 08: for cases other than ACCESS_DENIED, we'll assert instead of throw to give release builds more opportunity to fallback.
566 #pragma warning disable 168
567 catch (FileLoadException fle)
568 #pragma warning restore
571 // Ignore cases where the loader gets an access
572 // denied back from the OS. This showed up for
573 // href-run exe's at one point.
574 int hr = fle._HResult;
575 if (hr != Win32Native.MakeHRFromErrorCode(Win32Native.ERROR_ACCESS_DENIED))
577 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);
582 // Don't throw for zero-length satellite assemblies, for compat with v1
583 catch (BadImageFormatException bife)
585 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);
588 #if !FEATURE_CORECLR && !MONO
589 if (FrameworkEventSource.IsInitialized)
591 if (satellite != null)
593 FrameworkEventSource.Log.ResourceManagerGetSatelliteAssemblySucceeded(_mediator.BaseName, _mediator.MainAssembly, lookForCulture.Name, satAssemblyName);
597 FrameworkEventSource.Log.ResourceManagerGetSatelliteAssemblyFailed(_mediator.BaseName, _mediator.MainAssembly, lookForCulture.Name, satAssemblyName);
605 // Perf optimization - Don't use Reflection for most cases with
606 // our .resources files. This makes our code run faster and we can
607 // creating a ResourceReader via Reflection. This would incur
608 // a security check (since the link-time check on the constructor that
609 // takes a String is turned into a full demand with a stack walk)
610 // and causes partially trusted localized apps to fail.
611 private bool CanUseDefaultResourceClasses(String readerTypeName, String resSetTypeName)
613 Contract.Assert(readerTypeName != null, "readerTypeName shouldn't be null; check caller");
614 Contract.Assert(resSetTypeName != null, "resSetTypeName shouldn't be null; check caller");
616 if (_mediator.UserResourceSet != null)
619 // Ignore the actual version of the ResourceReader and
620 // RuntimeResourceSet classes. Let those classes deal with
621 // versioning themselves.
622 AssemblyName mscorlib = new AssemblyName(ResourceManager.MscorlibName);
624 if (readerTypeName != null)
626 if (!ResourceManager.CompareNames(readerTypeName, ResourceManager.ResReaderTypeName, mscorlib))
630 if (resSetTypeName != null)
632 if (!ResourceManager.CompareNames(resSetTypeName, ResourceManager.ResSetTypeName, mscorlib))
639 [System.Security.SecurityCritical]
640 private String GetSatelliteAssemblyName()
642 String satAssemblyName = _mediator.MainAssembly.GetSimpleName();
643 satAssemblyName += ".resources";
644 return satAssemblyName;
647 [System.Security.SecurityCritical]
648 private void HandleSatelliteMissing()
650 String satAssemName = _mediator.MainAssembly.GetSimpleName() + ".resources.dll";
651 if (_mediator.SatelliteContractVersion != null)
653 satAssemName += ", Version=" + _mediator.SatelliteContractVersion.ToString();
656 AssemblyName an = new AssemblyName();
657 an.SetPublicKey(_mediator.MainAssembly.GetPublicKey());
658 byte[] token = an.GetPublicKeyToken();
660 int iLen = token.Length;
661 StringBuilder publicKeyTok = new StringBuilder(iLen * 2);
662 for (int i = 0; i < iLen; i++)
664 publicKeyTok.Append(token[i].ToString("x", CultureInfo.InvariantCulture));
666 satAssemName += ", PublicKeyToken=" + publicKeyTok;
668 String missingCultureName = _mediator.NeutralResourcesCulture.Name;
669 if (missingCultureName.Length == 0)
671 missingCultureName = "<invariant>";
673 throw new MissingSatelliteAssemblyException(Environment.GetResourceString("MissingSatelliteAssembly_Culture_Name", _mediator.NeutralResourcesCulture, satAssemName), missingCultureName);
676 [System.Security.SecurityCritical] // auto-generated
677 private void HandleResourceStreamMissing(String fileName)
679 // Keep people from bothering me about resources problems
680 if (_mediator.MainAssembly == typeof(Object).Assembly && _mediator.BaseName.Equals("mscorlib"))
682 // This would break CultureInfo & all our exceptions.
683 Contract.Assert(false, "Couldn't get mscorlib" + ResourceManager.ResFileExtension + " from mscorlib'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.");
685 // We cannot continue further - simply FailFast.
686 string mesgFailFast = "mscorlib" + ResourceManager.ResFileExtension + " couldn't be found! Large parts of the BCL won't work!";
687 System.Environment.FailFast(mesgFailFast);
689 // We really don't think this should happen - we always
690 // expect the neutral locale's resources to be present.
691 String resName = String.Empty;
692 if (_mediator.LocationInfo != null && _mediator.LocationInfo.Namespace != null)
693 resName = _mediator.LocationInfo.Namespace + Type.Delimiter;
695 throw new MissingManifestResourceException(Environment.GetResourceString("MissingManifestResource_NoNeutralAsm", resName, _mediator.MainAssembly.GetSimpleName()));
699 static bool GetNeutralResourcesLanguageAttribute (Assembly assembly, ref string cultureName, ref short fallbackLocation)
701 var ca = assembly.GetCustomAttribute<NeutralResourcesLanguageAttribute> ();
705 cultureName = ca.CultureName;
706 fallbackLocation = (short) ca.Location;
710 [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
711 [System.Security.SecurityCritical] // Our security team doesn't yet allow safe-critical P/Invoke methods.
712 [ResourceExposure(ResourceScope.None)]
713 [System.Security.SuppressUnmanagedCodeSecurity]
714 [return: MarshalAs(UnmanagedType.Bool)]
715 internal static extern bool GetNeutralResourcesLanguageAttribute(RuntimeAssembly assemblyHandle, StringHandleOnStack cultureName, out short fallbackLocation);