1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
6 #include "assemblybinder.hpp"
7 #include "clrprivbindercoreclr.h"
8 #include "clrprivbinderutil.h"
10 using namespace BINDER_SPACE;
12 //=============================================================================
14 //-----------------------------------------------------------------------------
16 HRESULT CLRPrivBinderCoreCLR::BindAssemblyByNameWorker(BINDER_SPACE::AssemblyName *pAssemblyName,
17 BINDER_SPACE::Assembly **ppCoreCLRFoundAssembly,
20 VALIDATE_ARG_RET(pAssemblyName != nullptr && ppCoreCLRFoundAssembly != nullptr);
24 // MSCORLIB should be bound using BindToSystem
25 _ASSERTE(!pAssemblyName->IsMscorlib());
28 hr = AssemblyBinder::BindAssembly(&m_appContext,
32 FALSE, //fNgenExplicitBind,
33 FALSE, //fExplicitBindToNativeImage,
35 ppCoreCLRFoundAssembly);
38 (*ppCoreCLRFoundAssembly)->SetBinder(this);
44 // ============================================================================
45 // CLRPrivBinderCoreCLR implementation
46 // ============================================================================
47 HRESULT CLRPrivBinderCoreCLR::BindAssemblyByName(IAssemblyName *pIAssemblyName,
48 ICLRPrivAssembly **ppAssembly)
51 VALIDATE_ARG_RET(pIAssemblyName != nullptr && ppAssembly != nullptr);
55 *ppAssembly = nullptr;
57 ReleaseHolder<BINDER_SPACE::Assembly> pCoreCLRFoundAssembly;
58 ReleaseHolder<AssemblyName> pAssemblyName;
60 SAFE_NEW(pAssemblyName, AssemblyName);
61 IF_FAIL_GO(pAssemblyName->Init(pIAssemblyName));
63 hr = BindAssemblyByNameWorker(pAssemblyName, &pCoreCLRFoundAssembly, false /* excludeAppPaths */);
65 #if !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE)
66 if ((hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) ||
67 (hr == FUSION_E_APP_DOMAIN_LOCKED) || (hr == FUSION_E_REF_DEF_MISMATCH))
69 // If we are here, one of the following is possible:
71 // 1) The assembly has not been found in the current binder's application context (i.e. it has not already been loaded), OR
72 // 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
73 // mismatch (either due to version difference or strong-name difference).
75 // Thus, if default binder has been overridden, then invoke it in an attempt to perform the binding for it make the call
76 // of what to do next. The host-overridden binder can either fail the bind or return reference to an existing assembly
77 // that has been loaded.
79 // Attempt to resolve the assembly via managed TPA ALC instance if one exists
80 INT_PTR pManagedAssemblyLoadContext = GetManagedAssemblyLoadContext();
81 if (pManagedAssemblyLoadContext != NULL)
83 hr = AssemblyBinder::BindUsingHostAssemblyResolver(pManagedAssemblyLoadContext, pAssemblyName, pIAssemblyName,
84 NULL, &pCoreCLRFoundAssembly);
87 // We maybe returned an assembly that was bound to a different AssemblyLoadContext instance.
88 // In such a case, we will not overwrite the binding context (which would be wrong since it would not
89 // be present in the cache of the current binding context).
90 if (pCoreCLRFoundAssembly->GetBinder() == NULL)
92 pCoreCLRFoundAssembly->SetBinder(this);
97 #endif // !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE)
101 *ppAssembly = pCoreCLRFoundAssembly.Extract();
105 EX_CATCH_HRESULT(hr);
110 #if !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE)
111 HRESULT CLRPrivBinderCoreCLR::BindUsingPEImage( /* in */ PEImage *pPEImage,
112 /* in */ BOOL fIsNativeImage,
113 /* [retval][out] */ ICLRPrivAssembly **ppAssembly)
119 ReleaseHolder<BINDER_SPACE::Assembly> pCoreCLRFoundAssembly;
120 ReleaseHolder<BINDER_SPACE::AssemblyName> pAssemblyName;
121 ReleaseHolder<IMDInternalImport> pIMetaDataAssemblyImport;
123 PEKIND PeKind = peNone;
125 // Get the Metadata interface
127 IF_FAIL_GO(BinderAcquireImport(pPEImage, &pIMetaDataAssemblyImport, dwPAFlags, fIsNativeImage));
128 IF_FAIL_GO(AssemblyBinder::TranslatePEToArchitectureType(dwPAFlags, &PeKind));
130 _ASSERTE(pIMetaDataAssemblyImport != NULL);
132 // Using the information we just got, initialize the assemblyname
133 SAFE_NEW(pAssemblyName, AssemblyName);
134 IF_FAIL_GO(pAssemblyName->Init(pIMetaDataAssemblyImport, PeKind));
136 // Validate architecture
137 if (!BINDER_SPACE::Assembly::IsValidArchitecture(pAssemblyName->GetArchitecture()))
139 IF_FAIL_GO(HRESULT_FROM_WIN32(ERROR_BAD_FORMAT));
142 // Ensure we are not being asked to bind to a TPA assembly
144 // Easy out for mscorlib
145 if (pAssemblyName->IsMscorlib())
147 IF_FAIL_GO(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
151 SString& simpleName = pAssemblyName->GetSimpleName();
152 SimpleNameToFileNameMap * tpaMap = GetAppContext()->GetTpaList();
153 if (tpaMap->LookupPtr(simpleName.GetUnicode()) != NULL)
155 // The simple name of the assembly being requested to be bound was found in the TPA list.
156 // Now, perform the actual bind to see if the assembly was really in the TPA assembly list or not.
157 hr = BindAssemblyByNameWorker(pAssemblyName, &pCoreCLRFoundAssembly, true /* excludeAppPaths */);
160 if (pCoreCLRFoundAssembly->GetIsInGAC())
162 *ppAssembly = pCoreCLRFoundAssembly.Extract();
168 hr = AssemblyBinder::BindUsingPEImage(&m_appContext, pAssemblyName, pPEImage, PeKind, pIMetaDataAssemblyImport, &pCoreCLRFoundAssembly);
171 _ASSERTE(pCoreCLRFoundAssembly != NULL);
172 pCoreCLRFoundAssembly->SetBinder(this);
173 *ppAssembly = pCoreCLRFoundAssembly.Extract();
178 EX_CATCH_HRESULT(hr);
182 #endif // !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE)
184 HRESULT CLRPrivBinderCoreCLR::VerifyBind(IAssemblyName *AssemblyName,
185 ICLRPrivAssembly *pAssembly,
186 ICLRPrivAssemblyInfo *pAssemblyInfo)
191 HRESULT CLRPrivBinderCoreCLR::GetBinderFlags(DWORD *pBinderFlags)
193 if (pBinderFlags == NULL)
195 *pBinderFlags = BINDER_NONE;
199 HRESULT CLRPrivBinderCoreCLR::GetBinderID(
202 *pBinderId = reinterpret_cast<UINT_PTR>(this);
206 HRESULT CLRPrivBinderCoreCLR::FindAssemblyBySpec(
208 LPVOID pvAssemblySpec,
210 ICLRPrivAssembly **ppAssembly)
212 // We are not using a cache at this level
213 // However, assemblies bound by the CoreCLR binder is already cached in the
214 // AppDomain and will be resolved from there if required
218 HRESULT CLRPrivBinderCoreCLR::SetupBindingPaths(SString &sTrustedPlatformAssemblies,
219 SString &sPlatformResourceRoots,
221 SString &sAppNiPaths)
227 hr = m_appContext.SetupBindingPaths(sTrustedPlatformAssemblies, sPlatformResourceRoots, sAppPaths, sAppNiPaths, TRUE /* fAcquireLock */);
229 EX_CATCH_HRESULT(hr);
233 bool CLRPrivBinderCoreCLR::IsInTpaList(const SString &sFileName)
235 bool fIsFileOnTpaList = false;
237 TpaFileNameHash * tpaFileNameMap = m_appContext.GetTpaFileNameList();
238 if (tpaFileNameMap != nullptr)
240 const FileNameMapEntry *pTpaEntry = tpaFileNameMap->LookupPtr(sFileName.GetUnicode());
241 fIsFileOnTpaList = (pTpaEntry != nullptr);
244 return fIsFileOnTpaList;
247 // See code:BINDER_SPACE::AssemblyBinder::GetAssembly for info on fNgenExplicitBind
248 // and fExplicitBindToNativeImage, and see code:CEECompileInfo::LoadAssemblyByPath
249 // for an example of how they're used.
250 HRESULT CLRPrivBinderCoreCLR::Bind(SString &assemblyDisplayName,
252 PEAssembly *pParentAssembly,
253 BOOL fNgenExplicitBind,
254 BOOL fExplicitBindToNativeImage,
255 ICLRPrivAssembly **ppAssembly)
258 VALIDATE_ARG_RET(ppAssembly != NULL);
260 AssemblyName assemblyName;
262 ReleaseHolder<AssemblyName> pAssemblyName;
264 if (!assemblyDisplayName.IsEmpty())
266 // AssemblyDisplayName can be empty if wszCodeBase is specified.
267 SAFE_NEW(pAssemblyName, AssemblyName);
268 IF_FAIL_GO(pAssemblyName->Init(assemblyDisplayName));
273 ReleaseHolder<BINDER_SPACE::Assembly> pAsm;
274 hr = AssemblyBinder::BindAssembly(&m_appContext,
279 fExplicitBindToNativeImage,
280 false, // excludeAppPaths
284 _ASSERTE(pAsm != NULL);
285 pAsm->SetBinder(this);
286 *ppAssembly = pAsm.Extract();
289 EX_CATCH_HRESULT(hr);
295 #ifndef CROSSGEN_COMPILE
296 HRESULT CLRPrivBinderCoreCLR::PreBindByteArray(PEImage *pPEImage, BOOL fInspectionOnly)
299 VALIDATE_ARG_RET(pPEImage != NULL);
303 hr = AssemblyBinder::PreBindByteArray(&m_appContext, pPEImage, fInspectionOnly);
305 EX_CATCH_HRESULT(hr);
309 #endif // CROSSGEN_COMPILE