diff options
Diffstat (limited to 'src/binder/clrprivbinderassemblyloadcontext.cpp')
-rw-r--r-- | src/binder/clrprivbinderassemblyloadcontext.cpp | 58 |
1 files changed, 37 insertions, 21 deletions
diff --git a/src/binder/clrprivbinderassemblyloadcontext.cpp b/src/binder/clrprivbinderassemblyloadcontext.cpp index 8f3a3eef49..57f4ee72c4 100644 --- a/src/binder/clrprivbinderassemblyloadcontext.cpp +++ b/src/binder/clrprivbinderassemblyloadcontext.cpp @@ -61,19 +61,14 @@ HRESULT CLRPrivBinderAssemblyLoadContext::BindAssemblyByName(IAssemblyName * 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. - + // 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)) { - // Step 1 - Try to find the assembly within the LoadContext. + // 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)) @@ -87,8 +82,7 @@ HRESULT CLRPrivBinderAssemblyLoadContext::BindAssemblyByName(IAssemblyName * // 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); + hr = AssemblyBinder::BindUsingHostAssemblyResolver(GetManagedAssemblyLoadContext(), pAssemblyName, pIAssemblyName, &pCoreCLRFoundAssembly); if (SUCCEEDED(hr)) { // We maybe returned an assembly that was bound to a different AssemblyLoadContext instance. @@ -148,19 +142,41 @@ HRESULT CLRPrivBinderAssemblyLoadContext::BindUsingPEImage( /* in */ PEImage *pP 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). + // 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)); } - hr = AssemblyBinder::BindUsingPEImage(&m_appContext, pAssemblyName, pPEImage, PeKind, pIMetaDataAssemblyImport, &pCoreCLRFoundAssembly); - if (hr == S_OK) { - _ASSERTE(pCoreCLRFoundAssembly != NULL); - pCoreCLRFoundAssembly->SetBinder(this); - *ppAssembly = pCoreCLRFoundAssembly.Extract(); + 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:; } |