using System.Globalization;
using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
namespace System.Resources
{
{
return ((RuntimeAssembly)mainAssembly).InternalGetSatelliteAssembly(culture, version, throwOnFileNotFound: false);
}
-
- [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
- [return: MarshalAs(UnmanagedType.Bool)]
- private static extern bool GetNeutralResourcesLanguageAttribute(RuntimeAssembly assemblyHandle, StringHandleOnStack cultureName, out short fallbackLocation);
-
- private static bool GetNeutralResourcesLanguageAttribute(Assembly assemblyHandle, ref string cultureName, out short fallbackLocation)
- {
- return GetNeutralResourcesLanguageAttribute(((RuntimeAssembly)assemblyHandle).GetNativeHandle(),
- JitHelpers.GetStringHandleOnStack(ref cultureName),
- out fallbackLocation);
- }
}
}
MPF_ENTRY(DEFAULT_DLL_IMPORT_SEARCH_PATHS_IS_CACHED),
MPF_ENTRY(DEFAULT_DLL_IMPORT_SEARCH_PATHS_STATUS),
- MPF_ENTRY(NEUTRAL_RESOURCES_LANGUAGE_IS_CACHED),
MPF_ENTRY(COMPUTED_METHODDEF_TO_PROPERTYINFO_MAP),
MPF_ENTRY(LOW_LEVEL_SYSTEM_ASSEMBLY_BY_NAME),
#undef MPF_ENTRY
END_QCALL;
}
-BOOL QCALLTYPE AssemblyNative::GetNeutralResourcesLanguageAttribute(QCall::AssemblyHandle pAssembly, QCall::StringHandleOnStack cultureName, INT16& outFallbackLocation)
-{
- CONTRACTL {
- QCALL_CHECK;
- } CONTRACTL_END;
-
- BOOL retVal = FALSE;
- BEGIN_QCALL;
-
- _ASSERTE(pAssembly);
- Assembly * pAsm = pAssembly->GetAssembly();
- _ASSERTE(pAsm);
- Module * pModule = pAsm->GetManifestModule();
- _ASSERTE(pModule);
-
- LPCUTF8 pszCultureName = NULL;
- ULONG cultureNameLength = 0;
- INT16 fallbackLocation = 0;
-
- // find the attribute if it exists
- if (pModule->GetNeutralResourcesLanguage(&pszCultureName, &cultureNameLength, &fallbackLocation, FALSE)) {
- StackSString culture(SString::Utf8, pszCultureName, cultureNameLength);
- cultureName.Set(culture);
- outFallbackLocation = fallbackLocation;
- retVal = TRUE;
- }
-
- END_QCALL;
-
- return retVal;
-}
-
BOOL QCALLTYPE AssemblyNative::GetIsCollectible(QCall::AssemblyHandle pAssembly)
{
QCALL_CONTRACT;
static
BYTE * QCALLTYPE GetResource(QCall::AssemblyHandle pAssembly, LPCWSTR wszName, DWORD * length);
- static
- BOOL QCALLTYPE GetNeutralResourcesLanguageAttribute(QCall::AssemblyHandle pAssembly, QCall::StringHandleOnStack cultureName, INT16& outFallbackLocation);
-
static
FCDECL1(FC_BOOL_RET, IsDynamic, AssemblyBaseObject * pAssemblyUNSAFE);
return !!(m_dwPersistedFlags & NO_STRING_INTERNING);
}
-BOOL Module::GetNeutralResourcesLanguage(LPCUTF8 * cultureName, ULONG * cultureNameLength, INT16 * fallbackLocation, BOOL cacheAttribute)
-{
- STANDARD_VM_CONTRACT;
-
- BOOL retVal = FALSE;
- if (!(m_dwPersistedFlags & NEUTRAL_RESOURCES_LANGUAGE_IS_CACHED))
- {
- const BYTE *pVal = NULL;
- ULONG cbVal = 0;
-
- // This flag applies to assembly, but it is stored on module so it can be cached in ngen image
- // Thus, we should ever need it for manifest module only.
- IMDInternalImport *mdImport = GetAssembly()->GetManifestImport();
- _ASSERTE(mdImport);
-
- mdToken token;
- IfFailThrow(mdImport->GetAssemblyFromScope(&token));
-
- // Check for the existance of the attribute.
- HRESULT hr = mdImport->GetCustomAttributeByName(token,"System.Resources.NeutralResourcesLanguageAttribute",(const void **)&pVal, &cbVal);
- if (hr == S_OK) {
-
- // we should not have a native image (it would have been cached at ngen time)
- _ASSERTE(!HasNativeImage());
-
- CustomAttributeParser cap(pVal, cbVal);
- IfFailThrow(cap.SkipProlog());
- IfFailThrow(cap.GetString(cultureName, cultureNameLength));
- IfFailThrow(cap.GetI2(fallbackLocation));
- // Should only be true on Module.Save(). Update flag to show we have the attribute cached
- if (cacheAttribute)
- FastInterlockOr(&m_dwPersistedFlags, NEUTRAL_RESOURCES_LANGUAGE_IS_CACHED);
-
- retVal = TRUE;
- }
- }
- else
- {
- *cultureName = m_pszCultureName;
- *cultureNameLength = m_CultureNameLength;
- *fallbackLocation = m_FallbackLocation;
- retVal = TRUE;
-
-#ifdef _DEBUG
- // confirm that the NGENed attribute is correct
- LPCUTF8 pszCultureNameCheck = NULL;
- ULONG cultureNameLengthCheck = 0;
- INT16 fallbackLocationCheck = 0;
- const BYTE *pVal = NULL;
- ULONG cbVal = 0;
-
- IMDInternalImport *mdImport = GetAssembly()->GetManifestImport();
- _ASSERTE(mdImport);
- mdToken token;
- IfFailThrow(mdImport->GetAssemblyFromScope(&token));
-
- // Confirm that the attribute exists, and has the save value as when we ngen'd it
- HRESULT hr = mdImport->GetCustomAttributeByName(token,"System.Resources.NeutralResourcesLanguageAttribute",(const void **)&pVal, &cbVal);
- _ASSERTE(hr == S_OK);
- CustomAttributeParser cap(pVal, cbVal);
- IfFailThrow(cap.SkipProlog());
- IfFailThrow(cap.GetString(&pszCultureNameCheck, &cultureNameLengthCheck));
- IfFailThrow(cap.GetI2(&fallbackLocationCheck));
- _ASSERTE(cultureNameLengthCheck == m_CultureNameLength);
- _ASSERTE(fallbackLocationCheck == m_FallbackLocation);
- _ASSERTE(strncmp(pszCultureNameCheck,m_pszCultureName,m_CultureNameLength) == 0);
-#endif // _DEBUG
- }
-
- return retVal;
-}
-
-
BOOL Module::HasDefaultDllImportSearchPathsAttribute()
{
CONTRACTL
//
CorProfileData * profileData = GetProfileData();
- // ngen the neutral resources culture
- if(GetNeutralResourcesLanguage(&m_pszCultureName, &m_CultureNameLength, &m_FallbackLocation, TRUE)) {
- image->StoreStructure((void *) m_pszCultureName,
- (ULONG)(m_CultureNameLength + 1),
- DataImage::ITEM_BINDER_ITEMS,
- 1);
- }
-
-
m_TypeRefToMethodTableMap.Save(image, DataImage::ITEM_TYPEREF_MAP, profileData, mdtTypeRef);
image->BindPointer(&m_TypeRefToMethodTableMap, pModuleNode, offsetof(Module, m_TypeRefToMethodTableMap));
image->ZeroPointerField(this, offsetof(Module, m_pNgenStats));
- // fixup the pointer for NeutralResourcesLanguage, if we have it cached
- if(!!(m_dwPersistedFlags & NEUTRAL_RESOURCES_LANGUAGE_IS_CACHED)) {
- image->FixupPointerField(this, offsetof(Module, m_pszCultureName));
- }
-
// Fixup the property name set
image->FixupPointerField(this, offsetof(Module, m_propertyNameSet));
//If module has default dll import search paths attribute
DEFAULT_DLL_IMPORT_SEARCH_PATHS_STATUS = 0x00000800,
- //If attribute value has been cached before
- NEUTRAL_RESOURCES_LANGUAGE_IS_CACHED = 0x00001000,
-
//If m_MethodDefToPropertyInfoMap has been generated
COMPUTED_METHODDEF_TO_PROPERTYINFO_MAP = 0x00002000,
ULONG m_DefaultDllImportSearchPathsAttributeValue;
- LPCUTF8 m_pszCultureName;
- ULONG m_CultureNameLength;
- INT16 m_FallbackLocation;
-
#ifdef PROFILING_SUPPORTED_DATA
// a wrapper for the underlying PEFile metadata emitter which validates that the metadata edits being
// made are supported modifications to the type system
//-----------------------------------------------------------------------------------------
BOOL IsPreV4Assembly();
-
- //-----------------------------------------------------------------------------------------
- // Parse/Return NeutralResourcesLanguageAttribute if it exists (updates Module member variables at ngen time)
- //-----------------------------------------------------------------------------------------
- BOOL GetNeutralResourcesLanguage(LPCUTF8 * cultureName, ULONG * cultureNameLength, INT16 * fallbackLocation, BOOL cacheAttribute);
-
protected:
QCFuncElement("_GetAssemblyName", TypeName::QGetAssemblyName)
FCFuncEnd()
-FCFuncStart(gManifestBasedResourceGrovelerFuncs)
- QCFuncElement("GetNeutralResourcesLanguageAttribute", AssemblyNative::GetNeutralResourcesLanguageAttribute)
-FCFuncEnd()
-
FCFuncStart(gRuntimeAssemblyFuncs)
QCFuncElement("GetFullName", AssemblyNative::GetFullName)
QCFuncElement("GetLocation", AssemblyNative::GetLocation)
#endif
FCClassElement("Interlocked", "System.Threading", gInterlockedFuncs)
FCClassElement("LoaderAllocatorScout", "System.Reflection", gLoaderAllocatorFuncs)
-FCClassElement("ManifestBasedResourceGroveler", "System.Resources", gManifestBasedResourceGrovelerFuncs)
FCClassElement("Marshal", "System.Runtime.InteropServices", gInteropMarshalFuncs)
FCClassElement("Math", "System", gMathFuncs)
FCClassElement("MathF", "System", gMathFFuncs)
return returnCulture;
}
- internal static CultureInfo GetNeutralResourcesLanguage(Assembly a, ref UltimateResourceFallbackLocation fallbackLocation)
+ internal static CultureInfo GetNeutralResourcesLanguage(Assembly a, out UltimateResourceFallbackLocation fallbackLocation)
{
Debug.Assert(a != null, "assembly != null");
- string cultureName = null;
- short fallback = 0;
- if (GetNeutralResourcesLanguageAttribute(a, ref cultureName, out fallback))
- {
- if ((UltimateResourceFallbackLocation)fallback < UltimateResourceFallbackLocation.MainAssembly || (UltimateResourceFallbackLocation)fallback > UltimateResourceFallbackLocation.Satellite)
- {
- throw new ArgumentException(SR.Format(SR.Arg_InvalidNeutralResourcesLanguage_FallbackLoc, fallback));
- }
- fallbackLocation = (UltimateResourceFallbackLocation)fallback;
- }
- else
+
+ var attr = a.GetCustomAttribute<NeutralResourcesLanguageAttribute>();
+ if (attr == null)
{
fallbackLocation = UltimateResourceFallbackLocation.MainAssembly;
return CultureInfo.InvariantCulture;
}
+ fallbackLocation = attr.Location;
+ if (fallbackLocation < UltimateResourceFallbackLocation.MainAssembly || fallbackLocation > UltimateResourceFallbackLocation.Satellite)
+ {
+ throw new ArgumentException(SR.Format(SR.Arg_InvalidNeutralResourcesLanguage_FallbackLoc, fallbackLocation));
+ }
+
try
{
- CultureInfo c = CultureInfo.GetCultureInfo(cultureName);
- return c;
+ return CultureInfo.GetCultureInfo(attr.CultureName);
}
catch (ArgumentException e)
{ // we should catch ArgumentException only.
// fires, please fix the build process for the BCL directory.
if (a == typeof(object).Assembly)
{
- Debug.Fail(System.CoreLib.Name + "'s NeutralResourcesLanguageAttribute is a malformed culture name! name: \"" + cultureName + "\" Exception: " + e);
+ Debug.Fail(System.CoreLib.Name + "'s NeutralResourcesLanguageAttribute is a malformed culture name! name: \"" + attr.CultureName + "\" Exception: " + e);
return CultureInfo.InvariantCulture;
}
- throw new ArgumentException(SR.Format(SR.Arg_InvalidNeutralResourcesLanguage_Asm_Culture, a.ToString(), cultureName), e);
+ throw new ArgumentException(SR.Format(SR.Arg_InvalidNeutralResourcesLanguage_Asm_Culture, a.ToString(), attr.CultureName), e);
}
}
_resourceSets = new Dictionary<string, ResourceSet>();
_lastUsedResourceCache = new CultureNameResourceSetPair();
- _fallbackLoc = UltimateResourceFallbackLocation.MainAssembly;
-
ResourceManagerMediator mediator = new ResourceManagerMediator(this);
_resourceGroveler = new ManifestBasedResourceGroveler(mediator);
- _neutralResourcesCulture = ManifestBasedResourceGroveler.GetNeutralResourcesLanguage(MainAssembly, ref _fallbackLoc);
+ _neutralResourcesCulture = ManifestBasedResourceGroveler.GetNeutralResourcesLanguage(MainAssembly, out _fallbackLoc);
}
// Gets the base name for the ResourceManager.
{
// This method should be obsolete - replace it with the one below.
// Unfortunately, we made it protected.
- UltimateResourceFallbackLocation ignoringUsefulData = UltimateResourceFallbackLocation.MainAssembly;
- CultureInfo culture = ManifestBasedResourceGroveler.GetNeutralResourcesLanguage(a, ref ignoringUsefulData);
- return culture;
+ return ManifestBasedResourceGroveler.GetNeutralResourcesLanguage(a, out _);
}
// IGNORES VERSION