From a56e30c8d33048216567753d9d3fefc2152af8ac Mon Sep 17 00:00:00 2001 From: Jiyoung Yun Date: Thu, 13 Apr 2017 14:17:19 +0900 Subject: Imported Upstream version 2.0.0.11353 --- src/vm/assembly.cpp | 2299 ++------------------------------------------------- 1 file changed, 80 insertions(+), 2219 deletions(-) (limited to 'src/vm/assembly.cpp') diff --git a/src/vm/assembly.cpp b/src/vm/assembly.cpp index 2db3e23fff..75430644c3 100644 --- a/src/vm/assembly.cpp +++ b/src/vm/assembly.cpp @@ -22,16 +22,7 @@ #include "perfcounters.h" #include "assemblyname.hpp" -#ifdef FEATURE_FUSION -#include "fusion.h" -#include "assemblysink.h" -#include "ngenoptout.h" -#endif -#if !defined(FEATURE_CORECLR) && !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE) -#include "assemblyusagelogmanager.h" -#include "policy.h" -#endif #include "eeprofinterfaces.h" #include "reflectclasswriter.h" @@ -53,29 +44,15 @@ #endif #include "appdomainnative.hpp" -#ifdef FEATURE_REMOTING -#include "remoting.h" -#include "appdomainhelper.h" -#endif #include "customattribute.h" #include "winnls.h" -#include "constrainedexecutionregion.h" #include "caparser.h" #include "../md/compiler/custattr.h" #include "mdaassistants.h" #include "peimagelayout.inl" -#if !defined(FEATURE_CORECLR) && !defined(CROSSGEN_COMPILE) -#include -#include "eventmsg.h" -#endif - -#ifdef FEATURE_TRACELOGGING -#include "clrtracelogging.h" -#endif // FEATURE_TRACELOGGING - // Define these macro's to do strict validation for jit lock and class init entry leaks. // This defines determine if the asserts that verify for these leaks are defined or not. @@ -129,10 +106,6 @@ enum ReasonForNotSharing //---------------------------------------------------------------------------------------------- Assembly::Assembly(BaseDomain *pDomain, PEAssembly* pFile, DebuggerAssemblyControlFlags debuggerFlags, BOOL fIsCollectible) : m_FreeFlag(0), -#ifdef FEATURE_MULTIMODULE_ASSEMBLIES - m_pAllowedFiles(NULL), - m_crstAllowedFiles(CrstAllowedFiles), -#endif m_pDomain(pDomain), m_pClassLoader(NULL), m_pEntryPoint(NULL), @@ -161,9 +134,6 @@ Assembly::Assembly(BaseDomain *pDomain, PEAssembly* pFile, DebuggerAssemblyContr m_fIsDomainNeutral(pDomain == SharedDomain::GetDomain()), #ifdef FEATURE_LOADER_OPTIMIZATION m_bMissingDependenciesCheckDone(FALSE), -#ifdef FEATURE_FUSION - m_pBindingClosure(NULL), -#endif #endif // FEATURE_LOADER_OPTIMIZATION m_debuggerFlags(debuggerFlags), m_fTerminated(FALSE), @@ -171,8 +141,8 @@ Assembly::Assembly(BaseDomain *pDomain, PEAssembly* pFile, DebuggerAssemblyContr #ifdef FEATURE_COMINTEROP , m_InteropAttributeStatus(INTEROP_ATTRIBUTE_UNSET) #endif -#ifndef FEATURE_CORECLR - , m_fSupportsAutoNGen(FALSE) +#ifdef FEATURE_PREJIT + , m_isInstrumentedStatus(IS_INSTRUMENTED_UNSET) #endif { STANDARD_VM_CONTRACT; @@ -183,42 +153,6 @@ Assembly::Assembly(BaseDomain *pDomain, PEAssembly* pFile, DebuggerAssemblyContr #define REFEMIT_MANIFEST_MODULE_NAME W("RefEmit_InMemoryManifestModule") -#ifdef FEATURE_TRACELOGGING -//---------------------------------------------------------------------------------------------- -// Reads and logs the TargetFramework attribute for an assembly. For example: [assembly: TargetFramework(".NETFramework,Version=v4.0")] -//---------------------------------------------------------------------------------------------- -void Assembly::TelemetryLogTargetFrameworkAttribute() -{ - const BYTE *pbAttr; // Custom attribute data as a BYTE*. - ULONG cbAttr; // Size of custom attribute data. - HRESULT hr = GetManifestImport()->GetCustomAttributeByName(GetManifestToken(), TARGET_FRAMEWORK_TYPE, (const void**)&pbAttr, &cbAttr); - bool dataLogged = false; - if (hr == S_OK) - { - CustomAttributeParser cap(pbAttr, cbAttr); - LPCUTF8 lpTargetFramework; - ULONG cbTargetFramework; - if (SUCCEEDED(cap.ValidateProlog())) - { - if (SUCCEEDED(cap.GetString(&lpTargetFramework, &cbTargetFramework))) - { - if ((lpTargetFramework != NULL) && (cbTargetFramework != 0)) - { - SString s(SString::Utf8, lpTargetFramework, cbTargetFramework); - CLRTraceLog::Logger::LogTargetFrameworkAttribute(s.GetUnicode(), GetSimpleName()); - dataLogged = true; - } - } - } - } - if (!dataLogged) - { - CLRTraceLog::Logger::LogTargetFrameworkAttribute(L"", GetSimpleName()); - } -} - -#endif // FEATURE_TRACELOGGING - //---------------------------------------------------------------------------------------------- // Does most Assembly initialization tasks. It can assume the ctor has already run // and the assembly is safely destructable. Whether this function throws or succeeds, @@ -264,9 +198,6 @@ void Assembly::Init(AllocMemTracker *pamTracker, LoaderAllocator *pLoaderAllocat m_pSharedSecurityDesc = Security::CreateSharedSecurityDescriptor(this); -#ifdef FEATURE_MULTIMODULE_ASSEMBLIES - m_pAllowedFiles = new EEUtf8StringHashTable(); -#endif COUNTER_ONLY(GetPerfCounters().m_Loading.cAssemblies++); @@ -285,20 +216,6 @@ void Assembly::Init(AllocMemTracker *pamTracker, LoaderAllocator *pLoaderAllocat if (!m_pManifest->IsReadyToRun()) CacheManifestExportedTypes(pamTracker); -#if !defined(FEATURE_CORECLR) && !defined(CROSSGEN_COMPILE) - GenerateBreadcrumbForServicing(); - - m_fSupportsAutoNGen = SupportsAutoNGenWorker(); - - ReportAssemblyUse(); -#endif - -#ifdef FEATURE_TRACELOGGING - - TelemetryLogTargetFrameworkAttribute(); - -#endif // FEATURE_TRACELOGGING - // Check for the assemblies that contain SIMD Vector types. // If we encounter a non-trusted assembly with these names, we will simply not recognize any of its @@ -380,16 +297,6 @@ Assembly::~Assembly() if (m_pwStrongNameKeyContainer && (m_FreeFlag & FREE_KEY_CONTAINER)) delete[] m_pwStrongNameKeyContainer; -#ifdef FEATURE_MULTIMODULE_ASSEMBLIES - if (m_pAllowedFiles) - delete(m_pAllowedFiles); -#endif -#ifdef FEATURE_FUSION - if (m_pBindingClosure) - { - m_pBindingClosure->Release(); - } -#endif if (IsDynamic()) { if (m_pOnDiskManifest) // clear the on disk manifest if it is not cleared yet. @@ -757,7 +664,6 @@ Assembly *Assembly::CreateDynamic(AppDomain *pDomain, CreateDynamicAssemblyArgs &ma)); pFile = PEAssembly::Create(pCallerAssembly->GetManifestFile(), pAssemblyEmit, args->access & ASSEMBLY_ACCESS_REFLECTION_ONLY); -#if defined(FEATURE_HOST_ASSEMBLY_RESOLVER) // Dynamically created modules (aka RefEmit assemblies) do not have a LoadContext associated with them since they are not bound // using an actual binder. As a result, we will assume the same binding/loadcontext information for the dynamic assembly as its // caller/creator to ensure that any assembly loads triggered by the dynamic assembly are resolved using the intended load context. @@ -803,90 +709,21 @@ Assembly *Assembly::CreateDynamic(AppDomain *pDomain, CreateDynamicAssemblyArgs // Set it as the fallback load context binder for the dynamic assembly being created pFile->SetFallbackLoadContextBinder(pFallbackLoadContextBinder); -#endif // defined(FEATURE_HOST_ASSEMBLY_RESOLVER) } AssemblyLoadSecurity loadSecurity; -#ifndef FEATURE_CORECLR - DWORD dwSpecialFlags = 0xFFFFFFFF; - - // Don't bother with setting up permissions if this isn't allowed to run - // This doesn't apply in CoreCLR because you cannot specify evidence when creating a dynamic assembly - if ((args->identity != NULL) && - (args->access & ASSEMBLY_ACCESS_RUN)) - { - loadSecurity.m_pAdditionalEvidence = &args->identity; - } - else - { - if (pCallerAssembly != NULL) // can be null if caller is interop - { - if (args->securityContextSource == kCurrentAssembly) - { - IAssemblySecurityDescriptor *pCallerSecDesc = pCallerAssembly->GetSecurityDescriptor(pCallersDomain); - gc.granted = pCallerSecDesc->GetGrantedPermissionSet(&(gc.denied)); - dwSpecialFlags = pCallerSecDesc->GetSpecialFlags(); - } - else - { - IApplicationSecurityDescriptor *pCallersDomainSecDesc = pCallersDomain->GetSecurityDescriptor(); - -#ifdef FEATURE_CAS_POLICY - // We only want to propigate the identity of homogenous domains, since heterogenous domains tend - // to be fully trusted even if they are housing partially trusted code - which could lead to an - // elevation of privilege if we allow the grant set to be pushed to assemblies partially trusted - // code is loading. - if (!pCallersDomainSecDesc->IsHomogeneous()) - { - COMPlusThrow(kNotSupportedException, W("NotSupported_SecurityContextSourceAppDomainInHeterogenous")); - } -#endif // FEATURE_CAS_POLICY - - gc.granted = pCallersDomainSecDesc->GetGrantedPermissionSet(); - dwSpecialFlags = pCallersDomainSecDesc->GetSpecialFlags(); - } - - // Caller may be in another appdomain context, in which case we'll - // need to marshal/unmarshal the grant and deny sets across. -#ifdef FEATURE_REMOTING // should not happen without remoting - if (pCallersDomain != ::GetAppDomain()) - { - gc.granted = AppDomainHelper::CrossContextCopyFrom(pCallersDomain->GetId(), &(gc.granted)); - if (gc.denied != NULL) - { - gc.denied = AppDomainHelper::CrossContextCopyFrom(pCallersDomain->GetId(), &(gc.denied)); - } - } -#else // !FEATURE_REMOTING - _ASSERTE(pCallersDomain == ::GetAppDomain()); -#endif // FEATURE_REMOTING - } - } -#else // FEATURE_CORECLR // In SilverLight all dynamic assemblies should be transparent and partially trusted, even if they are // created by platform assemblies. Thus they should inherit the grant sets from the appdomain not the // parent assembly. IApplicationSecurityDescriptor *pCurrentDomainSecDesc = ::GetAppDomain()->GetSecurityDescriptor(); gc.granted = pCurrentDomainSecDesc->GetGrantedPermissionSet(); DWORD dwSpecialFlags = pCurrentDomainSecDesc->GetSpecialFlags(); -#endif // !FEATURE_CORECLR // If the dynamic assembly creator did not specify evidence for the newly created assembly, then it // should inherit the grant set of the creation assembly. if (loadSecurity.m_pAdditionalEvidence == NULL) { -#ifdef FEATURE_CAS_POLICY - // If we're going to inherit the grant set of an anonymously hosted dynamic method, it will be - // full trust/transparent. In that case, we should demand full trust. - if(args->securityContextSource == kCurrentAssembly && - pCallerAssembly != NULL && - pCallersDomain != NULL && - pCallerAssembly->GetDomainAssembly(pCallersDomain) == pCallersDomain->GetAnonymouslyHostedDynamicMethodsAssembly()) - { - loadSecurity.m_fPropagatingAnonymouslyHostedDynamicMethodGrant = true; - } -#endif // FEATURE_CAS_POLICY loadSecurity.m_pGrantSet = &gc.granted; loadSecurity.m_pRefusedSet = &gc.denied; @@ -950,33 +787,11 @@ Assembly *Assembly::CreateDynamic(AppDomain *pDomain, CreateDynamicAssemblyArgs pAssem->m_dwDynamicAssemblyAccess = args->access; -#ifdef FEATURE_CAS_POLICY - // If a legacy assembly is emitting an assembly, then we implicitly add the legacy attribute. If the legacy - // assembly is also in partial trust, we implicitly make the emitted assembly transparent. - ModuleSecurityDescriptor *pEmittingMSD = ModuleSecurityDescriptor::GetModuleSecurityDescriptor(pCallerAssembly); - if (pEmittingMSD->GetSecurityRuleSet() == SecurityRuleSet_Level1) - { - IAssemblySecurityDescriptor *pCallerSecDesc = pCallerAssembly->GetSecurityDescriptor(pCallersDomain); - if (!pCallerSecDesc->IsFullyTrusted()) - { - args->flags = kTransparentAssembly; - } - } - - // If the code emitting the dynamic assembly is transparent and it is attempting to emit a non-transparent - // assembly, then we need to do a demand for the grant set of the emitting assembly (which should also be - // is the grant set of the dynamic assembly). - if (Security::IsMethodTransparent(pmdEmitter) && !(args->flags & kTransparentAssembly)) - { - Security::DemandGrantSet(pCallerAssembly->GetSecurityDescriptor(pCallersDomain)); - } -#else // FEATURE_CORECLR // Making the dynamic assembly opportunistically critical in full trust CoreCLR and transparent otherwise. if (!GetAppDomain()->GetSecurityDescriptor()->IsFullyTrusted()) { args->flags = kTransparentAssembly; } -#endif //!FEATURE_CORECLR // Fake up a module security descriptor for the assembly. TokenSecurityDescriptorFlags tokenFlags = TokenSecurityDescriptorFlags_None; @@ -991,42 +806,7 @@ Assembly *Assembly::CreateDynamic(AppDomain *pDomain, CreateDynamicAssemblyArgs if (args->flags & kTreatAsSafeAssembly) tokenFlags |= TokenSecurityDescriptorFlags_TreatAsSafe; -#ifdef FEATURE_APTCA - if (args->aptcaBlob != NULL) - { - tokenFlags |= ParseAptcaAttribute(args->aptcaBlob->GetDirectPointerToNonObjectElements(), - args->aptcaBlob->GetNumComponents()); - } - -#endif // FEATURE_APTCA -#ifndef FEATURE_CORECLR - // Use the security rules given to us if the emitting code has selected a specific one. Otherwise, - // inherit the security rules of the emitting assembly. - if (args->securityRulesBlob != NULL) - { - tokenFlags |= ParseSecurityRulesAttribute(args->securityRulesBlob->GetDirectPointerToNonObjectElements(), - args->securityRulesBlob->GetNumComponents()); - } - else - { - // Ensure that dynamic assemblies created by mscorlib always specify a rule set, since we want to - // make sure that creating a level 2 assembly was an explicit decision by the emitting code, - // rather than an implicit decision because mscorlib is level 2 itself. - // - // If you're seeing this assert, it means that you've created a dynamic assembly from mscorlib, - // but did not pass a CustomAttributeBuilder for the SecurityRulesAttribute to the - // DefineDynamicAssembly call. - _ASSERTE(!pCallerAssembly->IsSystem()); - - // Use the creating assembly's security rule set for the emitted assembly - SecurityRuleSet callerRuleSet = - ModuleSecurityDescriptor::GetModuleSecurityDescriptor(pCallerAssembly)->GetSecurityRuleSet(); - tokenFlags |= EncodeSecurityRuleSet(callerRuleSet); - - tokenFlags |= TokenSecurityDescriptorFlags_SecurityRules; - } -#endif // !FEATURE_CORECLR _ASSERTE(pAssem->GetManifestModule()->m_pModuleSecurityDescriptor != NULL); pAssem->GetManifestModule()->m_pModuleSecurityDescriptor->OverrideTokenFlags(tokenFlags); @@ -1038,47 +818,6 @@ Assembly *Assembly::CreateDynamic(AppDomain *pDomain, CreateDynamicAssemblyArgs if (publicKey.GetSize() > 0) { pAssem->SetStrongNameLevel(Assembly::SN_PUBLIC_KEY); -#ifndef FEATURE_CORECLR - gc.strongNameKeyPair = args->assemblyName->GetStrongNameKeyPair(); - // If there's a public key, there might be a strong name key pair. - if (gc.strongNameKeyPair != NULL) - { - MethodDescCallSite getKeyPair(METHOD__STRONG_NAME_KEY_PAIR__GET_KEY_PAIR, &gc.strongNameKeyPair); - - ARG_SLOT arglist[] = - { - ObjToArgSlot(gc.strongNameKeyPair), - PtrToArgSlot(&gc.orArrayOrContainer) - }; - - BOOL bKeyInArray; - bKeyInArray = (BOOL)getKeyPair.Call_RetBool(arglist); - - if (bKeyInArray) - { - U1ARRAYREF orArray = (U1ARRAYREF)gc.orArrayOrContainer; - pAssem->m_cbStrongNameKeyPair = orArray->GetNumComponents(); - pAssem->m_pbStrongNameKeyPair = new BYTE[pAssem->m_cbStrongNameKeyPair]; - - pAssem->m_FreeFlag |= pAssem->FREE_KEY_PAIR; - memcpy(pAssem->m_pbStrongNameKeyPair, orArray->GetDataPtr(), pAssem->m_cbStrongNameKeyPair); - pAssem->SetStrongNameLevel(Assembly::SN_FULL_KEYPAIR_IN_ARRAY); - } - else - { - STRINGREF orContainer = (STRINGREF)gc.orArrayOrContainer; - DWORD cchContainer = orContainer->GetStringLength(); - pAssem->m_pwStrongNameKeyContainer = new WCHAR[cchContainer + 1]; - - pAssem->m_FreeFlag |= pAssem->FREE_KEY_CONTAINER; - memcpy(pAssem->m_pwStrongNameKeyContainer, orContainer->GetBuffer(), cchContainer * sizeof(WCHAR)); - pAssem->m_pwStrongNameKeyContainer[cchContainer] = W('\0'); - - pAssem->SetStrongNameLevel(Assembly::SN_FULL_KEYPAIR_IN_CONTAINER); - } - } - else -#endif // FEATURE_CORECLR { // Since we have no way to validate the public key of a dynamic assembly we don't allow // partial trust code to emit a dynamic assembly with an arbitrary public key. @@ -1147,87 +886,6 @@ Assembly *Assembly::CreateDynamic(AppDomain *pDomain, CreateDynamicAssemblyArgs RETURN pRetVal; } // Assembly::CreateDynamic -#ifdef FEATURE_MULTIMODULE_ASSEMBLIES -ReflectionModule *Assembly::CreateDynamicModule(LPCWSTR wszModuleName, LPCWSTR wszFileName, BOOL fIsTransient, INT32* ptkFile) -{ - CONTRACT(ReflectionModule *) - { - STANDARD_VM_CHECK; - POSTCONDITION(CheckPointer(RETVAL)); - } - CONTRACT_END; - - AllocMemTracker amTracker; - - // Add a manifest entry for the module - mdFile token; - IMetaDataAssemblyEmit *pAssemblyEmit = GetManifestFile()->GetAssemblyEmitter(); - IfFailThrow(pAssemblyEmit->DefineFile(wszFileName, NULL, 0, 0, &token)); - - if (ptkFile) - *ptkFile = (INT32)token; - - GetManifestModule()->UpdateDynamicMetadataIfNeeded(); - - // Define initial metadata for the module - SafeComHolder pEmit; - PEFile::DefineEmitScope(IID_IMetaDataEmit, (void **)&pEmit); - - // the module name will be set later when we create the ReflectionModule - - // Create the PEFile for the module - PEModuleHolder pFile(PEModule::Create(GetManifestFile(), token, pEmit)); - - // Create the DomainModule - NewHolder pDomainModule(new DomainModule(::GetAppDomain(), GetDomainAssembly(), pFile)); - - // Create the module itself - ReflectionModuleHolder pWrite(ReflectionModule::Create(this, pFile, &amTracker, wszModuleName, fIsTransient)); - - amTracker.SuppressRelease(); //@todo: OOM: is this the right place to commit the tracker? - pWrite->SetIsTenured(); - - // Modules take the DebuggerAssemblyControlFlags down from its parent Assembly initially. - // By default, this turns on JIT optimization. - - pWrite->SetDebuggerInfoBits(GetDebuggerInfoBits()); - - // Associate the two - pDomainModule->SetModule(pWrite); - m_pManifest->StoreFileThrowing(token, pWrite); - - // Simulate loading process - pDomainModule->Begin(); - pDomainModule->DeliverSyncEvents(); - pDomainModule->DeliverAsyncEvents(); - pDomainModule->FinishLoad(); - pDomainModule->ClearLoading(); - pDomainModule->m_level = FILE_ACTIVE; - - pDomainModule.SuppressRelease(); - ReflectionModule *pModule = pWrite.Extract(); - - LPCSTR szUTF8FileName; - CQuickBytes qbLC; - - // Get the UTF8 file name - IfFailThrow(m_pManifest->GetMDImport()->GetFileProps(token, &szUTF8FileName, NULL, NULL, NULL)); - UTF8_TO_LOWER_CASE(szUTF8FileName, qbLC); - LPCSTR szUTF8FileNameLower = (LPUTF8) qbLC.Ptr(); - - CrstHolder lock(&m_crstAllowedFiles); - - // insert the value into manifest's look up table. - // Need to perform case insensitive hashing as well. - m_pAllowedFiles->InsertValue(szUTF8FileName, (HashDatum)(size_t)token, TRUE); - m_pAllowedFiles->InsertValue(szUTF8FileNameLower, (HashDatum)(size_t)token, TRUE); - - // Now make file token associate with the loaded module - m_pManifest->StoreFileThrowing(token, pModule); - - RETURN pModule; -} // Assembly::CreateDynamicModule -#endif // FEATURE_MULTIMODULE_ASSEMBLIES #endif // CROSSGEN_COMPILE @@ -1409,37 +1067,7 @@ void Assembly::SetParent(BaseDomain* pParent) mdFile Assembly::GetManifestFileToken(LPCSTR name) { -#ifdef FEATURE_MULTIMODULE_ASSEMBLIES - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - FORBID_FAULT; - MODE_ANY; - SUPPORTS_DAC; - } - CONTRACTL_END; - - HashDatum datum; - // Note: We're doing a case sensitive lookup - // This is OK because the lookup string and the string we insert into the hashtable - // are obtained from the same place. - - // m_pAllowedFiles only grows - entries are never deleted from it. So we do not take - // a lock around GetValue. If the code is modified such that we delete entries from m_pAllowedFiles, - // reconsider whether the callers that consume the mdFile should take the m_crstAllowedFiles lock. - if (m_pAllowedFiles->GetValue(name, &datum)) { - - if (datum != NULL) // internal module - return (mdFile)(size_t)PTR_TO_TADDR(datum); - else // manifest file - return mdFileNil; - } - else - return mdTokenNil; // not found -#else return mdFileNil; -#endif } mdFile Assembly::GetManifestFileToken(IMDInternalImport *pImport, mdFile kFile) @@ -1772,11 +1400,6 @@ Module * Assembly::FindModuleByTypeRef( RETURN NULL; } -#ifndef FEATURE_CORECLR - // Event Tracing for Windows is used to log data for performance and functional testing purposes. - // The events below are used to help measure the performance of assembly loading of a static reference. - FireEtwLoaderPhaseStart((::GetAppDomain() ? ::GetAppDomain()->GetId().m_dwId : ETWAppDomainIdNotAvailable), ETWLoadContextNotAvailable, ETWFieldUnused, ETWLoaderStaticLoad, NULL, NULL, GetClrInstanceId()); -#endif //!FEATURE_CORECLR DomainAssembly * pDomainAssembly = pModule->LoadAssembly( ::GetAppDomain(), @@ -1784,27 +1407,6 @@ Module * Assembly::FindModuleByTypeRef( szNamespace, szClassName); -#ifndef FEATURE_CORECLR - if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_Context, TRACE_LEVEL_INFORMATION, CLR_PRIVATEBINDING_KEYWORD)) - { - StackSString assemblySimpleName; - EX_TRY - { - if ((pDomainAssembly != NULL) && (pDomainAssembly->GetCurrentAssembly() != NULL)) - { - assemblySimpleName.AppendUTF8(pDomainAssembly->GetCurrentAssembly()->GetSimpleName()); - assemblySimpleName.Normalize(); // Ensures that the later cast to LPCWSTR does not throw. - } - } - EX_CATCH - { - assemblySimpleName.Clear(); - } - EX_END_CATCH(RethrowTransientExceptions) - - FireEtwLoaderPhaseEnd(::GetAppDomain() ? ::GetAppDomain()->GetId().m_dwId : ETWAppDomainIdNotAvailable, ETWLoadContextNotAvailable, ETWFieldUnused, ETWLoaderStaticLoad, NULL, assemblySimpleName.IsEmpty() ? NULL : (LPCWSTR)assemblySimpleName, GetClrInstanceId()); - } -#endif //!FEATURE_CORECLR if (pDomainAssembly == NULL) RETURN NULL; @@ -1889,105 +1491,6 @@ void Assembly::CacheManifestExportedTypes(AllocMemTracker *pamTracker) } void Assembly::CacheManifestFiles() { -#ifdef FEATURE_MULTIMODULE_ASSEMBLIES - CONTRACT_VOID - { - THROWS; - GC_TRIGGERS; - INJECT_FAULT(COMPlusThrowOM();); - } - CONTRACT_END; - - mdToken tkFile; - LPCSTR pszFileName; - CQuickBytes qbLC; - - HENUMInternalHolder phEnum(GetManifestImport()); - phEnum.EnumInit(mdtFile, - mdTokenNil); - - - DWORD dwCount = GetManifestImport()->EnumGetCount(&phEnum); - LockOwner lockOwner = { &m_crstAllowedFiles, IsOwnerOfCrst }; - if (!m_pAllowedFiles->Init(dwCount+1, &lockOwner)) - ThrowOutOfMemory(); - - CrstHolder lock(&m_crstAllowedFiles); - - m_nextAvailableModuleIndex = dwCount+1; - - while (GetManifestImport()->EnumNext(&phEnum, &tkFile)) - { - if (TypeFromToken(tkFile) == mdtFile) - { - IfFailThrow(GetManifestImport()->GetFileProps( - tkFile, - &pszFileName, - NULL, // hash - NULL, // hash len - NULL)); // flags - - // Add to hash table - m_pAllowedFiles->InsertValue(pszFileName, (HashDatum)(size_t)tkFile, TRUE); - - // Need to perform case insensitive hashing as well. - { - UTF8_TO_LOWER_CASE(pszFileName, qbLC); - pszFileName = (LPUTF8) qbLC.Ptr(); - } - - // Add each internal module - m_pAllowedFiles->InsertValue(pszFileName, (HashDatum)(size_t)tkFile, TRUE); - } - } - - HENUMInternalHolder phEnumModules(GetManifestImport()); - phEnumModules.EnumInit(mdtModuleRef, mdTokenNil); - mdToken tkModuleRef; - - while (GetManifestImport()->EnumNext(&phEnumModules, &tkModuleRef)) - { - LPCSTR pszModuleRefName, pszModuleRefNameLower; - - if (TypeFromToken(tkModuleRef) == mdtModuleRef) - { - IfFailThrow(GetManifestImport()->GetModuleRefProps(tkModuleRef, &pszModuleRefName)); - - // Convert to lower case and lookup - { - UTF8_TO_LOWER_CASE(pszModuleRefName, qbLC); - pszModuleRefNameLower = (LPUTF8) qbLC.Ptr(); - } - - HashDatum datum; - if (m_pAllowedFiles->GetValue(pszModuleRefNameLower, &datum)) - { - mdFile tkFileForModuleRef = (mdFile)(size_t)datum; - m_pAllowedFiles->InsertValue(pszModuleRefName, (HashDatum)(size_t)tkFileForModuleRef); - } - } - } - - // Add the manifest file - if (!GetManifestImport()->IsValidToken(GetManifestImport()->GetModuleFromScope())) - { - ThrowHR(COR_E_BADIMAGEFORMAT); - } - IfFailThrow(GetManifestImport()->GetScopeProps(&pszFileName, NULL)); - - // Add to hash table - m_pAllowedFiles->InsertValue(pszFileName, NULL, TRUE); - - // Need to perform case insensitive hashing as well. - { - UTF8_TO_LOWER_CASE(pszFileName, qbLC); - pszFileName = (LPUTF8) qbLC.Ptr(); - } - - m_pAllowedFiles->InsertValue(pszFileName, NULL, TRUE); - - RETURN; -#endif } @@ -2042,57 +1545,7 @@ void Assembly::PublishModuleIntoAssembly(Module *module) -#ifdef FEATURE_MULTIMODULE_ASSEMBLIES -Module* Assembly::FindModule(PEFile *pFile, BOOL includeLoading) -{ - CONTRACT(Module *) - { - THROWS; - GC_TRIGGERS; - INJECT_FAULT(COMPlusThrowOM();); - } - CONTRACT_END; - - DomainFile *pModule = GetDomainAssembly()->FindModule(pFile, includeLoading); - - if (pModule == NULL) - RETURN NULL; - else - RETURN pModule->GetModule(); -} -#endif // FEATURE_MULTIMODULE_ASSEMBLIES - -#ifdef FEATURE_MIXEDMODE -DomainFile* Assembly::FindIJWDomainFile(HMODULE hMod, const SString &path) -{ - CONTRACT (DomainFile*) - { - INSTANCE_CHECK; - THROWS; - GC_TRIGGERS; - MODE_ANY; - PRECONDITION(CheckPointer(GetManifestModule())); - POSTCONDITION(CheckPointer(RETVAL, NULL_OK)); - } - CONTRACT_END; - - ModuleIterator i = IterateModules(); - while (i.Next()) - { - PEFile *pFile = i.GetModule()->GetFile(); - if ( !pFile->IsResource() - && !pFile->IsDynamic() - && !pFile->IsILOnly()) - { - if ( (pFile->GetLoadedIL()!= NULL && pFile->GetIJWBase() == hMod) - || PEImage::PathEquals(pFile->GetPath(), path)) - RETURN i.GetModule()->GetDomainFile(); - } - } - RETURN NULL; -} -#endif // FEATURE_MIXEDMODE //***************************************************************************** // Set up the list of names of any friend assemblies @@ -2211,236 +1664,28 @@ enum CorEntryPointType EntryCrtMain // unsigned main(void) }; -#ifdef STRESS_THREAD - -struct Stress_Thread_Param +void DECLSPEC_NORETURN ThrowMainMethodException(MethodDesc* pMD, UINT resID) { - MethodDesc *pFD; - GlobalStrongHandleHolder argHandle; - short numSkipArgs; - CorEntryPointType EntryType; - Thread* pThread; - -public: - Stress_Thread_Param() - : pFD(NULL), - argHandle(), - numSkipArgs(0), - EntryType(EntryManagedMain), - pThread(NULL) - { LIMITED_METHOD_CONTRACT; } - - Stress_Thread_Param* Clone () + CONTRACTL { - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - } - CONTRACTL_END; - - NewHolder retVal= new Stress_Thread_Param; - - retVal->pFD = pFD; - if (argHandle.GetValue()!=NULL) - { - GCX_COOP(); - retVal->argHandle.Assign(CreateDuplicateHandle(argHandle.GetValue())); - } - retVal->numSkipArgs = numSkipArgs; - retVal->EntryType = EntryType; - retVal->pThread = pThread; - return retVal.Extract(); + THROWS; + GC_TRIGGERS; + MODE_ANY; + INJECT_FAULT(COMPlusThrowOM()); } -}; - -struct Stress_Thread_Worker_Param -{ - Stress_Thread_Param *lpParameter; - ULONG retVal; -}; - -static void Stress_Thread_Proc_Worker_Impl(Stress_Thread_Worker_Param * args) -{ - STATIC_CONTRACT_THROWS; - - args->retVal = E_FAIL; - - Stress_Thread_Param* lpParam = (Stress_Thread_Param *)args->lpParameter; - - ARG_SLOT stackVar = 0; - - MethodDescCallSite threadStart(lpParam->pFD); + CONTRACTL_END; - // Build the parameter array and invoke the method. - if (lpParam->EntryType == EntryManagedMain) + DefineFullyQualifiedNameForClassW(); + LPCWSTR szClassName = GetFullyQualifiedNameForClassW(pMD->GetMethodTable()); + LPCUTF8 szUTFMethodName; + if (FAILED(pMD->GetMDImport()->GetNameOfMethodDef(pMD->GetMemberDef(), &szUTFMethodName))) { - PTRARRAYREF StrArgArray = (PTRARRAYREF)ObjectFromHandle(lpParam->argHandle.GetValue()); - stackVar = ObjToArgSlot(StrArgArray); + szUTFMethodName = "Invalid MethodDef record"; } - - if (lpParam->pFD->IsVoid()) - { - threadStart.Call(&stackVar); - args->retVal = GetLatchedExitCode(); - } - else - { - // We are doing the same cast as in RunMain. Main is required to return INT32 if it returns. - ARG_SLOT retVal = (INT32)threadStart.Call_RetArgSlot(&stackVar); - args->retVal = static_cast(retVal); - } -} - -// wrap into EX_TRY_NOCATCH and call the real thing -static void Stress_Thread_Proc_Worker (LPVOID ptr) -{ - STATIC_CONTRACT_THROWS; - - EX_TRY_NOCATCH(Stress_Thread_Worker_Param *, args, (Stress_Thread_Worker_Param *) ptr) - { - Stress_Thread_Proc_Worker_Impl(args); - // - // When we get mainCRTStartup from the C++ then this should be able to go away. - fflush(stdout); - fflush(stderr); - } - EX_END_NOCATCH -} - -static DWORD WINAPI __stdcall Stress_Thread_Proc (LPVOID lpParameter) -{ - STATIC_CONTRACT_THROWS; - - Stress_Thread_Worker_Param args = {(Stress_Thread_Param*)lpParameter,0}; - Stress_Thread_Param *lpParam = (Stress_Thread_Param *)lpParameter; - Thread *pThread = lpParam->pThread; - if (!pThread->HasStarted()) - return 0; - - _ASSERTE(::GetAppDomain() != NULL); - BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(return E_FAIL); - EX_TRY - { - - ADID KickOffDomain = pThread->GetKickOffDomainId(); - - // should always have a kickoff domain - a thread should never start in a domain that is unloaded - // because otherwise it would have been collected because nobody can hold a reference to thread object - // in a domain that has been unloaded. But it is possible that we started the unload, in which - // case this thread wouldn't be allowed in or would be punted anyway. - if (KickOffDomain != lpParam->pThread->GetDomain()->GetId()) - pThread->DoADCallBack(KickOffDomain, Stress_Thread_Proc_Worker, &args); - else - Stress_Thread_Proc_Worker(&args); - - } - EX_CATCH - { - } - EX_END_CATCH(SwallowAllExceptions); - - delete (Stress_Thread_Param *) lpParameter; - // Enable preemptive GC so a GC thread can suspend me. - GCX_PREEMP_NO_DTOR(); - DestroyThread(pThread); - - END_SO_INTOLERANT_CODE; - return args.retVal; -} - -static void Stress_Thread_Start (LPVOID lpParameter) -{ - CONTRACT_VOID - { - THROWS; - GC_TRIGGERS; - INJECT_FAULT(COMPlusThrowOM()); - MODE_ANY; - } - CONTRACT_END; - - Thread *pCurThread = GetThread(); - if (pCurThread->m_stressThreadCount == -1) { - pCurThread->m_stressThreadCount = g_pConfig->GetStressThreadCount(); - } - DWORD dwThreads = pCurThread->m_stressThreadCount; - if (dwThreads <= 1) - RETURN; - - Thread ** threads = new Thread* [dwThreads-1]; - - DWORD n; - for (n = 0; n < dwThreads-1; n ++) - { - threads[n] = SetupUnstartedThread(); - - threads[n]->m_stressThreadCount = dwThreads/2; - Stress_Thread_Param *param = ((Stress_Thread_Param*)lpParameter)->Clone(); - param->pThread = threads[n]; - if (!threads[n]->CreateNewThread(0, Stress_Thread_Proc, param)) - { - delete param; - threads[n]->DecExternalCount(FALSE); - ThrowOutOfMemory(); - } - threads[n]->SetThreadPriority (THREAD_PRIORITY_NORMAL); - } - - for (n = 0; n < dwThreads-1; n ++) - { - threads[n]->StartThread(); - } - __SwitchToThread (0, CALLER_LIMITS_SPINNING); - - RETURN; -} - -void Stress_Thread_RunMain(MethodDesc* pFD, CorEntryPointType EntryType, short numSkipArgs, OBJECTHANDLE argHandle) -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - } - CONTRACTL_END; - - Stress_Thread_Param Param; - Param.pFD = pFD; - Param.argHandle.Assign(argHandle); - Param.numSkipArgs = numSkipArgs; - Param.EntryType = EntryType; - Param.pThread = NULL; - Stress_Thread_Start (&Param); -} - - -#endif // STRESS_THREAD - -void DECLSPEC_NORETURN ThrowMainMethodException(MethodDesc* pMD, UINT resID) -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - INJECT_FAULT(COMPlusThrowOM()); - } - CONTRACTL_END; - - DefineFullyQualifiedNameForClassW(); - LPCWSTR szClassName = GetFullyQualifiedNameForClassW(pMD->GetMethodTable()); - LPCUTF8 szUTFMethodName; - if (FAILED(pMD->GetMDImport()->GetNameOfMethodDef(pMD->GetMemberDef(), &szUTFMethodName))) - { - szUTFMethodName = "Invalid MethodDef record"; - } - PREFIX_ASSUME(szUTFMethodName!=NULL); - MAKE_WIDEPTR_FROMUTF8(szMethodName, szUTFMethodName); - COMPlusThrowHR(COR_E_METHODACCESS, resID, szClassName, szMethodName); -} + PREFIX_ASSUME(szUTFMethodName!=NULL); + MAKE_WIDEPTR_FROMUTF8(szMethodName, szUTFMethodName); + COMPlusThrowHR(COR_E_METHODACCESS, resID, szClassName, szMethodName); +} // Returns true if this is a valid main method? void ValidateMainMethod(MethodDesc * pFD, CorEntryPointType *pType) @@ -2547,20 +1792,7 @@ HRESULT RunMain(MethodDesc *pFD , if ((EntryType == EntryManagedMain) && (stringArgs == NULL)) { - #ifndef FEATURE_CORECLR - // If you look at the DIFF on this code then you will see a major change which is that we - // no longer accept all the different types of data arguments to main. We now only accept - // an array of strings. - - wzArgs = CorCommandLine::GetArgvW(&cCommandArgs); - // In the WindowsCE case where the app has additional args the count will come back zero. - if (cCommandArgs > 0) { - if (!wzArgs) - return E_INVALIDARG; - } -#else // !FEATURE_CORECLR return E_INVALIDARG; -#endif // !FEATURE_CORECLR } ETWFireEvent(Main_V1); @@ -2606,11 +1838,6 @@ HRESULT RunMain(MethodDesc *pFD , StrArgArray = *pParam->stringArgs; } -#ifdef STRESS_THREAD - OBJECTHANDLE argHandle = (StrArgArray != NULL) ? CreateGlobalStrongHandle (StrArgArray) : NULL; - Stress_Thread_RunMain(pParam->pFD, pParam->EntryType, pParam->numSkipArgs, argHandle); -#endif - ARG_SLOT stackVar = ObjToArgSlot(StrArgArray); if (pParam->pFD->IsVoid()) @@ -2711,37 +1938,12 @@ INT32 Assembly::ExecuteMainMethod(PTRARRAYREF *stringArgs, BOOL waitForOtherThre if (pMeth) { RunMainPre(); -#if defined(FEATURE_APPX_BINDER) && defined(FEATURE_MULTICOREJIT) - if (AppX::IsAppXProcess()) - { - GCX_PREEMP(); - - // we call this to obtain and cache the PRAID value which is used - // by multicore JIT manager and watson bucket params generation. - - // NOTE: this makes a COM call into WinRT so we must do this after we've - // set the thread's apartment state which will do CoInitializeEx(). - LPCWSTR praid; - hr = AppX::GetApplicationId(praid); - _ASSERTE(SUCCEEDED(hr)); - - if (!pMeth->GetModule()->HasNativeImage()) - { - // For Appx, multicore JIT is only needed when root assembly does not have NI image - // When it has NI image, we can't generate profile, and do not need to playback profile - AppDomain * pDomain = pThread->GetDomain(); - pDomain->GetMulticoreJitManager().AutoStartProfileAppx(pDomain); - } - } -#endif // FEATURE_APPX_BINDER && FEATURE_MULTICOREJIT -#ifdef FEATURE_CORECLR // Set the root assembly as the assembly that is containing the main method // The root assembly is used in the GetEntryAssembly method that on CoreCLR is used // to get the TargetFrameworkMoniker for the app AppDomain * pDomain = pThread->GetDomain(); pDomain->SetRootAssembly(pMeth->GetAssembly()); -#endif hr = RunMain(pMeth, 1, &iRetVal, stringArgs); } } @@ -2884,161 +2086,6 @@ BOOL Assembly::FileNotFound(HRESULT hr) (hr == CLR_E_BIND_TYPE_NOT_FOUND); } -#ifdef FEATURE_MULTIMODULE_ASSEMBLIES -PEModule * Assembly::LoadModule_AddRef(mdFile kFile, BOOL fLoadResource) -{ - CONTRACT(PEModule *) - { - INSTANCE_CHECK; - THROWS; - GC_TRIGGERS; - MODE_ANY; - POSTCONDITION(CheckPointer(RETVAL, fLoadResource ? NULL_NOT_OK : NULL_OK)); - INJECT_FAULT(COMPlusThrowOM();); - } - CONTRACT_END - - if (! ((TypeFromToken(kFile) == mdtFile) && - GetManifestImport()->IsValidToken(kFile)) ) - { - ThrowHR(COR_E_BADIMAGEFORMAT, BFA_INVALID_FILE_TOKEN); - } - - LPCSTR psModuleName; - DWORD dwFlags; - IfFailThrow(GetManifestImport()->GetFileProps( - kFile, - &psModuleName, - NULL, - NULL, - &dwFlags)); - - if (! (IsFfContainsMetaData(dwFlags) || fLoadResource) ) - RETURN NULL; - - SString name(SString::Utf8, psModuleName); - PEModule * pModule = NULL; - - if (AssemblySpec::VerifyBindingString((LPCWSTR)name)) - { - EX_TRY - { - GCX_PREEMP(); - -#ifdef FEATURE_FUSION // specific to remote modules - if (GetFusionAssembly()) { - StackSString path; - ::GetAppDomain()->GetFileFromFusion(GetFusionAssembly(), - (LPCWSTR)name, path); - pModule = PEModule::Open(m_pManifestFile, kFile, path); - goto lDone; - } - - if (GetIHostAssembly()) { - pModule = PEModule::Open(m_pManifestFile, kFile, name); - goto lDone; - } -#endif - if (!m_pManifestFile->GetPath().IsEmpty()) { - StackSString path = m_pManifestFile->GetPath(); - - SString::Iterator i = path.End()-1; - - if (PEAssembly::FindLastPathSeparator(path, i)) { - path.Truncate(++i); - path.Insert(i, name); - } - pModule = PEModule::Open(m_pManifestFile, kFile, path); - } -#ifdef FEATURE_FUSION - lDone: ; -#endif - } - EX_CATCH - { - Exception *ex = GET_EXCEPTION(); - if (FileNotFound(ex->GetHR()) || - (ex->GetHR() == FUSION_E_INVALID_NAME)) - pModule = RaiseModuleResolveEvent_AddRef(psModuleName, kFile); - - if (pModule == NULL) - { - EEFileLoadException::Throw(name, ex->GetHR(), ex); - } - } - EX_END_CATCH(SwallowAllExceptions) - } - - if (pModule == NULL) - { - pModule = RaiseModuleResolveEvent_AddRef(psModuleName, kFile); - if (pModule == NULL) - { - EEFileLoadException::Throw(name, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)); - } - } - - RETURN pModule; -} - -PEModule * Assembly::RaiseModuleResolveEvent_AddRef(LPCSTR szName, mdFile kFile) -{ - CONTRACT(PEModule *) - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - INJECT_FAULT(COMPlusThrowOM();); - POSTCONDITION(CheckPointer(RETVAL, NULL_OK)); - } - CONTRACT_END; - - Module* pModule = NULL; - -#ifndef CROSSGEN_COMPILE - GCX_COOP(); - - struct _gc { - OBJECTREF AssemblyRef; - STRINGREF str; - } gc; - ZeroMemory(&gc, sizeof(gc)); - - GCPROTECT_BEGIN(gc); - if ((gc.AssemblyRef = GetExposedObject()) != NULL) - { - MethodDescCallSite onModuleResolve(METHOD__ASSEMBLY__ON_MODULE_RESOLVE, &gc.AssemblyRef); - gc.str = StringObject::NewString(szName); - ARG_SLOT args[2] = { - ObjToArgSlot(gc.AssemblyRef), - ObjToArgSlot(gc.str) - }; - - REFLECTMODULEBASEREF ResultingModuleRef = - (REFLECTMODULEBASEREF) onModuleResolve.Call_RetOBJECTREF(args); - - if (ResultingModuleRef != NULL) - { - pModule = ResultingModuleRef->GetModule(); - } - } - GCPROTECT_END(); - - if (pModule && ( (!(pModule->IsIntrospectionOnly())) != !(IsIntrospectionOnly()) )) - { - COMPlusThrow(kFileLoadException, IDS_CLASSLOAD_MODULE_RESOLVE_INTROSPECTION_MISMATCH); - } - - if ((pModule != NULL) && - (pModule == m_pManifest->LookupFile(kFile))) - { - RETURN clr::SafeAddRef((PEModule *)pModule->GetFile()); - } -#endif // CROSSGEN_COMPILE - - RETURN NULL; -} -#endif // FEATURE_MULTIMODULE_ASSEMBLIES BOOL Assembly::GetResource(LPCSTR szName, DWORD *cbResource, PBYTE *pbInMemoryResource, Assembly** pAssemblyRef, @@ -3072,21 +2119,37 @@ BOOL Assembly::IsInstrumented() STATIC_CONTRACT_GC_TRIGGERS; STATIC_CONTRACT_FAULT; - BOOL isInstrumented = false; - - EX_TRY + // This will set the value of m_isInstrumentedStatus by calling IsInstrumentedHelper() + // that method performs string pattern matching using the Config value of ZapBBInstr + // We cache the value returned from that method in m_isInstrumentedStatus + // + if (m_isInstrumentedStatus == IS_INSTRUMENTED_UNSET) { - FAULT_NOT_FATAL(); + EX_TRY + { + FAULT_NOT_FATAL(); - isInstrumented = IsInstrumentedHelper(); - } - EX_CATCH - { - isInstrumented = false; + if (IsInstrumentedHelper()) + { + m_isInstrumentedStatus = IS_INSTRUMENTED_TRUE; + } + else + { + m_isInstrumentedStatus = IS_INSTRUMENTED_FALSE; + } + } + + EX_CATCH + { + m_isInstrumentedStatus = IS_INSTRUMENTED_FALSE; + } + EX_END_CATCH(RethrowTerminalExceptions); } - EX_END_CATCH(RethrowTerminalExceptions); - return isInstrumented; + // At this point m_isInstrumentedStatus can't have the value of IS_INSTRUMENTED_UNSET + _ASSERTE(m_isInstrumentedStatus != IS_INSTRUMENTED_UNSET); + + return (m_isInstrumentedStatus == IS_INSTRUMENTED_TRUE); } BOOL Assembly::IsInstrumentedHelper() @@ -3100,7 +2163,7 @@ BOOL Assembly::IsInstrumentedHelper() return false; // We must have a native image in order to perform IBC instrumentation - if (!GetManifestFile()->HasNativeImage()) + if (!GetManifestFile()->HasNativeOrReadyToRunImage()) return false; // @Consider using the full name instead of the short form @@ -3173,24 +2236,13 @@ mdAssemblyRef Assembly::AddAssemblyRef(Assembly *refedAssembly, IMetaDataAssembl GC_TRIGGERS; INJECT_FAULT(COMPlusThrowOM();); PRECONDITION(CheckPointer(refedAssembly)); -#ifdef FEATURE_CORECLR PRECONDITION(CheckPointer(pAssemEmitter, NULL_NOT_OK)); -#else - PRECONDITION(CheckPointer(pAssemEmitter, NULL_OK)); -#endif //FEATURE_CORECLR POSTCONDITION(!IsNilToken(RETVAL)); POSTCONDITION(TypeFromToken(RETVAL) == mdtAssemblyRef); } CONTRACT_END; SafeComHolder emitHolder; -#if !defined(FEATURE_CORECLR) && !defined(CROSSGEN_COMPILE) - if (pAssemEmitter == NULL) - { - pAssemEmitter = GetOnDiskMDAssemblyEmitter(); - emitHolder.Assign(pAssemEmitter); - } -#endif // FEATURE_CORECLR && !CROSSGEN_COMPILE AssemblySpec spec; spec.InitializeSpec(refedAssembly->GetManifestFile()); @@ -3258,778 +2310,56 @@ void Assembly::AddExportedType(mdExportedType cl) } -#if !defined(FEATURE_CORECLR) && !defined(CROSSGEN_COMPILE) -//*********************************************************** -// -// get the IMetaDataAssemblyEmit for the on disk manifest. -// Note that the pointer returned is AddRefed. It is the caller's -// responsibility to release the reference. -// -//*********************************************************** -IMetaDataAssemblyEmit *Assembly::GetOnDiskMDAssemblyEmitter() + +HRESULT STDMETHODCALLTYPE +GetAssembliesByName(LPCWSTR szAppBase, + LPCWSTR szPrivateBin, + LPCWSTR szAssemblyName, + IUnknown *ppIUnk[], + ULONG cMax, + ULONG *pcAssemblies) { CONTRACTL { - THROWS; + NOTHROW; + MODE_PREEMPTIVE; GC_TRIGGERS; - INJECT_FAULT(COMPlusThrowOM();); + INJECT_FAULT(return E_OUTOFMEMORY;); } CONTRACTL_END - IMetaDataAssemblyEmit *pAssemEmitter = NULL; - IMetaDataEmit *pEmitter; - RefClassWriter *pRCW; + HRESULT hr = S_OK; - _ASSERTE(m_pOnDiskManifest); + if (g_fEEInit) { + // Cannot call this during EE startup + return MSEE_E_ASSEMBLYLOADINPROGRESS; + } - pRCW = m_pOnDiskManifest->GetClassWriter(); - _ASSERTE(pRCW); + if (!(szAssemblyName && ppIUnk && pcAssemblies)) + return E_POINTER; - // If the RefClassWriter has a on disk emitter, then use it rather than the in-memory emitter. - pEmitter = pRCW->GetOnDiskEmitter(); + hr = COR_E_NOTSUPPORTED; - if (pEmitter == NULL) - pEmitter = m_pOnDiskManifest->GetEmitter(); - - _ASSERTE(pEmitter != NULL); - - IfFailThrow(pEmitter->QueryInterface(IID_IMetaDataAssemblyEmit, (void**) &pAssemEmitter)); - - if (pAssemEmitter == NULL) - { - // the manifest is not writable - _ASSERTE(!"Bad usage!"); - } - return pAssemEmitter; -} + return hr; +}// Used by the IMetadata API's to access an assemblies metadata. -//*********************************************************** -// -// prepare saving manifest to disk. -// -//*********************************************************** -void Assembly::PrepareSavingManifest(ReflectionModule *pAssemblyModule) +#ifdef FEATURE_LOADER_OPTIMIZATION + +void Assembly::SetMissingDependenciesCheckDone() { - STANDARD_VM_CONTRACT; + LIMITED_METHOD_CONTRACT; + m_bMissingDependenciesCheckDone=TRUE; +}; - if (pAssemblyModule) - { - // embedded assembly - m_pOnDiskManifest = pAssemblyModule; - m_fEmbeddedManifest = true; - } - else - { - m_fEmbeddedManifest = false; - - StackSString name(SString::Utf8, GetSimpleName()); - - // Create the module - m_pOnDiskManifest = CreateDynamicModule(name, name, FALSE /*fIsTransient*/); - // store the fact this on disk manifest is temporary and can be hidden from the user - m_needsToHideManifestForEmit = TRUE; - } - - NonVMComHolder pAssemblyEmit(GetOnDiskMDAssemblyEmitter()); - - // Copy assembly metadata to emit scope - //@todo: add Title, Description, Alias as CA - // @todo: propagate all of the information - // @todo: introduce a helper in metadata to take the ansi version of string. - - IMetaDataAssemblyImport *pAssemblyImport = GetManifestFile()->GetAssemblyImporter(); - - const void *pbPublicKey; - ULONG cbPublicKey; - ULONG ulHashAlgId; - LPWSTR szName; - ULONG chName; - ASSEMBLYMETADATA MetaData; - DWORD dwAssemblyFlags; - - MetaData.cbLocale = 0; - MetaData.ulProcessor = 0; - MetaData.ulOS = 0; - IfFailThrow(pAssemblyImport->GetAssemblyProps(TokenFromRid(1, mdtAssembly), - NULL, NULL, NULL, - NULL, 0, &chName, - &MetaData, NULL)); - StackSString name; - szName = name.OpenUnicodeBuffer(chName); - - SString locale; - MetaData.szLocale = locale.OpenUnicodeBuffer(MetaData.cbLocale); - - SBuffer proc; - MetaData.rProcessor = (DWORD *) proc.OpenRawBuffer(MetaData.ulProcessor*sizeof(*MetaData.rProcessor)); - - SBuffer os; - MetaData.rOS = (OSINFO *) os.OpenRawBuffer(MetaData.ulOS*sizeof(*MetaData.rOS)); - - IfFailThrow(pAssemblyImport->GetAssemblyProps(TokenFromRid(1, mdtAssembly), - &pbPublicKey, &cbPublicKey, &ulHashAlgId, - szName, chName, &chName, - &MetaData, &dwAssemblyFlags)); - - mdAssembly ad; - IfFailThrow(pAssemblyEmit->DefineAssembly(pbPublicKey, cbPublicKey, ulHashAlgId, - szName, &MetaData, dwAssemblyFlags, &ad)); - - SafeComHolder pImport; - IfFailThrow(pAssemblyEmit->QueryInterface(IID_IMetaDataImport, (void**)&pImport)); - ULONG cExistingName = 0; - if (FAILED(pImport->GetScopeProps(NULL, 0, &cExistingName, NULL)) || cExistingName == 0) - { - SafeComHolder pEmit; - IfFailThrow(pAssemblyEmit->QueryInterface(IID_IMetaDataEmit, (void**)&pEmit)); - IfFailThrow(pEmit->SetModuleProps(szName)); - } - - name.CloseBuffer(); - locale.CloseBuffer(); - proc.CloseRawBuffer(); - os.CloseRawBuffer(); -} // Assembly::PrepareSavingManifest - - -//*********************************************************** -// -// add a file name to the file list of this assembly. On disk only. -// -//*********************************************************** -mdFile Assembly::AddFile(LPCWSTR wszFileName) -{ - STANDARD_VM_CONTRACT; - - SafeComHolder pAssemEmitter(GetOnDiskMDAssemblyEmitter()); - mdFile fl; - - // Define File. - IfFailThrow( pAssemEmitter->DefineFile( - wszFileName, // [IN] Name of the file. - 0, // [IN] Hash Blob. - 0, // [IN] Count of bytes in the Hash Blob. - 0, // [IN] Flags. - &fl) ); // [OUT] Returned File token. - - return fl; -} // Assembly::AddFile - - -//*********************************************************** -// -// Set the hash value on a file table entry. -// -//*********************************************************** -void Assembly::SetFileHashValue(mdFile tkFile, LPCWSTR wszFullFileName) -{ - STANDARD_VM_CONTRACT; - - SafeComHolder pAssemEmitter(GetOnDiskMDAssemblyEmitter()); - - // Get the hash value. - SBuffer buffer; - PEImageHolder map(PEImage::OpenImage(StackSString(wszFullFileName))); - map->ComputeHash(GetHashAlgId(), buffer); - - // Set the hash blob. - IfFailThrow( pAssemEmitter->SetFileProps( - tkFile, // [IN] File Token. - buffer, // [IN] Hash Blob. - buffer.GetSize(), // [IN] Count of bytes in the Hash Blob. - (DWORD) -1)); // [IN] Flags. - -} // Assembly::SetHashValue - -//***************************************************************************** -// Add a Type name to the ExportedType table in the on-disk assembly manifest. -//***************************************************************************** -mdExportedType Assembly::AddExportedTypeOnDisk(LPCWSTR wszExportedType, mdToken tkImpl, mdToken tkTypeDef, CorTypeAttr flags) -{ - STANDARD_VM_CONTRACT; - - _ASSERTE(TypeFromToken(tkTypeDef) == mdtTypeDef); - - // The on-disk assembly manifest - SafeComHolder pAssemEmitter(GetOnDiskMDAssemblyEmitter()); - - mdExportedType ct; - - IfFailThrow( pAssemEmitter->DefineExportedType( - wszExportedType, // [IN] Name of the COMType. - tkImpl, // [IN] mdFile or mdAssemblyRef that provides the ExportedType. - tkTypeDef, // [IN] TypeDef token within the file. - flags, // [IN] Flags. - &ct) ); // [OUT] Returned ExportedType token. - - return ct; -} // Assembly::AddExportedTypeOnDisk - -//******************************************************************************* -// Add a Type name to the ExportedType table in the in-memory assembly manifest. -//******************************************************************************* -mdExportedType Assembly::AddExportedTypeInMemory(LPCWSTR wszExportedType, mdToken tkImpl, mdToken tkTypeDef, CorTypeAttr flags) -{ - STANDARD_VM_CONTRACT; - - _ASSERTE(TypeFromToken(tkTypeDef) == mdtTypeDef); - - // The in-memory assembly manifest - IMetaDataAssemblyEmit* pAssemEmitter = GetManifestFile()->GetAssemblyEmitter(); - - mdExportedType ct; - - IfFailThrow( pAssemEmitter->DefineExportedType( - wszExportedType, // [IN] Name of the COMType. - tkImpl, // [IN] mdFile or mdAssemblyRef that provides the ExportedType. - tkTypeDef, // [IN] TypeDef token within the file. - flags, // [IN] Flags. - &ct) ); // [OUT] Returned ExportedType token. - - return ct; -} // Assembly::AddExportedTypeInMemory - - -//*********************************************************** -// add an entry to ManifestResource table for a stand alone managed resource. On disk only. -//*********************************************************** -void Assembly::AddStandAloneResource(LPCWSTR wszName, LPCWSTR wszDescription, LPCWSTR wszMimeType, LPCWSTR wszFileName, LPCWSTR wszFullFileName, int iAttribute) -{ - STANDARD_VM_CONTRACT; - - SafeComHolder pAssemEmitter(GetOnDiskMDAssemblyEmitter()); - mdFile tkFile; - mdManifestResource mr; - SBuffer hash; - - // Get the hash value; - if (GetHashAlgId()) - { - PEImageHolder pImage(PEImage::OpenImage(StackSString(wszFullFileName))); - pImage->ComputeHash(GetHashAlgId(), hash); - } - - IfFailThrow( pAssemEmitter->DefineFile( - wszFileName, // [IN] Name of the file. - hash, // [IN] Hash Blob. - hash.GetSize(), // [IN] Count of bytes in the Hash Blob. - ffContainsNoMetaData, // [IN] Flags. - &tkFile) ); // [OUT] Returned File token. - - - IfFailThrow( pAssemEmitter->DefineManifestResource( - wszName, // [IN] Name of the resource. - tkFile, // [IN] mdFile or mdAssemblyRef that provides the resource. - 0, // [IN] Offset to the beginning of the resource within the file. - iAttribute, // [IN] Flags. - &mr) ); // [OUT] Returned ManifestResource token. - -} // Assembly::AddStandAloneResource - - -//*********************************************************** -// Save security permission requests. -//*********************************************************** -void Assembly::AddDeclarativeSecurity(DWORD dwAction, void const *pValue, DWORD cbValue) -{ - STANDARD_VM_CONTRACT; - - mdAssembly tkAssembly = 0x20000001; - - SafeComHolder pAssemEmitter(GetOnDiskMDAssemblyEmitter()); - _ASSERTE( pAssemEmitter ); - - SafeComHolder pEmitHelper; - IfFailThrow( pAssemEmitter->QueryInterface(IID_IMetaDataEmitHelper, (void**)&pEmitHelper) ); - - IfFailThrow(pEmitHelper->AddDeclarativeSecurityHelper(tkAssembly, - dwAction, - pValue, - cbValue, - NULL)); -} - - -//*********************************************************** -// Allocate space for a strong name signature in the manifest -//*********************************************************** -HRESULT Assembly::AllocateStrongNameSignature(ICeeFileGen *pCeeFileGen, - HCEEFILE ceeFile) -{ - CONTRACTL - { - NOTHROW; - GC_TRIGGERS; - MODE_PREEMPTIVE; - INJECT_FAULT(return E_OUTOFMEMORY;); - } - CONTRACTL_END - - HRESULT hr; - HCEESECTION TData; - DWORD dwDataOffset; - DWORD dwDataLength; - DWORD dwDataRVA; - VOID *pvBuffer; - const void *pbPublicKey; - ULONG cbPublicKey; - - // Determine size of signature blob. - - IfFailRet(GetManifestImport()->GetAssemblyProps(TokenFromRid(1, mdtAssembly), - &pbPublicKey, &cbPublicKey, NULL, - NULL, NULL, NULL)); - - if (!StrongNameSignatureSize((BYTE *) pbPublicKey, cbPublicKey, &dwDataLength)) { - hr = StrongNameErrorInfo(); - return hr; - } - - // Allocate space for the signature in the text section and update the COM+ - // header to point to the space. - IfFailRet(pCeeFileGen->GetIlSection(ceeFile, &TData)); - IfFailRet(pCeeFileGen->GetSectionDataLen(TData, &dwDataOffset)); - IfFailRet(pCeeFileGen->GetSectionBlock(TData, dwDataLength, 4, &pvBuffer)); - IfFailRet(pCeeFileGen->GetMethodRVA(ceeFile, dwDataOffset, &dwDataRVA)); - IfFailRet(pCeeFileGen->SetStrongNameEntry(ceeFile, dwDataLength, dwDataRVA)); - - return S_OK; -} - - -//*********************************************************** -// Strong name sign a manifest already persisted to disk -//*********************************************************** -HRESULT Assembly::SignWithStrongName(LPCWSTR wszFileName) -{ - CONTRACTL - { - NOTHROW; - GC_TRIGGERS; - INJECT_FAULT(return E_OUTOFMEMORY;); - } - CONTRACTL_END - - HRESULT hr = S_OK; - - // If we're going to do a full signing we have a key pair either - // in a key container or provided directly in a byte array. - - switch (m_eStrongNameLevel) { - case SN_FULL_KEYPAIR_IN_ARRAY: - if (!StrongNameSignatureGeneration(wszFileName, NULL, m_pbStrongNameKeyPair, m_cbStrongNameKeyPair, NULL, NULL)) - hr = StrongNameErrorInfo(); - break; - - case SN_FULL_KEYPAIR_IN_CONTAINER: - if (!StrongNameSignatureGeneration(wszFileName, m_pwStrongNameKeyContainer, NULL, 0, NULL, NULL)) - hr = StrongNameErrorInfo(); - break; - - default: - break; - } - - return hr; -} - - -//*********************************************************** -// save the manifest to disk! -//*********************************************************** -void Assembly::SaveManifestToDisk(LPCWSTR wszFileName, int entrypoint, int fileKind, DWORD corhFlags, DWORD peFlags) -{ - STANDARD_VM_CONTRACT; - - HRESULT hr = NOERROR; - HCEEFILE ceeFile = NULL; - ICeeFileGen *pCeeFileGen = NULL; - RefClassWriter *pRCW; - IMetaDataEmit *pEmitter; - - _ASSERTE( m_fEmbeddedManifest == false ); - - pRCW = m_pOnDiskManifest->GetClassWriter(); - _ASSERTE(pRCW); - - IfFailGo( pRCW->EnsureCeeFileGenCreated(corhFlags, peFlags) ); - - pCeeFileGen = pRCW->GetCeeFileGen(); - ceeFile = pRCW->GetHCEEFILE(); - _ASSERTE(ceeFile && pCeeFileGen); - - //Emit the MetaData - pEmitter = m_pOnDiskManifest->GetClassWriter()->GetEmitter(); - IfFailGo( pCeeFileGen->EmitMetaDataEx(ceeFile, pEmitter) ); - - // Allocate space for a strong name signature if a public key was supplied - // (this doesn't strong name the assembly, but it makes it possible to do so - // as a post processing step). - if (IsStrongNamed()) - IfFailGo(AllocateStrongNameSignature(pCeeFileGen, ceeFile)); - - IfFailGo( pCeeFileGen->SetOutputFileName(ceeFile, (LPWSTR)wszFileName) ); - - // the entryPoint for an assembly is a tkFile token if exist. - if (RidFromToken(entrypoint) != mdTokenNil) - IfFailGo( pCeeFileGen->SetEntryPoint(ceeFile, entrypoint) ); - if (fileKind == Dll) - { - pCeeFileGen->SetDllSwitch(ceeFile, true); - } - else - { - // should have a valid entry point for applications - if (fileKind == WindowApplication) - { - IfFailGo( pCeeFileGen->SetSubsystem(ceeFile, IMAGE_SUBSYSTEM_WINDOWS_GUI, CEE_IMAGE_SUBSYSTEM_MAJOR_VERSION, CEE_IMAGE_SUBSYSTEM_MINOR_VERSION) ); - } - else - { - _ASSERTE(fileKind == ConsoleApplication); - IfFailGo( pCeeFileGen->SetSubsystem(ceeFile, IMAGE_SUBSYSTEM_WINDOWS_CUI, CEE_IMAGE_SUBSYSTEM_MAJOR_VERSION, CEE_IMAGE_SUBSYSTEM_MINOR_VERSION) ); - } - - } - - //Generate the CeeFile - IfFailGo(pCeeFileGen->GenerateCeeFile(ceeFile) ); - - // Strong name sign the resulting assembly if required. - if (IsStrongNamed()) - IfFailGo(SignWithStrongName(wszFileName)); - - // now release the m_pOnDiskManifest -ErrExit: - pRCW->DestroyCeeFileGen(); - - // we keep the on disk manifest so that the GetModules code can skip over this ad-hoc module when modules are enumerated. - // Need to see if we can remove the creation of this module alltogether - //m_pOnDiskManifest = NULL; - - if (FAILED(hr)) - { - if (HRESULT_FACILITY(hr) == FACILITY_WIN32) - { - if (IsWin32IOError(HRESULT_CODE(hr))) - { - COMPlusThrowHR(COR_E_IO); - } - else - { - COMPlusThrowHR(hr); - } - } - if (hr == CEE_E_CVTRES_NOT_FOUND) - COMPlusThrow(kIOException, W("Argument_cvtres_NotFound")); - COMPlusThrowHR(hr); - } -} // Assembly::SaveManifestToDisk - -#endif // FEATURE_CORECLR && !CROSSGEN_COMPILE - - -HRESULT STDMETHODCALLTYPE -GetAssembliesByName(LPCWSTR szAppBase, - LPCWSTR szPrivateBin, - LPCWSTR szAssemblyName, - IUnknown *ppIUnk[], - ULONG cMax, - ULONG *pcAssemblies) -{ - CONTRACTL - { - NOTHROW; - MODE_PREEMPTIVE; - GC_TRIGGERS; - INJECT_FAULT(return E_OUTOFMEMORY;); - } - CONTRACTL_END - - HRESULT hr = S_OK; - - if (g_fEEInit) { - // Cannot call this during EE startup - return MSEE_E_ASSEMBLYLOADINPROGRESS; - } - - if (!(szAssemblyName && ppIUnk && pcAssemblies)) - return E_POINTER; - -#if defined(FEATURE_CORECLR) || defined(CROSSGEN_COMPILE) - hr = COR_E_NOTSUPPORTED; -#else - AppDomain *pDomain = NULL; - - BEGIN_EXTERNAL_ENTRYPOINT(&hr) - if(szAppBase || szPrivateBin) - { - GCX_COOP_THREAD_EXISTS(GET_THREAD()); - MethodDescCallSite createDomainEx(METHOD__APP_DOMAIN__CREATE_DOMAINEX); - struct _gc { - STRINGREF pFriendlyName; - STRINGREF pAppBase; - STRINGREF pPrivateBin; - } gc; - ZeroMemory(&gc, sizeof(gc)); - - GCPROTECT_BEGIN(gc); - gc.pFriendlyName = StringObject::NewString(W("GetAssembliesByName")); - - if(szAppBase) - { - gc.pAppBase = StringObject::NewString(szAppBase); - } - - if(szPrivateBin) - { - gc.pPrivateBin = StringObject::NewString(szPrivateBin); - } - - ARG_SLOT args[5] = - { - ObjToArgSlot(gc.pFriendlyName), - NULL, - ObjToArgSlot(gc.pAppBase), - ObjToArgSlot(gc.pPrivateBin), - BoolToArgSlot(false) - }; - APPDOMAINREF pDom = (APPDOMAINREF) createDomainEx.Call_RetOBJECTREF(args); - if (pDom == NULL) - { - hr = E_FAIL; - } - else - { - Context *pContext = CRemotingServices::GetServerContextForProxy((OBJECTREF) pDom); - _ASSERTE(pContext); - pDomain = pContext->GetDomain(); - } - - GCPROTECT_END(); - } - else - pDomain = SystemDomain::System()->DefaultDomain(); - - Assembly *pFoundAssembly; - if (SUCCEEDED(hr)) { - pFoundAssembly = pDomain->LoadAssemblyHelper(szAssemblyName, - NULL); - if (SUCCEEDED(hr)) { - if (cMax < 1) - hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); - else { - ppIUnk[0] = (IUnknown *)pFoundAssembly->GetManifestAssemblyImporter(); - ppIUnk[0]->AddRef(); - } - *pcAssemblies = 1; - } - } - - END_EXTERNAL_ENTRYPOINT; -#endif // FEATURE_CORECLR - - return hr; -}// Used by the IMetadata API's to access an assemblies metadata. - -#ifdef FEATURE_LOADER_OPTIMIZATION - -void Assembly::SetMissingDependenciesCheckDone() -{ - LIMITED_METHOD_CONTRACT; - m_bMissingDependenciesCheckDone=TRUE; -}; - -BOOL Assembly::MissingDependenciesCheckDone() -{ - LIMITED_METHOD_CONTRACT; - return m_bMissingDependenciesCheckDone; -}; - - -#ifdef FEATURE_FUSION -void Assembly::SetBindingClosure(IAssemblyBindingClosure* pClosure) // Addrefs. It is assumed the caller did not addref pClosure for us. -{ - CONTRACTL - { - THROWS; - GC_NOTRIGGER; - INJECT_FAULT(COMPlusThrowOM();); - } - CONTRACTL_END; - - _ASSERTE(m_pBindingClosure == NULL); - _ASSERTE(pClosure != NULL); - - m_pBindingClosure = pClosure; - pClosure->AddRef(); // It is assumed the caller did not addref pBindingClosure for us. -} - -IAssemblyBindingClosure * Assembly::GetBindingClosure() -{ - LIMITED_METHOD_CONTRACT; - return m_pBindingClosure; -} - - -// The shared module list is effectively an extension of the shared domain assembly hash table. -// It is the canonical list and aribiter of modules loaded from this assembly by any app domain. -// Modules are stored here immediately on creating (to prevent duplicate creation), as opposed to -// in the rid map, where they are only placed upon load completion. - -BOOL Assembly::CanBeShared(DomainAssembly *pDomainAssembly) -{ - CONTRACTL - { - PRECONDITION(CheckPointer(pDomainAssembly)); - THROWS; - GC_TRIGGERS; - INJECT_FAULT(COMPlusThrowOM();); - } - CONTRACTL_END; - - LOG((LF_CODESHARING, - LL_INFO100, - "Checking if we can share: \"%S\" in domain 0x%x.\n", - GetDebugName(), pDomainAssembly->GetAppDomain())); - - STRESS_LOG2(LF_CODESHARING, LL_INFO1000,"Checking whether DomainAssembly %p is compatible with Assembly %p", - pDomainAssembly,this); - - // We must always share the same system assemblies - if (IsSystem()) - { - STRESS_LOG0(LF_CODESHARING, LL_INFO1000,"System assembly - sharing"); - return TRUE; - } - - if ((pDomainAssembly->GetDebuggerInfoBits()&~(DACF_PDBS_COPIED|DACF_IGNORE_PDBS|DACF_OBSOLETE_TRACK_JIT_INFO)) - != (m_debuggerFlags&~(DACF_PDBS_COPIED|DACF_IGNORE_PDBS|DACF_OBSOLETE_TRACK_JIT_INFO))) - { - LOG((LF_CODESHARING, - LL_INFO100, - "We can't share it, desired debugging flags %x are different than %x\n", - pDomainAssembly->GetDebuggerInfoBits(), (m_debuggerFlags&~(DACF_PDBS_COPIED|DACF_IGNORE_PDBS|DACF_OBSOLETE_TRACK_JIT_INFO)))); - STRESS_LOG2(LF_CODESHARING, LL_INFO100,"Flags diff= %08x [%08x/%08x]",pDomainAssembly->GetDebuggerInfoBits(), - m_debuggerFlags); - g_dwLoaderReasonForNotSharing = ReasonForNotSharing_DebuggerFlagMismatch; - return FALSE; - } - - PEAssembly * pDomainAssemblyFile = pDomainAssembly->GetFile(); - if (pDomainAssemblyFile == NULL) - { - g_dwLoaderReasonForNotSharing = ReasonForNotSharing_NullPeassembly; - return FALSE; - } - - IAssemblyBindingClosure * pContext = GetBindingClosure(); - if (pContext == NULL) - { - STRESS_LOG1(LF_CODESHARING, LL_INFO1000,"No context 1 - status=%d",pDomainAssemblyFile->IsSystem()); - if (pDomainAssemblyFile->IsSystem()) - return TRUE; - else - { - g_dwLoaderReasonForNotSharing = ReasonForNotSharing_MissingAssemblyClosure1; - return FALSE; - } - } - - IAssemblyBindingClosure * pCurrentContext = pDomainAssembly->GetAssemblyBindingClosure(LEVEL_STARTING); - if (pCurrentContext == NULL) - { - STRESS_LOG1(LF_CODESHARING, LL_INFO1000,"No context 2 - status=%d",pDomainAssemblyFile->IsSystem()); - if (pDomainAssemblyFile->IsSystem()) - return TRUE; - else - { - g_dwLoaderReasonForNotSharing = ReasonForNotSharing_MissingAssemblyClosure2; - return FALSE; - } - } - - // ensure the closures are walked - { - ReleaseHolder pWinRTBindResult; - - IUnknown * pUnk; - if (pDomainAssembly->GetFile()->IsWindowsRuntime()) - { // It is .winmd file (WinRT assembly) - IfFailThrow(CLRPrivAssemblyWinRT::GetIBindResult(pDomainAssembly->GetFile()->GetHostAssembly(), &pWinRTBindResult)); - pUnk = pWinRTBindResult; - } - else - { - pUnk = pDomainAssembly->GetFile()->GetFusionAssembly(); - } - - GCX_PREEMP(); - IfFailThrow(pCurrentContext->EnsureWalked(pUnk, ::GetAppDomain()->GetFusionContext(), LEVEL_COMPLETE)); - } - - if ((pContext->HasBeenWalked(LEVEL_COMPLETE) != S_OK) || !MissingDependenciesCheckDone()) - { - GCX_COOP(); - - BOOL fMissingDependenciesResolved = FALSE; - - ENTER_DOMAIN_PTR(SystemDomain::System()->DefaultDomain(), ADV_DEFAULTAD); - { - { - ReleaseHolder pWinRTBindResult; - - IUnknown * pUnk; - if (GetManifestFile()->IsWindowsRuntime()) - { // It is .winmd file (WinRT assembly) - IfFailThrow(CLRPrivAssemblyWinRT::GetIBindResult(GetManifestFile()->GetHostAssembly(), &pWinRTBindResult)); - pUnk = pWinRTBindResult; - } - else - { - pUnk = GetManifestFile()->GetFusionAssembly(); - } - - GCX_PREEMP(); - IfFailThrow(pContext->EnsureWalked(pUnk, ::GetAppDomain()->GetFusionContext(), LEVEL_COMPLETE)); - } - DomainAssembly * domainAssembly = ::GetAppDomain()->FindDomainAssembly(this); - if (domainAssembly != NULL) - { - if (domainAssembly->CheckMissingDependencies() == CMD_Resolved) - { - //cannot share - fMissingDependenciesResolved = TRUE; - } - } - } - END_DOMAIN_TRANSITION; - - if (fMissingDependenciesResolved) - { - STRESS_LOG0(LF_CODESHARING, LL_INFO1000,"Missing dependencies resolved - not sharing"); - g_dwLoaderReasonForNotSharing = ReasonForNotSharing_MissingDependenciesResolved; - return FALSE; - } - } +BOOL Assembly::MissingDependenciesCheckDone() +{ + LIMITED_METHOD_CONTRACT; + return m_bMissingDependenciesCheckDone; +}; - HRESULT hr = pContext->IsEqual(pCurrentContext); - IfFailThrow(hr); - if (hr != S_OK) - { - STRESS_LOG1(LF_CODESHARING, LL_INFO1000,"Closure comparison returned %08x - not sharing",hr); - g_dwLoaderReasonForNotSharing = ReasonForNotSharing_ClosureComparisonFailed; - return FALSE; - } - LOG((LF_CODESHARING, LL_INFO100, "We can share it : \"%S\"\n", GetDebugName())); - STRESS_LOG0(LF_CODESHARING, LL_INFO1000,"Everything is fine - sharing"); - return TRUE; -} -#endif -#ifdef FEATURE_VERSIONING BOOL Assembly::CanBeShared(DomainAssembly *pDomainAssembly) { @@ -4059,11 +2389,10 @@ BOOL Assembly::CanBeShared(DomainAssembly *pDomainAssembly) return TRUE; } -#endif // FEATURE_VERSIONING #endif // FEATURE_LOADER_OPTIMIZATION -#if defined(FEATURE_APTCA) || defined(FEATURE_CORESYSTEM) +#if defined(FEATURE_CORESYSTEM) BOOL Assembly::AllowUntrustedCaller() { CONTRACTL @@ -4076,7 +2405,7 @@ BOOL Assembly::AllowUntrustedCaller() return ModuleSecurityDescriptor::GetModuleSecurityDescriptor(this)->IsAPTCA(); } -#endif // defined(FEATURE_APTCA) || defined(FEATURE_CORESYSTEM) +#endif // defined(FEATURE_CORESYSTEM) void DECLSPEC_NORETURN Assembly::ThrowTypeLoadException(LPCUTF8 pszFullName, UINT resIDWhy) { @@ -4306,365 +2635,6 @@ IWinMDImport *Assembly::GetManifestWinMDImport() #endif // FEATURE_COMINTEROP -#if !defined(FEATURE_CORECLR) && !defined(CROSSGEN_COMPILE) -void Assembly::GenerateBreadcrumbForServicing() -{ - STANDARD_VM_CONTRACT; - - if (AppX::IsAppXProcess() || IsIntrospectionOnly() || GetManifestFile()->IsDynamic()) - { - return; - } - - if (HasServiceableAttribute() || IsExistingOobAssembly()) - { - StackSString ssDisplayName; - GetDisplayName(ssDisplayName); - - WriteBreadcrumb(ssDisplayName); - CheckDenyList(ssDisplayName); - } -} - -void Assembly::WriteBreadcrumb(const SString &ssDisplayName) -{ - STANDARD_VM_CONTRACT; - - WCHAR path[MAX_LONGPATH]; - HRESULT hr = WszSHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, SHGFP_TYPE_CURRENT, ARRAYSIZE(path), path); - if (hr != S_OK) - { - return; - } - - if (wcscat_s(path, W("\\Microsoft\\NetFramework\\BreadcrumbStore\\")) != 0) - { - return; - } - - size_t dirPathLen = wcslen(path); - - // Validate the display name. E.g., we don't want the display name to start with "..\\". - bool inSimpleName = true; - for (SString::CIterator it = ssDisplayName.Begin(); it != ssDisplayName.End(); ++it) - { - WCHAR c = *it; - - // The following characters are always allowed: a-zA-Z0-9_ - if (c >= W('a') && c <= W('z') || c >= W('A') && c <= W('Z') || c >= W('0') && c <= W('9') || c == W('_')) continue; - - // The period is allowed except as the first char. - if (c == W('.') && it != ssDisplayName.Begin()) continue; - - // A comma terminates the assembly simple name, and we are in key=value portion of the display name. - if (c == W(',')) - { - inSimpleName = false; - continue; - } - - // In key=value portion, space and equal sign are also allowed. - if (!inSimpleName && (c == W(' ') || c == W('='))) continue; - - // If we reach here, we have an invalid assembly display name. Return without writing breadcrumb. - return; - } - - // Log a breadcrumb using full display name. - if (wcscat_s(path, ssDisplayName.GetUnicode()) == 0) - { - HandleHolder hFile = WszCreateFile(path, 0, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); - } - - // Log another breadcrumb using display name without version. - // First make a copy of the display name, and look for its version part. - StackSString ssNoVersion(ssDisplayName); - SString::Iterator itVersion = ssNoVersion.Begin(); - if (!ssNoVersion.Find(itVersion, W(", Version="))) - { - return; - } - - // Start from the comma before Version=, advance past the comma, then look for the next comma. - SString::Iterator itVersionEnd = itVersion; - ++itVersionEnd; - if (!ssNoVersion.Find(itVersionEnd, W(','))) - { - // Version is the last key=value pair. - itVersionEnd = ssNoVersion.End(); - } - - // Erase the version. - ssNoVersion.Delete(itVersion, itVersionEnd - itVersion); - - // Generate the full path string and create the file. - path[dirPathLen] = W('\0'); - if (wcscat_s(path, ssNoVersion.GetUnicode()) == 0) - { - HandleHolder hFile = WszCreateFile(path, 0, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); - } - -} - -bool Assembly::HasServiceableAttribute() -{ - STANDARD_VM_CONTRACT; - - IMDInternalImport *pImport = GetManifestImport(); - MDEnumHolder hEnum(pImport); - HRESULT hr = pImport->EnumCustomAttributeByNameInit(GetManifestToken(), ASSEMBLY_METADATA_TYPE, &hEnum); - if (hr != S_OK) - { - return false; - } - - mdCustomAttribute tkAttribute; - while (pImport->EnumNext(&hEnum, &tkAttribute)) - { - // Get raw custom attribute. - const BYTE *pbAttr = NULL; // Custom attribute data as a BYTE*. - ULONG cbAttr = 0; // Size of custom attribute data. - if (FAILED(pImport->GetCustomAttributeAsBlob(tkAttribute, reinterpret_cast(&pbAttr), &cbAttr))) - { - THROW_BAD_FORMAT(BFA_INVALID_TOKEN, GetManifestModule()); - } - - CustomAttributeParser cap(pbAttr, cbAttr); - if (FAILED(cap.ValidateProlog())) - { - THROW_BAD_FORMAT(BFA_BAD_CA_HEADER, GetManifestModule()); - } - - // Get the metadata key. It is not null terminated. - LPCUTF8 key; - ULONG cbKey; - if (FAILED(cap.GetString(&key, &cbKey))) - { - THROW_BAD_FORMAT(BFA_BAD_CA_HEADER, GetManifestModule()); - } - - const LPCUTF8 szServiceable = "Serviceable"; - const ULONG cbServiceable = 11; - if (cbKey != cbServiceable || strncmp(key, szServiceable, cbKey) != 0) - { - continue; - } - - // Get the metadata value. It is not null terminated. - if (FAILED(cap.GetString(&key, &cbKey))) - { - THROW_BAD_FORMAT(BFA_BAD_CA_HEADER, GetManifestModule()); - } - - const LPCUTF8 szTrue = "True"; - const ULONG cbTrue = 4; - if (cbKey == cbTrue && strncmp(key, szTrue, cbKey) == 0) - { - return true; - } - } - - return false; -} - -bool Assembly::IsExistingOobAssembly() -{ - WRAPPER_NO_CONTRACT; - - return ExistingOobAssemblyList::Instance()->IsOnlist(this); -} - -void Assembly::CheckDenyList(const SString &ssDisplayName) -{ - STANDARD_VM_CONTRACT; - - StackSString ssKeyName(W("SOFTWARE\\Microsoft\\.NETFramework\\Policy\\DenyList\\")); - - ssKeyName.Append(ssDisplayName); - - RegKeyHolder hKey; - LONG status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, ssKeyName.GetUnicode(), 0, KEY_WOW64_64KEY | GENERIC_READ, &hKey); - - if (status != ERROR_SUCCESS) - { - return; - } - - StackSString ssFwlink; - HRESULT hr = Clr::Util::Reg::ReadStringValue(hKey, NULL, NULL, ssFwlink); - if (FAILED(hr) || ssFwlink.GetCount() == 0) - { - ssFwlink.Set(W("http://go.microsoft.com/fwlink/?LinkID=286319")); - } - - StackSString ssMessageTemplate; - if(!ssMessageTemplate.LoadResource(CCompRC::Optional, IDS_EE_ASSEMBLY_ON_DENY_LIST)) - { - ssMessageTemplate.Set(W("The assembly %1 that the application tried to load has a known vulnerability. Please go to %2 to find a fix for this issue.")); - } - - StackSString ssMessage; - ssMessage.FormatMessage(FORMAT_MESSAGE_FROM_STRING, ssMessageTemplate.GetUnicode(), 0, 0, ssDisplayName, ssFwlink); - - ClrReportEvent( - W(".NET Runtime"), // Event source - EVENTLOG_ERROR_TYPE, // Type - 0, // Category - SecurityConfig, // Event ID - NULL, // User SID - ssMessage.GetUnicode()); // Message - - NewHolder pEx(new EEMessageException(kSecurityException, IDS_EE_ASSEMBLY_ON_DENY_LIST, ssDisplayName.GetUnicode(), ssFwlink.GetUnicode())); - EEFileLoadException::Throw(m_pManifestFile, pEx->GetHR(), pEx); -} - -BOOL IsReportableAssembly(PEAssembly *pPEAssembly) -{ - STANDARD_VM_CONTRACT; - - // If the assembly could have used a native image, but did not, report the IL image - BOOL fCanUseNativeImage = (pPEAssembly->HasHostAssembly() || pPEAssembly->IsContextLoad()) && - pPEAssembly->CanUseNativeImage() && - !IsNativeImageOptedOut(pPEAssembly->GetFusionAssemblyName()); - - return fCanUseNativeImage; -} - -BOOL Assembly::SupportsAutoNGenWorker() -{ - STANDARD_VM_CONTRACT; - - PEAssembly *pPEAssembly = GetManifestFile(); - - if (pPEAssembly->IsSourceGAC() && Fusion::Util::IsUnifiedAssembly(pPEAssembly->GetFusionAssemblyName()) == S_OK) - { - // Assemblies in the .NET Framework supports Auto NGen. - return TRUE; - } - - if (IsAfContentType_WindowsRuntime(GetFlags())) - { - // WinMD files support Auto NGen. - return TRUE; - } - - if (pPEAssembly->HasHostAssembly()) - { - // Auto NGen is enabled on all Metro app assemblies. - return TRUE; - } - - if (pPEAssembly->IsSourceGAC()) - { - // For non-framework assemblies in GAC, look for TargetFrameworkAttriute. - const BYTE *pbAttr; // Custom attribute data as a BYTE*. - ULONG cbAttr; // Size of custom attribute data. - HRESULT hr = GetManifestImport()->GetCustomAttributeByName(GetManifestToken(), TARGET_FRAMEWORK_TYPE, (const void**)&pbAttr, &cbAttr); - if (hr != S_OK) - { - return FALSE; - } - - CustomAttributeParser cap(pbAttr, cbAttr); - if (FAILED(cap.ValidateProlog())) - { - THROW_BAD_FORMAT(BFA_BAD_CA_HEADER, GetManifestModule()); - } - LPCUTF8 lpTargetFramework; - ULONG cbTargetFramework; - if (FAILED(cap.GetString(&lpTargetFramework, &cbTargetFramework))) - { - THROW_BAD_FORMAT(BFA_BAD_CA_HEADER, GetManifestModule()); - } - - if (lpTargetFramework == NULL || cbTargetFramework == 0) - { - return FALSE; - } - - SString ssTargetFramework(SString::Utf8, lpTargetFramework, cbTargetFramework); - - // Look for two special TargetFramework values that disables AutoNGen. To guard against future - // variations of the string values, we do prefix matches. - SString ssFramework40(SString::Literal, W(".NETFramework,Version=v4.0")); - SString ssPortableLib(SString::Literal, W(".NETPortable,")); - if (ssTargetFramework.BeginsWithCaseInsensitive(ssFramework40) || ssTargetFramework.BeginsWithCaseInsensitive(ssPortableLib)) - { - return FALSE; - } - - // If TargetFramework doesn't match one of the two special values, we enable Auto NGen. - return TRUE; - } - - return FALSE; -} - -void Assembly::ReportAssemblyUse() -{ - STANDARD_VM_CONTRACT; - - // Do not log if we don't have a global gac logger object - if (g_pIAssemblyUsageLogGac != NULL) - { - // Only consider reporting for loads that could possibly use native images. - PEAssembly *pPEAssembly = this->GetManifestFile(); - if (IsReportableAssembly(pPEAssembly) && !pPEAssembly->IsReportedToUsageLog()) - { - // Do not log repeatedly - pPEAssembly->SetReportedToUsageLog(); - - ReleaseHolder pRefCountedUsageLog; - IAssemblyUsageLog *pUsageLog = NULL; - if (SupportsAutoNGen()) - { - if (pPEAssembly->IsSourceGAC()) - { - pUsageLog = g_pIAssemblyUsageLogGac; - } - else if (pPEAssembly->HasHostAssembly()) - { - UINT_PTR binderId; - IfFailThrow(pPEAssembly->GetHostAssembly()->GetBinderID(&binderId)); - pRefCountedUsageLog = AssemblyUsageLogManager::GetUsageLogForBinder(binderId); - pUsageLog = pRefCountedUsageLog; - } - } - - if (pUsageLog) - { - PEAssembly *pPEAssembly = GetManifestFile(); - StackSString name; - // GAC Assemblies are reported by assembly name - if (pUsageLog == g_pIAssemblyUsageLogGac) - { - this->GetDisplayName(name); - } - // Other assemblies (AppX...) are reported by file path - else - { - name.Set(pPEAssembly->GetILimage()->GetPath().GetUnicode()); - } - - if (pPEAssembly->HasNativeImage()) - { - if(!IsSystem()) - { - // If the assembly used a native image, report it - ReleaseHolder pNativeImage = pPEAssembly->GetNativeImageWithRef(); - pUsageLog->LogFile(name.GetUnicode(), pNativeImage->GetPath().GetUnicode(), ASSEMBLY_USAGE_LOG_FLAGS_NI); - } - } - else - { - // If the assembly could have used a native image, but did not, report the IL image - pUsageLog->LogFile(name.GetUnicode(), NULL, ASSEMBLY_USAGE_LOG_FLAGS_IL); - } - } - } - } -} -#endif // FEATURE_CORECLR && !CROSSGEN_COMPILE #endif // #ifndef DACCESS_COMPILE @@ -4750,11 +2720,7 @@ FriendAssemblyDescriptor::~FriendAssemblyDescriptor() while (itFullAccessAssemblies.Next()) { FriendAssemblyName_t *pFriendAssemblyName = static_cast(itFullAccessAssemblies.GetElement()); -#ifdef FEATURE_FUSION - pFriendAssemblyName->Release(); -#else // FEATURE_FUSION delete pFriendAssemblyName; -#endif // FEATURE_FUSION } } @@ -4839,9 +2805,6 @@ FriendAssemblyDescriptor *FriendAssemblyDescriptor::CreateFriendAssemblyDescript // Create an AssemblyNameObject from the string. FriendAssemblyNameHolder pFriendAssemblyName; -#ifdef FEATURE_FUSION - hr = CreateAssemblyNameObject(&pFriendAssemblyName, displayName.GetUnicode(), CANOF_PARSE_FRIEND_DISPLAY_NAME, NULL); -#else // FEATURE_FUSION StackScratchBuffer buffer; pFriendAssemblyName = new FriendAssemblyName_t; hr = pFriendAssemblyName->Init(displayName.GetUTF8(buffer)); @@ -4850,7 +2813,6 @@ FriendAssemblyDescriptor *FriendAssemblyDescriptor::CreateFriendAssemblyDescript { hr = pFriendAssemblyName->CheckFriendAssemblyName(); } -#endif // FEATURE_FUSION if (FAILED(hr)) { @@ -4867,31 +2829,6 @@ FriendAssemblyDescriptor *FriendAssemblyDescriptor::CreateFriendAssemblyDescript // CoreCLR does not have a valid scenario for strong-named assemblies requiring their dependencies // to be strong-named as well. -#if !defined(FEATURE_CORECLR) - // If this assembly has a strong name, then its friends declarations need to have strong names too - if (pAssembly->IsStrongNamed()) - { -#ifdef FEATURE_FUSION - DWORD dwSize = 0; - if (SUCCEEDED(hr = pFriendAssemblyName->GetProperty(ASM_NAME_PUBLIC_KEY, NULL, &dwSize))) - { - // If this call succeeds with an empty buffer, then the supplied name doesn't have a public key. - THROW_HR_ERROR_WITH_INFO(META_E_CA_FRIENDS_SN_REQUIRED, pAssembly); - } - else if (hr != HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) - { - IfFailThrow(hr); - } -#else // FEATURE_FUSION - // Desktop crossgen comes here - if (!pFriendAssemblyName->IsStrongNamed()) - { - // If this call succeeds with an empty buffer, then the supplied name doesn't have a public key. - THROW_HR_ERROR_WITH_INFO(META_E_CA_FRIENDS_SN_REQUIRED, pAssembly); - } -#endif // FEATURE_FUSION - } -#endif // !defined(FEATURE_CORECLR) pFriendAssemblies->AddFriendAssembly(pFriendAssemblyName); @@ -4954,23 +2891,14 @@ bool FriendAssemblyDescriptor::IsAssemblyOnList(PEAssembly *pAssembly, const Arr } CONTRACTL_END; -#ifndef FEATURE_FUSION AssemblySpec asmDef; asmDef.InitializeSpec(pAssembly); -#endif ArrayList::ConstIterator itAssemblyNames = alAssemblyNames.Iterate(); while (itAssemblyNames.Next()) { const FriendAssemblyName_t *pFriendAssemblyName = static_cast(itAssemblyNames.GetElement()); -#ifdef FEATURE_FUSION - // This is a const operation on the pointer, but Fusion is not const-correct. - // @TODO - propigate const correctness through Fusion and remove this cast - HRESULT hr = const_cast(pFriendAssemblyName)->IsEqual(pAssembly->GetFusionAssemblyName(), ASM_CMPF_DEFAULT); - IfFailThrow(hr); -#else HRESULT hr = AssemblySpec::RefMatchesDef(pFriendAssemblyName, &asmDef) ? S_OK : S_FALSE; -#endif if (hr == S_OK) { @@ -4984,70 +2912,3 @@ bool FriendAssemblyDescriptor::IsAssemblyOnList(PEAssembly *pAssembly, const Arr #endif // !DACCESS_COMPILE -#if !defined(FEATURE_CORECLR) && !defined(CROSSGEN_COMPILE) && !defined(DACCESS_COMPILE) - -ExistingOobAssemblyList::ExistingOobAssemblyList() -{ - STANDARD_VM_CONTRACT; - - RegKeyHolder hKey; - LONG status = RegOpenKeyExW(HKEY_LOCAL_MACHINE, W("SOFTWARE\\Microsoft\\.NETFramework\\Policy\\Servicing"), 0, KEY_WOW64_64KEY | GENERIC_READ, &hKey); - if (status != ERROR_SUCCESS) - { - return; - } - - for (DWORD i = 0; ; i++) - { - WCHAR name[MAX_PATH_FNAME + 1]; - DWORD cchName = ARRAYSIZE(name); - status = RegEnumKeyExW(hKey, i, name, &cchName, NULL, NULL, NULL, NULL); - - if (status == ERROR_NO_MORE_ITEMS) - { - break; - } - - if (status == ERROR_SUCCESS) - { - NonVMComHolder pAssemblyName; - HRESULT hr = CreateAssemblyNameObject(&pAssemblyName, name, CANOF_PARSE_DISPLAY_NAME, NULL); - if (SUCCEEDED(hr)) - { - hr = m_alExistingOobAssemblies.Append(pAssemblyName.GetValue()); - if (SUCCEEDED(hr)) - { - pAssemblyName.SuppressRelease(); - } - } - } - } -} - -bool ExistingOobAssemblyList::IsOnlist(Assembly *pAssembly) -{ - STANDARD_VM_CONTRACT; - - ArrayList::Iterator itAssemblyNames = m_alExistingOobAssemblies.Iterate(); - while (itAssemblyNames.Next()) - { - IAssemblyName *pAssemblyName = static_cast(itAssemblyNames.GetElement()); - HRESULT hr = pAssemblyName->IsEqual(pAssembly->GetFusionAssemblyName(), ASM_CMPF_DEFAULT); - if (hr == S_OK) - { - return true; - } - } - - return false; -} - -void ExistingOobAssemblyList::Init() -{ - STANDARD_VM_CONTRACT; - - s_pInstance = new ExistingOobAssemblyList(); -} - -ExistingOobAssemblyList *ExistingOobAssemblyList::s_pInstance; -#endif // !defined(FEATURE_CORECLR) && !defined(CROSSGEN_COMPILE) && !defined(DACCESS_COMPILE) -- cgit v1.2.3