//===================================================================================================================== // Used only for designer binding context CLRPrivBinderAppX * CLRPrivBinderAppX::CreateParentedBinder( ICLRPrivBinder * pParentBinder, CLRPrivTypeCacheWinRT * pWinRtTypeCache, LPCWSTR * rgwzAltPath, UINT cAltPaths, BOOL fCanUseNativeImages) { STANDARD_VM_CONTRACT; HRESULT hr = S_OK; ReleaseHolder<CLRPrivBinderAppX> pBinder; pBinder = clr::SafeAddRef(new CLRPrivBinderAppX(rgwzAltPath, cAltPaths)); pBinder->m_pParentBinder = clr::SafeAddRef(pParentBinder); pBinder->m_fCanUseNativeImages = fCanUseNativeImages; // We want to share FusionBinder with pParentBinder (which bubbles up through the chain of binders to the global AppXBinder code:s_pSingleton) // Ideally we would get the FusionBinder from pParentBinder (via casting to a new interface). It is much easier just to fetch it from // the global AppX binder directly pBinder->m_pFusionBinder = clr::SafeAddRef(s_pSingleton->GetFusionBinder()); if (cAltPaths > 0) { pBinder->m_pWinRTBinder = clr::SafeAddRef(new CLRPrivBinderWinRT( pBinder, pWinRtTypeCache, rgwzAltPath, cAltPaths, CLRPrivBinderWinRT::NamespaceResolutionKind_WindowsAPI, fCanUseNativeImages)); } pBinder.SuppressRelease(); return pBinder; }
// ============================================================================ // CLRPrivBinderCoreCLR implementation // ============================================================================ HRESULT CLRPrivBinderCoreCLR::BindAssemblyByName(IAssemblyName *pIAssemblyName, ICLRPrivAssembly **ppAssembly) { HRESULT hr = S_OK; VALIDATE_ARG_RET(pIAssemblyName != nullptr && ppAssembly != nullptr); EX_TRY { *ppAssembly = nullptr; ReleaseHolder<BINDER_SPACE::Assembly> pCoreCLRFoundAssembly; ReleaseHolder<AssemblyName> pAssemblyName; SAFE_NEW(pAssemblyName, AssemblyName); IF_FAIL_GO(pAssemblyName->Init(pIAssemblyName)); hr = BindAssemblyByNameWorker(pAssemblyName, &pCoreCLRFoundAssembly, false /* excludeAppPaths */); IF_FAIL_GO(hr); *ppAssembly = pCoreCLRFoundAssembly.Extract(); Exit:; } EX_CATCH_HRESULT(hr); return hr; }
HRESULT CCoreCLRBinderHelper::DefaultBinderSetupContext(DWORD dwAppDomainId,CLRPrivBinderCoreCLR **ppTPABinder) { HRESULT hr = S_OK; EX_TRY { if(ppTPABinder != NULL) { ReleaseHolder<CLRPrivBinderCoreCLR> pBinder; SAFE_NEW(pBinder, CLRPrivBinderCoreCLR); BINDER_SPACE::ApplicationContext *pApplicationContext = pBinder->GetAppContext(); hr = pApplicationContext->Init(); if(SUCCEEDED(hr)) { pApplicationContext->SetAppDomainId(dwAppDomainId); pBinder->SetManagedAssemblyLoadContext(NULL); *ppTPABinder = clr::SafeAddRef(pBinder.Extract()); } } } EX_CATCH_HRESULT(hr); Exit: return hr; }
/* static */ HRESULT CLRPrivBinderAssemblyLoadContext::SetupContext(DWORD dwAppDomainId, CLRPrivBinderCoreCLR *pTPABinder, LoaderAllocator* pLoaderAllocator, void* loaderAllocatorHandle, UINT_PTR ptrAssemblyLoadContext, CLRPrivBinderAssemblyLoadContext **ppBindContext) { HRESULT hr = E_FAIL; EX_TRY { if(ppBindContext != NULL) { ReleaseHolder<CLRPrivBinderAssemblyLoadContext> pBinder; SAFE_NEW(pBinder, CLRPrivBinderAssemblyLoadContext); hr = pBinder->m_appContext.Init(); if(SUCCEEDED(hr)) { // Save the reference to the AppDomain in which the binder lives pBinder->m_appContext.SetAppDomainId(dwAppDomainId); // Mark that this binder can explicitly bind to native images pBinder->m_appContext.SetExplicitBindToNativeImages(true); // Save reference to the TPABinder that is required to be present. _ASSERTE(pTPABinder != NULL); pBinder->m_pTPABinder = pTPABinder; // Save the reference to the IntPtr for GCHandle for the managed // AssemblyLoadContext instance pBinder->m_ptrManagedAssemblyLoadContext = ptrAssemblyLoadContext; if (pLoaderAllocator != NULL) { // Link to LoaderAllocator, keep a reference to it VERIFY(pLoaderAllocator->AddReferenceIfAlive()); } pBinder->m_pAssemblyLoaderAllocator = pLoaderAllocator; pBinder->m_loaderAllocatorHandle = loaderAllocatorHandle; #if !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE) if (pLoaderAllocator != NULL) { ((AssemblyLoaderAllocator*)pLoaderAllocator)->RegisterBinder(pBinder); } #endif // Return reference to the allocated Binder instance *ppBindContext = clr::SafeAddRef(pBinder.Extract()); } } } EX_CATCH_HRESULT(hr); Exit: return hr; }
//===================================================================================================================== STDMETHODIMP CLRPrivBinderLoadFile::BindAssemblyExplicit( PEImage* pImage, IAssemblyName **ppAssemblyName, ICLRPrivAssembly ** ppAssembly) { STANDARD_BIND_CONTRACT; PRECONDITION(AppDomain::GetCurrentDomain()->IsDefaultDomain()); VALIDATE_ARG_RET(pImage != nullptr); VALIDATE_ARG_RET(ppAssemblyName != nullptr); VALIDATE_ARG_RET(ppAssembly != nullptr); HRESULT hr = S_OK; fusion::logging::StatusScope logStatus(0, ID_FUSLOG_BINDING_STATUS_LOAD_FILE, &hr); ReleaseHolder<IAssemblyName> pAssemblyName; ReleaseHolder<ICLRPrivAssembly> pAssembly; EX_TRY { // check if a framework assembly { AssemblySpec spec; mdAssembly a; IfFailThrow(pImage->GetMDImport()->GetAssemblyFromScope(&a)); spec.InitializeSpec(a, pImage->GetMDImport(), NULL, false); IfFailThrow(spec.CreateFusionName(&pAssemblyName)); } hr = IfTransientFailThrow(m_pFrameworkBinder->BindFusionAssemblyByName( pAssemblyName, CLRPrivBinderFusion::kBindingScope_FrameworkSubset, &pAssembly)); if (FAILED(hr)) // not a Framework assembly { ReleaseHolder<CLRPrivResourcePathImpl> pPathResource = clr::SafeAddRef(new CLRPrivResourcePathImpl(pImage->GetPath().GetUnicode())); pAssembly = clr::SafeAddRef(new CLRPrivAssemblyLoadFile(this, m_pFrameworkBinder, pPathResource)); hr = S_OK; } } EX_CATCH_HRESULT(hr); if (SUCCEEDED(hr)) { *ppAssemblyName = pAssemblyName.Extract(); *ppAssembly = pAssembly.Extract(); } return hr; };
//===================================================================================================================== HRESULT CLRPrivBinderAppX::BindAppXAssemblyByName( IAssemblyName * pIAssemblyName, DWORD dwAppXBindFlags, ICLRPrivAssembly ** ppPrivAssembly) { STANDARD_VM_CONTRACT; HRESULT hr = S_OK; ReleaseHolder<CLRPrivAssemblyAppX> pAppXAssembly; IfFailRet(BindAppXAssemblyByNameWorker(pIAssemblyName, dwAppXBindFlags, &pAppXAssembly)); IfFailRet(pAppXAssembly->QueryInterface(__uuidof(ICLRPrivAssembly), (LPVOID*)ppPrivAssembly)); return hr; }
//===================================================================================================================== CLRPrivBinderAppX * CLRPrivBinderAppX::GetOrCreateBinder() { STANDARD_VM_CONTRACT; HRESULT hr = S_OK; if (s_pSingleton == nullptr) { ReleaseHolder<IAssemblyUsageLog> pNewUsageLog; IfFailThrow(AssemblyUsageLogManager::GetUsageLogForContext(W("App"), AppX::GetHeadPackageMoniker(), &pNewUsageLog)); ReleaseHolder<CLRPrivBinderAppX> pBinder; pBinder = clr::SafeAddRef(new CLRPrivBinderAppX(nullptr, 0)); pBinder->m_pFusionBinder = clr::SafeAddRef(new CLRPrivBinderFusion()); CLRPrivTypeCacheWinRT * pWinRtTypeCache = CLRPrivTypeCacheWinRT::GetOrCreateTypeCache(); pBinder->m_pWinRTBinder = clr::SafeAddRef(new CLRPrivBinderWinRT( pBinder, pWinRtTypeCache, nullptr, // rgwzAltPath 0, // cAltPaths CLRPrivBinderWinRT::NamespaceResolutionKind_WindowsAPI, TRUE // fCanUseNativeImages )); if (InterlockedCompareExchangeT<decltype(s_pSingleton)>(&s_pSingleton, pBinder, nullptr) == nullptr) pBinder.SuppressRelease(); // Register binder with usagelog infrastructure. UINT_PTR binderId; IfFailThrow(pBinder->GetBinderID(&binderId)); IfFailThrow(AssemblyUsageLogManager::RegisterBinderWithUsageLog(binderId, pNewUsageLog)); // Create and register WinRT usage log ReleaseHolder<IAssemblyUsageLog> pNewWinRTUsageLog; IfFailThrow(AssemblyUsageLogManager::GetUsageLogForContext(W("WinRT"), AppX::GetHeadPackageMoniker(), &pNewWinRTUsageLog)); UINT_PTR winRTBinderId; IfFailThrow(pBinder->m_pWinRTBinder->GetBinderID(&winRTBinderId)); IfFailThrow(AssemblyUsageLogManager::RegisterBinderWithUsageLog(winRTBinderId, pNewWinRTUsageLog)); } return s_pSingleton; }
//===================================================================================================================== HRESULT CLRPrivBinderAppX::PreBindAppXAssemblyByName( IAssemblyName * pIAssemblyName, DWORD dwAppXBindFlags, IBindResult ** ppIBindResult) { STANDARD_VM_CONTRACT; HRESULT hr = S_OK; VALIDATE_ARG_RET(pIAssemblyName != nullptr); VALIDATE_ARG_RET(ppIBindResult != nullptr); ReleaseHolder<CLRPrivAssemblyAppX> pAppXAssembly; IfFailRet(BindAppXAssemblyByNameWorker(pIAssemblyName, dwAppXBindFlags, &pAppXAssembly)); IfFailRet(pAppXAssembly->GetIBindResult(ppIBindResult)); return hr; }
// See code:BINDER_SPACE::AssemblyBinder::GetAssembly for info on fNgenExplicitBind // and fExplicitBindToNativeImage, and see code:CEECompileInfo::LoadAssemblyByPath // for an example of how they're used. HRESULT CLRPrivBinderCoreCLR::Bind(SString &assemblyDisplayName, LPCWSTR wszCodeBase, PEAssembly *pParentAssembly, BOOL fNgenExplicitBind, BOOL fExplicitBindToNativeImage, ICLRPrivAssembly **ppAssembly) { HRESULT hr = S_OK; VALIDATE_ARG_RET(ppAssembly != NULL); AssemblyName assemblyName; ReleaseHolder<AssemblyName> pAssemblyName; if (!assemblyDisplayName.IsEmpty()) { // AssemblyDisplayName can be empty if wszCodeBase is specified. SAFE_NEW(pAssemblyName, AssemblyName); IF_FAIL_GO(pAssemblyName->Init(assemblyDisplayName)); } EX_TRY { ReleaseHolder<BINDER_SPACE::Assembly> pAsm; hr = AssemblyBinder::BindAssembly(&m_appContext, pAssemblyName, wszCodeBase, pParentAssembly, fNgenExplicitBind, fExplicitBindToNativeImage, false, // excludeAppPaths &pAsm); if(SUCCEEDED(hr)) { _ASSERTE(pAsm != NULL); pAsm->SetBinder(this); *ppAssembly = pAsm.Extract(); } } EX_CATCH_HRESULT(hr); Exit: return hr; }
//************************************************************* // // Open the file with anme wzModule and check to see if there is a type // with namespace/class of wzNamespace/wzType. If so, return the RegMeta // corresponding to the file and the mdTypeDef of the typedef // //************************************************************* HRESULT CORPATHService::FindTypeDef( __in __in_z LPWSTR wzModule, // name of the module that we are going to open mdTypeRef tr, // TypeRef to resolve. IMetaModelCommon * pCommon, // Scope in which the TypeRef is defined. REFIID riid, IUnknown ** ppIScope, mdTypeDef * ptd) // [OUT] the type that we resolve to { HRESULT hr = NOERROR; NewHolder<Disp> pDisp; ReleaseHolder<IMetaDataImport2> pImport = NULL; CQuickArray<mdTypeRef> cqaNesters; CQuickArray<LPCUTF8> cqaNesterNamespaces; CQuickArray<LPCUTF8> cqaNesterNames; RegMeta * pRegMeta; _ASSERTE((ppIScope != NULL) && (ptd != NULL)); *ppIScope = NULL; pDisp = new (nothrow) Disp; IfNullGo(pDisp); IfFailGo(pDisp->OpenScope(wzModule, 0, IID_IMetaDataImport2, (IUnknown **)&pImport)); pRegMeta = static_cast<RegMeta *>(pImport.GetValue()); // Get the Nesting hierarchy. IfFailGo(ImportHelper::GetNesterHierarchy(pCommon, tr, cqaNesters, cqaNesterNamespaces, cqaNesterNames)); hr = ImportHelper::FindNestedTypeDef( pRegMeta->GetMiniMd(), cqaNesterNamespaces, cqaNesterNames, mdTokenNil, ptd); if (SUCCEEDED(hr)) { *ppIScope = pImport.Extract(); } ErrExit: return hr; } // CORPATHService::FindTypeDef
HRESULT CCoreCLRBinderHelper::GetAssemblyFromImage(PEImage *pPEImage, PEImage *pNativePEImage, ICLRPrivAssembly **ppAssembly) { HRESULT hr = S_OK; VALIDATE_ARG_RET(pPEImage != NULL && ppAssembly != NULL); EX_TRY { ReleaseHolder<BINDER_SPACE::Assembly> pAsm; hr = AssemblyBinder::GetAssemblyFromImage(pPEImage, pNativePEImage, &pAsm); if(SUCCEEDED(hr)) { _ASSERTE(pAsm != nullptr); *ppAssembly = pAsm.Extract(); } } EX_CATCH_HRESULT(hr); return hr; }
//===================================================================================================================== CLRPrivBinderLoadFile * CLRPrivBinderLoadFile::GetOrCreateBinder() { STANDARD_VM_CONTRACT; HRESULT hr = S_OK; if (s_pSingleton == nullptr) { ReleaseHolder<CLRPrivBinderLoadFile> pBinder = SafeAddRef(new CLRPrivBinderLoadFile()); CLRPrivBinderAppX * pAppXBinder = CLRPrivBinderAppX::GetOrCreateBinder(); CLRPrivBinderFusion * pFusionBinder = pAppXBinder->GetFusionBinder(); pBinder->m_pFrameworkBinder = SafeAddRef(pFusionBinder); _ASSERTE(pBinder->m_pFrameworkBinder != nullptr); if (InterlockedCompareExchangeT<decltype(s_pSingleton)>(&s_pSingleton, pBinder, nullptr) == nullptr) pBinder.SuppressRelease(); } return s_pSingleton; }
/* static */ HRESULT CLRPrivBinderAssemblyLoadContext::SetupContext(DWORD dwAppDomainId, CLRPrivBinderCoreCLR *pTPABinder, UINT_PTR ptrAssemblyLoadContext, CLRPrivBinderAssemblyLoadContext **ppBindContext) { HRESULT hr = E_FAIL; EX_TRY { if(ppBindContext != NULL) { ReleaseHolder<CLRPrivBinderAssemblyLoadContext> pBinder; SAFE_NEW(pBinder, CLRPrivBinderAssemblyLoadContext); hr = pBinder->m_appContext.Init(); if(SUCCEEDED(hr)) { // Save the reference to the AppDomain in which the binder lives pBinder->m_appContext.SetAppDomainId(dwAppDomainId); // Mark that this binder can explicitly bind to native images pBinder->m_appContext.SetExplicitBindToNativeImages(true); // Save reference to the TPABinder that is required to be present. _ASSERTE(pTPABinder != NULL); pBinder->m_pTPABinder = pTPABinder; // Save the reference to the IntPtr for GCHandle for the managed // AssemblyLoadContext instance pBinder->m_ptrManagedAssemblyLoadContext = ptrAssemblyLoadContext; // Return reference to the allocated Binder instance *ppBindContext = clr::SafeAddRef(pBinder.Extract()); } } } EX_CATCH_HRESULT(hr); Exit: return hr; }
HRESULT CCoreCLRBinderHelper::BindToSystemSatellite(SString &systemPath, SString &sSimpleName, SString &sCultureName, ICLRPrivAssembly **ppSystemAssembly) { HRESULT hr = S_OK; VALIDATE_ARG_RET(ppSystemAssembly != NULL && !systemPath.IsEmpty()); EX_TRY { ReleaseHolder<BINDER_SPACE::Assembly> pAsm; hr = AssemblyBinder::BindToSystemSatellite(systemPath, sSimpleName, sCultureName, &pAsm); if(SUCCEEDED(hr)) { _ASSERTE(pAsm != NULL); *ppSystemAssembly = pAsm.Extract(); } } EX_CATCH_HRESULT(hr); return hr; }
HRESULT CLRPrivBinderAssemblyLoadContext::BindUsingPEImage( /* in */ PEImage *pPEImage, /* in */ BOOL fIsNativeImage, /* [retval][out] */ ICLRPrivAssembly **ppAssembly) { HRESULT hr = S_OK; EX_TRY { ReleaseHolder<BINDER_SPACE::Assembly> pCoreCLRFoundAssembly; ReleaseHolder<BINDER_SPACE::AssemblyName> pAssemblyName; ReleaseHolder<IMDInternalImport> pIMetaDataAssemblyImport; PEKIND PeKind = peNone; // Get the Metadata interface DWORD dwPAFlags[2]; IF_FAIL_GO(BinderAcquireImport(pPEImage, &pIMetaDataAssemblyImport, dwPAFlags, fIsNativeImage)); IF_FAIL_GO(AssemblyBinder::TranslatePEToArchitectureType(dwPAFlags, &PeKind)); _ASSERTE(pIMetaDataAssemblyImport != NULL); // Using the information we just got, initialize the assemblyname SAFE_NEW(pAssemblyName, AssemblyName); IF_FAIL_GO(pAssemblyName->Init(pIMetaDataAssemblyImport, PeKind)); // Validate architecture if (!BINDER_SPACE::Assembly::IsValidArchitecture(pAssemblyName->GetArchitecture())) { IF_FAIL_GO(HRESULT_FROM_WIN32(ERROR_BAD_FORMAT)); } // Disallow attempt to bind to the core library. Aside from that, // the LoadContext can load any assembly (even if it was in a different LoadContext like TPA). if (pAssemblyName->IsMscorlib()) { IF_FAIL_GO(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)); } hr = AssemblyBinder::BindUsingPEImage(&m_appContext, pAssemblyName, pPEImage, PeKind, pIMetaDataAssemblyImport, &pCoreCLRFoundAssembly); if (hr == S_OK) { _ASSERTE(pCoreCLRFoundAssembly != NULL); pCoreCLRFoundAssembly->SetBinder(this); *ppAssembly = pCoreCLRFoundAssembly.Extract(); } Exit:; } EX_CATCH_HRESULT(hr); return hr; }
HRESULT DacVirtualUnwind(DWORD threadId, PT_CONTEXT context, PT_KNONVOLATILE_CONTEXT_POINTERS contextPointers) { if (!g_dacImpl) { DacError(E_UNEXPECTED); UNREACHABLE(); } // The DAC code doesn't use these context pointers but zero them out to be safe. if (contextPointers != NULL) { memset(contextPointers, 0, sizeof(T_KNONVOLATILE_CONTEXT_POINTERS)); } HRESULT hr = S_OK; #ifdef FEATURE_DATATARGET4 ReleaseHolder<ICorDebugDataTarget4> dt; hr = g_dacImpl->m_pTarget->QueryInterface(IID_ICorDebugDataTarget4, (void **)&dt); if (SUCCEEDED(hr)) { hr = dt->VirtualUnwind(threadId, sizeof(CONTEXT), (BYTE*)context); } else #endif { SIZE_T baseAddress = DacGlobalBase(); if (baseAddress == 0 || !PAL_VirtualUnwindOutOfProc(context, contextPointers, baseAddress, DacReadAllAdapter)) { hr = E_FAIL; } } return hr; }
HRESULT CCoreCLRBinderHelper::BindToSystem(ICLRPrivAssembly **ppSystemAssembly, bool fBindToNativeImage) { HRESULT hr = S_OK; VALIDATE_ARG_RET(ppSystemAssembly != NULL); EX_TRY { ReleaseHolder<BINDER_SPACE::Assembly> pAsm; #ifdef FEATURE_CORECLR StackSString systemPath(SystemDomain::System()->SystemDirectory()); hr = AssemblyBinder::BindToSystem(systemPath, &pAsm, fBindToNativeImage); #else AssemblySpec::BindToSystem(&pAsm); #endif if(SUCCEEDED(hr)) { _ASSERTE(pAsm != NULL); *ppSystemAssembly = pAsm.Extract(); } } EX_CATCH_HRESULT(hr); return hr; }
int coreclr_initialize( const char* exePath, const char* appDomainFriendlyName, int propertyCount, const char** propertyKeys, const char** propertyValues, void** hostHandle, unsigned int* domainId) { HRESULT hr; #ifdef FEATURE_PAL DWORD error = PAL_InitializeCoreCLR(exePath); hr = HRESULT_FROM_WIN32(error); // If PAL initialization failed, then we should return right away and avoid // calling any other APIs because they can end up calling into the PAL layer again. if (FAILED(hr)) { return hr; } #endif ReleaseHolder<ICLRRuntimeHost2> host; hr = CorHost2::CreateObject(IID_ICLRRuntimeHost2, (void**)&host); IfFailRet(hr); ConstWStringHolder appDomainFriendlyNameW = StringToUnicode(appDomainFriendlyName); STARTUP_FLAGS startupFlags; LPCWSTR* propertyKeysWTemp; LPCWSTR* propertyValuesWTemp; ExtractStartupFlagsAndConvertToUnicode( propertyKeys, propertyValues, &propertyCount, &startupFlags, &propertyKeysWTemp, &propertyValuesWTemp); ConstWStringArrayHolder propertyKeysW; propertyKeysW.Set(propertyKeysWTemp, propertyCount); ConstWStringArrayHolder propertyValuesW; propertyValuesW.Set(propertyValuesWTemp, propertyCount); hr = host->SetStartupFlags(startupFlags); IfFailRet(hr); hr = host->Start(); IfFailRet(hr); hr = host->CreateAppDomainWithManager( appDomainFriendlyNameW, // Flags: // APPDOMAIN_ENABLE_PLATFORM_SPECIFIC_APPS // - By default CoreCLR only allows platform neutral assembly to be run. To allow // assemblies marked as platform specific, include this flag // // APPDOMAIN_ENABLE_PINVOKE_AND_CLASSIC_COMINTEROP // - Allows sandboxed applications to make P/Invoke calls and use COM interop // // APPDOMAIN_SECURITY_SANDBOXED // - Enables sandboxing. If not set, the app is considered full trust // // APPDOMAIN_IGNORE_UNHANDLED_EXCEPTION // - Prevents the application from being torn down if a managed exception is unhandled // APPDOMAIN_ENABLE_PLATFORM_SPECIFIC_APPS | APPDOMAIN_ENABLE_PINVOKE_AND_CLASSIC_COMINTEROP | APPDOMAIN_DISABLE_TRANSPARENCY_ENFORCEMENT, NULL, // Name of the assembly that contains the AppDomainManager implementation NULL, // The AppDomainManager implementation type name propertyCount, propertyKeysW, propertyValuesW, (DWORD *)domainId); if (SUCCEEDED(hr)) { host.SuppressRelease(); *hostHandle = host; } return hr; }
HRESULT CLRPrivBinderAssemblyLoadContext::BindAssemblyByName(IAssemblyName *pIAssemblyName, ICLRPrivAssembly **ppAssembly) { HRESULT hr = S_OK; VALIDATE_ARG_RET(pIAssemblyName != nullptr && ppAssembly != nullptr); // DevDiv #933506: Exceptions thrown during AssemblyLoadContext.Load should propagate // EX_TRY { _ASSERTE(m_pTPABinder != NULL); ReleaseHolder<BINDER_SPACE::Assembly> pCoreCLRFoundAssembly; ReleaseHolder<AssemblyName> pAssemblyName; SAFE_NEW(pAssemblyName, AssemblyName); IF_FAIL_GO(pAssemblyName->Init(pIAssemblyName)); // When LoadContext needs to resolve an assembly reference, it will go through the following lookup order: // // 1) Lookup the assembly within the LoadContext itself. If assembly is found, use it. // 2) Invoke the LoadContext's Load method implementation. If assembly is found, use it. // 3) Lookup the assembly within TPABinder. If assembly is found, use it. // 4) Invoke the LoadContext's Resolving event. If assembly is found, use it. // 5) Raise exception. // // This approach enables a LoadContext to override assemblies that have been loaded in TPA context by loading // a different (or even the same!) version. { // Step 1 - Try to find the assembly within the LoadContext. hr = BindAssemblyByNameWorker(pAssemblyName, &pCoreCLRFoundAssembly); if ((hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) || (hr == FUSION_E_APP_DOMAIN_LOCKED) || (hr == FUSION_E_REF_DEF_MISMATCH)) { // If we are here, one of the following is possible: // // 1) The assembly has not been found in the current binder's application context (i.e. it has not already been loaded), OR // 2) An assembly with the same simple name was already loaded in the context of the current binder but we ran into a Ref/Def // mismatch (either due to version difference or strong-name difference). // // Thus, if default binder has been overridden, then invoke it in an attempt to perform the binding for it make the call // of what to do next. The host-overridden binder can either fail the bind or return reference to an existing assembly // that has been loaded. // hr = AssemblyBinder::BindUsingHostAssemblyResolver(GetManagedAssemblyLoadContext(), pAssemblyName, pIAssemblyName, m_pTPABinder, &pCoreCLRFoundAssembly); if (SUCCEEDED(hr)) { // We maybe returned an assembly that was bound to a different AssemblyLoadContext instance. // In such a case, we will not overwrite the binding context (which would be wrong since it would not // be present in the cache of the current binding context). if (pCoreCLRFoundAssembly->GetBinder() == NULL) { pCoreCLRFoundAssembly->SetBinder(this); } } } } IF_FAIL_GO(hr); // Extract the assembly reference. // // For TPA assemblies that were bound, TPABinder // would have already set the binder reference for the assembly, so we just need to // extract the reference now. *ppAssembly = pCoreCLRFoundAssembly.Extract(); Exit:; } // EX_CATCH_HRESULT(hr); return hr; }
//===================================================================================================================== HRESULT CLRPrivBinderAppX::BindAppXAssemblyByNameWorker( IAssemblyName * pIAssemblyName, DWORD dwAppXBindFlags, CLRPrivAssemblyAppX ** ppAssembly) { STANDARD_VM_CONTRACT; HRESULT hr = S_OK; fusion::logging::StatusScope logStatus(0, ID_FUSLOG_BINDING_STATUS_IMMERSIVE, &hr); VALIDATE_ARG_RET(pIAssemblyName != nullptr); VALIDATE_ARG_RET((dwAppXBindFlags & ABF_BindIL) == ABF_BindIL); VALIDATE_ARG_RET(ppAssembly != nullptr); DWORD dwContentType = AssemblyContentType_Default; IfFailRet(hr = fusion::util::GetProperty(pIAssemblyName, ASM_NAME_CONTENT_TYPE, &dwContentType)); if ((hr == S_OK) && (dwContentType != AssemblyContentType_Default)) { IfFailRet(CLR_E_BIND_UNRECOGNIZED_IDENTITY_FORMAT); } ReleaseHolder<CLRPrivAssemblyAppX> pAssembly; // Get the simple name. WCHAR wzSimpleName[_MAX_PATH]; DWORD cchSimpleName = _MAX_PATH; IfFailRet(pIAssemblyName->GetName(&cchSimpleName, wzSimpleName)); { // Look for previous successful bind. Host callouts are now forbidden. ForbidSuspendThreadCrstHolder lock(&m_MapReadLock); pAssembly = clr::SafeAddRef(m_NameToAssemblyMap.Lookup(wzSimpleName)); } if (pAssembly == nullptr) { ReleaseHolder<ICLRPrivResource> pResourceIL; ReleaseHolder<ICLRPrivResource> pResourceNI; // Create assembly identity using the simple name. For successful binds this will be updated // with the full assembly identity in the VerifyBind callback. NewHolder<AssemblyIdentity> pIdentity = new AssemblyIdentity(); IfFailRet(pIdentity->Initialize(wzSimpleName)); // // Check the head package first to see if this matches an EXE, then check // all packages to see if this matches a DLL. // WCHAR wzFilePath[_MAX_PATH]; { hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); if (FAILED(hr)) { // Create simple name with .EXE extension WCHAR wzSimpleFileName[_MAX_PATH]; wcscpy_s(wzSimpleFileName, NumItems(wzSimpleFileName), wzSimpleName); wcscat_s(wzSimpleFileName, NumItems(wzSimpleFileName), W(".EXE")); // Search for the file using AppX::FileFileInCurrentPackage helper. UINT32 cchFilePath = NumItems(wzFilePath); hr = AppX::FindFileInCurrentPackage( wzSimpleFileName, &cchFilePath, wzFilePath, PACKAGE_FILTER_CLR_DEFAULT, (PCWSTR *)(void *)m_rgAltPaths, m_cAltPaths, m_pParentBinder != NULL ? AppX::FindFindInPackageFlags_SkipCurrentPackageGraph : AppX::FindFindInPackageFlags_None); } if (FAILED(hr)) { // Create simple name with .DLL extension WCHAR wzSimpleFileName[_MAX_PATH]; wcscpy_s(wzSimpleFileName, NumItems(wzSimpleFileName), wzSimpleName); wcscat_s(wzSimpleFileName, NumItems(wzSimpleFileName), W(".DLL")); // Search for the file using AppX::FileFileInCurrentPackage helper UINT32 cchFilePath = NumItems(wzFilePath); hr = AppX::FindFileInCurrentPackage( wzSimpleFileName, &cchFilePath, wzFilePath, PACKAGE_FILTER_CLR_DEFAULT, (PCWSTR *)(void *)m_rgAltPaths, m_cAltPaths, m_pParentBinder != NULL ? AppX::FindFindInPackageFlags_SkipCurrentPackageGraph : AppX::FindFindInPackageFlags_None); } if (SUCCEEDED(hr)) { fusion::logging::LogMessage(0, ID_FUSLOG_BINDING_STATUS_FOUND, wzFilePath); } else { // Cache the bind failure result before returning. Careful not to overwrite the bind result with the cache insertion result. HRESULT hrResult = hr; IfFailRet(CacheBindResult(pIdentity, hr)); if (hr == S_OK) { // Cache now owns identity object lifetime. pIdentity.SuppressRelease(); } hr = hrResult; } IfFailRet(hr); } NewHolder<CLRPrivResourcePathImpl> pResourcePath = new CLRPrivResourcePathImpl(wzFilePath); IfFailRet(pResourcePath->QueryInterface(__uuidof(ICLRPrivResource), (LPVOID*)&pResourceIL)); pResourcePath.SuppressRelease(); // Create an IBindResult and provide it to the new CLRPrivAssemblyAppX object. ReleaseHolder<IBindResult> pIBindResult = ToInterface<IBindResult>( new CLRPrivAssemblyBindResultWrapper(pIAssemblyName, wzFilePath, m_pFingerprintFactory)); // Create the new CLRPrivAssemblyAppX object. NewHolder<CLRPrivAssemblyAppX> pAssemblyObj = new CLRPrivAssemblyAppX(pIdentity, this, pResourceIL, pIBindResult); // // Check cache. If someone beat us then use it instead; otherwise add new ICLRPrivAssembly. // do { // Because the read lock must be taken within a ForbidSuspend region, use AddInPhases. if (m_NameToAssemblyMap.CheckAddInPhases<ForbidSuspendThreadCrstHolder, CrstHolder>( pAssemblyObj, m_MapReadLock, m_MapWriteLock, pAssemblyObj.GetValue())) { { // Careful not to allow the cache insertion result to overwrite the bind result. HRESULT hrResult = hr; IfFailRet(CacheBindResult(pIdentity, hr)); if (hr == S_OK) { // Cache now owns identity object lifetime, but ~CLRPrivBinderAssembly // can also remove the identity from the cache prior to cache deletion. pIdentity.SuppressRelease(); } hr = hrResult; } pAssembly = pAssemblyObj.Extract(); } else { ForbidSuspendThreadCrstHolder lock(&m_MapReadLock); pAssembly = clr::SafeAddRef(m_NameToAssemblyMap.Lookup(wzSimpleName)); } } while (pAssembly == nullptr); // Keep looping until we find the existing one, or add a new one } _ASSERTE(pAssembly != nullptr); if (((dwAppXBindFlags & ABF_BindNI) == ABF_BindNI) && m_fCanUseNativeImages) { // // Look to see if there's a native image available. // // Fire BindingNgenPhaseStart ETW event if enabled. { InlineSString<128> ssAssemblyName; FireEtwBindingNgenPhaseStart( (AppDomain::GetCurrentDomain()->GetId().m_dwId), LOADCTX_TYPE_HOSTED, ETWFieldUnused, ETWLoaderLoadTypeNotAvailable, NULL, FusionBind::GetAssemblyNameDisplayName(pIAssemblyName, ssAssemblyName, ASM_DISPLAYF_FULL).GetUnicode(), GetClrInstanceId()); } ReleaseHolder<IBindResult> pIBindResultIL; IfFailRet(pAssembly->GetIBindResult(&pIBindResultIL)); _ASSERTE(pIBindResultIL != nullptr); NewArrayHolder<WCHAR> wzZapSet = DuplicateStringThrowing(g_pConfig->ZapSet()); NativeConfigData cfgData = { wzZapSet, PEFile::GetNativeImageConfigFlags() }; IfFailRet(BindToNativeAssembly( pIBindResultIL, &cfgData, static_cast<IBindContext*>(this), fusion::logging::GetCurrentFusionBindLog())); // Ensure that the native image found above in BindToNativeAssembly is reported as existing in the CLRPrivAssembly object if (hr == S_OK) { ReleaseHolder<ICLRPrivResource> pNIImageResource; // This will make GetAvailableImageTypes return that a native image exists. IfFailRet(pAssembly->GetImageResource(ASSEMBLY_IMAGE_TYPE_NATIVE, NULL, &pNIImageResource)); #ifdef _DEBUG DWORD dwImageTypes; _ASSERTE(SUCCEEDED(pAssembly->GetAvailableImageTypes(&dwImageTypes))); _ASSERTE((dwImageTypes & ASSEMBLY_IMAGE_TYPE_NATIVE) == ASSEMBLY_IMAGE_TYPE_NATIVE); #endif } // Fire BindingNgenPhaseEnd ETW event if enabled. { InlineSString<128> ssAssemblyName; FireEtwBindingNgenPhaseEnd( (AppDomain::GetCurrentDomain()->GetId().m_dwId), LOADCTX_TYPE_HOSTED, ETWFieldUnused, ETWLoaderLoadTypeNotAvailable, NULL, FusionBind::GetAssemblyNameDisplayName(pIAssemblyName, ssAssemblyName, ASM_DISPLAYF_FULL).GetUnicode(), GetClrInstanceId()); } // BindToNativeAssembly can return S_FALSE, but this could be misleading. if (hr == S_FALSE) hr = S_OK; } if (SUCCEEDED(hr)) { *ppAssembly = pAssembly.Extract(); } return hr; }
HRESULT CLRPrivBinderAssemblyLoadContext::BindAssemblyByName(IAssemblyName *pIAssemblyName, ICLRPrivAssembly **ppAssembly) { HRESULT hr = S_OK; VALIDATE_ARG_RET(pIAssemblyName != nullptr && ppAssembly != nullptr); // DevDiv #933506: Exceptions thrown during AssemblyLoadContext.Load should propagate // EX_TRY { _ASSERTE(m_pTPABinder != NULL); ReleaseHolder<BINDER_SPACE::Assembly> pCoreCLRFoundAssembly; ReleaseHolder<AssemblyName> pAssemblyName; SAFE_NEW(pAssemblyName, AssemblyName); IF_FAIL_GO(pAssemblyName->Init(pIAssemblyName)); // Check if the assembly is in the TPA list or not. Don't search app paths when using the TPA binder because the actual // binder is using a host assembly resolver. hr = m_pTPABinder->BindAssemblyByNameWorker(pAssemblyName, &pCoreCLRFoundAssembly, true /* excludeAppPaths */); if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) { // If we could not find the assembly in the TPA list, // then bind to it in the context of the current binder. // If we find it already loaded, we will return the reference. hr = BindAssemblyByNameWorker(pAssemblyName, &pCoreCLRFoundAssembly); if ((hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) || (hr == FUSION_E_APP_DOMAIN_LOCKED) || (hr == FUSION_E_REF_DEF_MISMATCH)) { // If we are here, one of the following is possible: // // 1) The assembly has not been found in the current binder's application context (i.e. it has not already been loaded), OR // 2) An assembly with the same simple name was already loaded in the context of the current binder but we ran into a Ref/Def // mismatch (either due to version difference or strong-name difference). // // Thus, if default binder has been overridden, then invoke it in an attempt to perform the binding for it make the call // of what to do next. The host-overridden binder can either fail the bind or return reference to an existing assembly // that has been loaded. hr = AssemblyBinder::BindUsingHostAssemblyResolver(GetManagedAssemblyLoadContext(), pAssemblyName, pIAssemblyName, &pCoreCLRFoundAssembly); if (SUCCEEDED(hr)) { // We maybe returned an assembly that was bound to a different AssemblyLoadContext instance. // In such a case, we will not overwrite the binding context (which would be wrong since it would not // be present in the cache of the current binding context). if (pCoreCLRFoundAssembly->GetBinder() == NULL) { pCoreCLRFoundAssembly->SetBinder(this); } } } } IF_FAIL_GO(hr); // Extract the assembly reference. // // For TPA assemblies that were bound, TPABinder // would have already set the binder reference for the assembly, so we just need to // extract the reference now. *ppAssembly = pCoreCLRFoundAssembly.Extract(); Exit: ; } // EX_CATCH_HRESULT(hr); return hr; }
HRESULT CLRPrivBinderAssemblyLoadContext::BindUsingPEImage( /* in */ PEImage *pPEImage, /* in */ BOOL fIsNativeImage, /* [retval][out] */ ICLRPrivAssembly **ppAssembly) { HRESULT hr = S_OK; EX_TRY { ReleaseHolder<BINDER_SPACE::Assembly> pCoreCLRFoundAssembly; ReleaseHolder<BINDER_SPACE::AssemblyName> pAssemblyName; ReleaseHolder<IMDInternalImport> pIMetaDataAssemblyImport; PEKIND PeKind = peNone; // Get the Metadata interface DWORD dwPAFlags[2]; IF_FAIL_GO(BinderAcquireImport(pPEImage, &pIMetaDataAssemblyImport, dwPAFlags, fIsNativeImage)); IF_FAIL_GO(AssemblyBinder::TranslatePEToArchitectureType(dwPAFlags, &PeKind)); _ASSERTE(pIMetaDataAssemblyImport != NULL); // Using the information we just got, initialize the assemblyname SAFE_NEW(pAssemblyName, AssemblyName); IF_FAIL_GO(pAssemblyName->Init(pIMetaDataAssemblyImport, PeKind)); // Validate architecture if (!BINDER_SPACE::Assembly::IsValidArchitecture(pAssemblyName->GetArchitecture())) { IF_FAIL_GO(HRESULT_FROM_WIN32(ERROR_BAD_FORMAT)); } // Ensure we are not being asked to bind to a TPA assembly // // Easy out for mscorlib if (pAssemblyName->IsMscorlib()) { IF_FAIL_GO(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)); } { SString& simpleName = pAssemblyName->GetSimpleName(); ApplicationContext *pTPAApplicationContext = m_pTPABinder->GetAppContext(); SimpleNameToFileNameMap * tpaMap = pTPAApplicationContext->GetTpaList(); if (tpaMap->LookupPtr(simpleName.GetUnicode()) != NULL) { // The simple name of the assembly being requested to be bound was found in the TPA list. // Now, perform the actual bind to see if the assembly was really in the TPA assembly or not. // Don't search app paths when using the TPA binder because the actual binder is using a host assembly resolver. hr = m_pTPABinder->BindAssemblyByNameWorker(pAssemblyName, &pCoreCLRFoundAssembly, true /* excludeAppPaths */); if (SUCCEEDED(hr)) { if (pCoreCLRFoundAssembly->GetIsInGAC()) { // If we were able to bind to a TPA assembly, then fail the load IF_FAIL_GO(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)); } } } hr = AssemblyBinder::BindUsingPEImage(&m_appContext, pAssemblyName, pPEImage, PeKind, pIMetaDataAssemblyImport, &pCoreCLRFoundAssembly); if (hr == S_OK) { _ASSERTE(pCoreCLRFoundAssembly != NULL); pCoreCLRFoundAssembly->SetBinder(this); *ppAssembly = pCoreCLRFoundAssembly.Extract(); } } Exit: ; } EX_CATCH_HRESULT(hr); return hr; }
HRESULT ExecuteAssembly( LPCSTR exePath, LPCSTR coreClrPath, LPCSTR appDomainFriendlyName, int propertyCount, LPCSTR* propertyKeys, LPCSTR* propertyValues, int argc, LPCSTR* argv, LPCSTR managedAssemblyPath, LPCSTR entryPointAssemblyName, LPCSTR entryPointTypeName, LPCSTR entryPointMethodName, DWORD* exitCode) { if (exitCode == NULL) { return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER); } *exitCode = -1; DWORD error = PAL_InitializeCoreCLR(exePath, coreClrPath, true); HRESULT hr = HRESULT_FROM_WIN32(error); // If PAL initialization failed, then we should return right away and avoid // calling any other APIs because they can end up calling into the PAL layer again. if (FAILED(hr)) { return hr; } ReleaseHolder<ICLRRuntimeHost2> host; hr = CorHost2::CreateObject(IID_ICLRRuntimeHost2, (void**)&host); IfFailRet(hr); hr = host->SetStartupFlags((STARTUP_FLAGS) (STARTUP_FLAGS::STARTUP_LOADER_OPTIMIZATION_SINGLE_DOMAIN | STARTUP_FLAGS::STARTUP_SINGLE_APPDOMAIN)); IfFailRet(hr); hr = host->Start(); IfFailRet(hr); ConstWStringHolder appDomainFriendlyNameW = StringToUnicode(appDomainFriendlyName); ConstWStringArrayHolder propertyKeysW; propertyKeysW.Set(StringArrayToUnicode(propertyCount, propertyKeys), propertyCount); ConstWStringArrayHolder propertyValuesW; propertyValuesW.Set(StringArrayToUnicode(propertyCount, propertyValues), propertyCount); DWORD domainId; hr = host->CreateAppDomainWithManager( appDomainFriendlyNameW, // Flags: // APPDOMAIN_ENABLE_PLATFORM_SPECIFIC_APPS // - By default CoreCLR only allows platform neutral assembly to be run. To allow // assemblies marked as platform specific, include this flag // // APPDOMAIN_ENABLE_PINVOKE_AND_CLASSIC_COMINTEROP // - Allows sandboxed applications to make P/Invoke calls and use COM interop // // APPDOMAIN_SECURITY_SANDBOXED // - Enables sandboxing. If not set, the app is considered full trust // // APPDOMAIN_IGNORE_UNHANDLED_EXCEPTION // - Prevents the application from being torn down if a managed exception is unhandled // APPDOMAIN_ENABLE_PLATFORM_SPECIFIC_APPS | APPDOMAIN_ENABLE_PINVOKE_AND_CLASSIC_COMINTEROP | APPDOMAIN_DISABLE_TRANSPARENCY_ENFORCEMENT, NULL, // Name of the assembly that contains the AppDomainManager implementation NULL, // The AppDomainManager implementation type name propertyCount, propertyKeysW, propertyValuesW, &domainId); IfFailRet(hr); ConstWStringArrayHolder argvW; argvW.Set(StringArrayToUnicode(argc, argv), argc); if (entryPointAssemblyName == NULL || entryPointTypeName == NULL || entryPointMethodName == NULL) { ConstWStringHolder managedAssemblyPathW = StringToUnicode(managedAssemblyPath); hr = host->ExecuteAssembly(domainId, managedAssemblyPathW, argc, argvW, exitCode); IfFailRet(hr); } else { ConstWStringHolder entryPointAssemblyNameW = StringToUnicode(entryPointAssemblyName); ConstWStringHolder entryPointTypeNameW = StringToUnicode(entryPointTypeName); ConstWStringHolder entryPointMethodNameW = StringToUnicode(entryPointMethodName); HostMain pHostMain; hr = host->CreateDelegate( domainId, entryPointAssemblyNameW, entryPointTypeNameW, entryPointMethodNameW, (INT_PTR*)&pHostMain); IfFailRet(hr); *exitCode = pHostMain(argc, argvW); } hr = host->UnloadAppDomain(domainId, true); // Wait until done IfFailRet(hr); hr = host->Stop(); // The PAL_Terminate is not called here since it would terminate the current process. return hr; }
HRESULT ExecuteAssembly( LPCSTR exePath, LPCSTR coreClrPath, LPCSTR appDomainFriendlyName, int propertyCount, LPCSTR* propertyKeys, LPCSTR* propertyValues, int argc, LPCSTR* argv, LPCSTR managedAssemblyPath, LPCSTR entryPointAssemblyName, LPCSTR entryPointTypeName, LPCSTR entryPointMethodName, DWORD* exitCode) { if (exitCode == NULL) { return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER); } *exitCode = -1; ReleaseHolder<ICLRRuntimeHost2> host; //(reinterpret_cast<ICLRRuntimeHost2*>(hostHandle)); DWORD domainId; HRESULT hr = coreclr_initialize(exePath, appDomainFriendlyName, propertyCount, propertyKeys, propertyValues, &host, &domainId); IfFailRet(hr); ConstWStringArrayHolder argvW; argvW.Set(StringArrayToUnicode(argc, argv), argc); if (entryPointAssemblyName == NULL || entryPointTypeName == NULL || entryPointMethodName == NULL) { ConstWStringHolder managedAssemblyPathW = StringToUnicode(managedAssemblyPath); hr = host->ExecuteAssembly(domainId, managedAssemblyPathW, argc, argvW, exitCode); IfFailRet(hr); } else { ConstWStringHolder entryPointAssemblyNameW = StringToUnicode(entryPointAssemblyName); ConstWStringHolder entryPointTypeNameW = StringToUnicode(entryPointTypeName); ConstWStringHolder entryPointMethodNameW = StringToUnicode(entryPointMethodName); HostMain pHostMain; hr = host->CreateDelegate( domainId, entryPointAssemblyNameW, entryPointTypeNameW, entryPointMethodNameW, (INT_PTR*)&pHostMain); IfFailRet(hr); *exitCode = pHostMain(argc, argvW); } hr = coreclr_shutdown(host, domainId); return hr; }
/* static */ HRESULT Compatibility::Retarget(AssemblyName *pAssemblyName, AssemblyName **ppRetargetedAssemblyName, BOOL *pfIsRetargeted) { HRESULT hr = S_OK; BINDER_LOG_ENTER(W("Compatibility::Retarget")); IF_FALSE_GO(pAssemblyName != NULL); IF_FALSE_GO(ppRetargetedAssemblyName != NULL); BINDER_LOG_ASSEMBLY_NAME(W("source"), pAssemblyName); if (pfIsRetargeted) { *pfIsRetargeted = FALSE; } #ifdef FEATURE_CORESYSTEM // Apply retargeting only for strong-named culture neutral assemblies if (pAssemblyName->IsStronglyNamed() && pAssemblyName->GetDeNormalizedCulture().IsEmpty()) { ReleaseHolder<AssemblyName> pRetargetedAssemblyName; SString &simpleName = pAssemblyName->GetSimpleName(); AssemblyVersion *pAssemblyVersion = pAssemblyName->GetVersion(); SString publicKeyToken; TextualIdentityParser::BlobToHex(pAssemblyName->GetPublicKeyTokenBLOB(), publicKeyToken); // Perform linear search for matching assembly. Legacy Fusion also does that for (unsigned int i = 0; i < LENGTH_OF(arRetargetConfig); i++) { #ifdef FEATURE_LEGACYNETCF if (!RuntimeIsLegacyNetCF(0) && arRetargetConfig[i].fMangoOnly == TRUE) continue; #endif if (IsMatchingString(simpleName, arRetargetConfig[i].pwzSimpleName) && IsMatchingVersion(pAssemblyVersion, arRetargetConfig[i].pwzVersion) && IsMatchingString(publicKeyToken, arRetargetConfig[i].pwzPublicKeyToken)) { AssemblyVersion newAssemblyVersion; IF_FALSE_GO(newAssemblyVersion.SetVersion(arRetargetConfig[i].pwzNewVersion)); SAFE_NEW(pRetargetedAssemblyName, AssemblyName); if (arRetargetConfig[i].pwzNewSimpleName != NULL) { pRetargetedAssemblyName-> GetSimpleName().Set(arRetargetConfig[i].pwzNewSimpleName); } else { pRetargetedAssemblyName->GetSimpleName().Set(simpleName); } pRetargetedAssemblyName->SetVersion(&newAssemblyVersion); SBuffer newPublicKeyTokenBlob; SmallStackSString newPublicKeyToken(arRetargetConfig[i].pwzNewPublicKeyToken); TextualIdentityParser::HexToBlob(newPublicKeyToken, FALSE /* fValidateHex */, TRUE /* fIsToken */, newPublicKeyTokenBlob); pRetargetedAssemblyName->GetPublicKeyTokenBLOB().Set(newPublicKeyTokenBlob); BINDER_LOG_ASSEMBLY_NAME(W("retargeted"), pRetargetedAssemblyName); *ppRetargetedAssemblyName = pRetargetedAssemblyName.Extract(); if (pfIsRetargeted) { *pfIsRetargeted = TRUE; } GO_WITH_HRESULT(S_OK); } } // Create a clone without retargetable flag if (pAssemblyName->GetIsRetargetable()) { IF_FAIL_GO(pAssemblyName->Clone(&pRetargetedAssemblyName)); pRetargetedAssemblyName->SetIsRetargetable(FALSE); *ppRetargetedAssemblyName = pRetargetedAssemblyName.Extract(); } else { pAssemblyName->AddRef(); *ppRetargetedAssemblyName = pAssemblyName; } } else #endif // FEATURE_CORESYSTEM { pAssemblyName->AddRef(); *ppRetargetedAssemblyName = pAssemblyName; } Exit: BINDER_LOG_LEAVE_HR(W("Compatibility::Retarget"), hr); return hr; }
// ============================================================================ // CLRPrivBinderCoreCLR implementation // ============================================================================ HRESULT CLRPrivBinderCoreCLR::BindAssemblyByName(IAssemblyName *pIAssemblyName, ICLRPrivAssembly **ppAssembly) { HRESULT hr = S_OK; VALIDATE_ARG_RET(pIAssemblyName != nullptr && ppAssembly != nullptr); EX_TRY { *ppAssembly = nullptr; ReleaseHolder<BINDER_SPACE::Assembly> pCoreCLRFoundAssembly; ReleaseHolder<AssemblyName> pAssemblyName; SAFE_NEW(pAssemblyName, AssemblyName); IF_FAIL_GO(pAssemblyName->Init(pIAssemblyName)); hr = BindAssemblyByNameWorker(pAssemblyName, &pCoreCLRFoundAssembly, false /* excludeAppPaths */); #if defined(FEATURE_HOST_ASSEMBLY_RESOLVER) && !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE) if ((hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) || (hr == FUSION_E_APP_DOMAIN_LOCKED) || (hr == FUSION_E_REF_DEF_MISMATCH)) { // If we are here, one of the following is possible: // // 1) The assembly has not been found in the current binder's application context (i.e. it has not already been loaded), OR // 2) An assembly with the same simple name was already loaded in the context of the current binder but we ran into a Ref/Def // mismatch (either due to version difference or strong-name difference). // // Thus, if default binder has been overridden, then invoke it in an attempt to perform the binding for it make the call // of what to do next. The host-overridden binder can either fail the bind or return reference to an existing assembly // that has been loaded. // Attempt to resolve the assembly via managed TPA ALC instance if one exists INT_PTR pManagedAssemblyLoadContext = GetManagedAssemblyLoadContext(); if (pManagedAssemblyLoadContext != NULL) { hr = AssemblyBinder::BindUsingHostAssemblyResolver(pManagedAssemblyLoadContext, pAssemblyName, pIAssemblyName, NULL, &pCoreCLRFoundAssembly); if (SUCCEEDED(hr)) { // We maybe returned an assembly that was bound to a different AssemblyLoadContext instance. // In such a case, we will not overwrite the binding context (which would be wrong since it would not // be present in the cache of the current binding context). if (pCoreCLRFoundAssembly->GetBinder() == NULL) { pCoreCLRFoundAssembly->SetBinder(this); } } } } #endif // defined(FEATURE_HOST_ASSEMBLY_RESOLVER) && !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE) IF_FAIL_GO(hr); *ppAssembly = pCoreCLRFoundAssembly.Extract(); Exit:; } EX_CATCH_HRESULT(hr); return hr; }