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.
4
5#include "common.h"
6#include "assemblybinder.hpp"
7#include "clrprivbindercoreclr.h"
8#include "clrprivbinderutil.h"
9
10using namespace BINDER_SPACE;
11
12//=============================================================================
13// Helper functions
14//-----------------------------------------------------------------------------
15
16HRESULT CLRPrivBinderCoreCLR::BindAssemblyByNameWorker(BINDER_SPACE::AssemblyName *pAssemblyName,
17 BINDER_SPACE::Assembly **ppCoreCLRFoundAssembly,
18 bool excludeAppPaths)
19{
20 VALIDATE_ARG_RET(pAssemblyName != nullptr && ppCoreCLRFoundAssembly != nullptr);
21 HRESULT hr = S_OK;
22
23#ifdef _DEBUG
24 // MSCORLIB should be bound using BindToSystem
25 _ASSERTE(!pAssemblyName->IsMscorlib());
26#endif
27
28 hr = AssemblyBinder::BindAssembly(&m_appContext,
29 pAssemblyName,
30 NULL,
31 NULL,
32 FALSE, //fNgenExplicitBind,
33 FALSE, //fExplicitBindToNativeImage,
34 excludeAppPaths,
35 ppCoreCLRFoundAssembly);
36 if (!FAILED(hr))
37 {
38 (*ppCoreCLRFoundAssembly)->SetBinder(this);
39 }
40
41 return hr;
42}
43
44// ============================================================================
45// CLRPrivBinderCoreCLR implementation
46// ============================================================================
47HRESULT CLRPrivBinderCoreCLR::BindAssemblyByName(IAssemblyName *pIAssemblyName,
48 ICLRPrivAssembly **ppAssembly)
49{
50 HRESULT hr = S_OK;
51 VALIDATE_ARG_RET(pIAssemblyName != nullptr && ppAssembly != nullptr);
52
53 EX_TRY
54 {
55 *ppAssembly = nullptr;
56
57 ReleaseHolder<BINDER_SPACE::Assembly> pCoreCLRFoundAssembly;
58 ReleaseHolder<AssemblyName> pAssemblyName;
59
60 SAFE_NEW(pAssemblyName, AssemblyName);
61 IF_FAIL_GO(pAssemblyName->Init(pIAssemblyName));
62
63 hr = BindAssemblyByNameWorker(pAssemblyName, &pCoreCLRFoundAssembly, false /* excludeAppPaths */);
64
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))
68 {
69 // If we are here, one of the following is possible:
70 //
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).
74 //
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.
78
79 // Attempt to resolve the assembly via managed TPA ALC instance if one exists
80 INT_PTR pManagedAssemblyLoadContext = GetManagedAssemblyLoadContext();
81 if (pManagedAssemblyLoadContext != NULL)
82 {
83 hr = AssemblyBinder::BindUsingHostAssemblyResolver(pManagedAssemblyLoadContext, pAssemblyName, pIAssemblyName,
84 NULL, &pCoreCLRFoundAssembly);
85 if (SUCCEEDED(hr))
86 {
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)
91 {
92 pCoreCLRFoundAssembly->SetBinder(this);
93 }
94 }
95 }
96 }
97#endif // !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE)
98
99 IF_FAIL_GO(hr);
100
101 *ppAssembly = pCoreCLRFoundAssembly.Extract();
102
103Exit:;
104 }
105 EX_CATCH_HRESULT(hr);
106
107 return hr;
108}
109
110#if !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE)
111HRESULT CLRPrivBinderCoreCLR::BindUsingPEImage( /* in */ PEImage *pPEImage,
112 /* in */ BOOL fIsNativeImage,
113 /* [retval][out] */ ICLRPrivAssembly **ppAssembly)
114{
115 HRESULT hr = S_OK;
116
117 EX_TRY
118 {
119 ReleaseHolder<BINDER_SPACE::Assembly> pCoreCLRFoundAssembly;
120 ReleaseHolder<BINDER_SPACE::AssemblyName> pAssemblyName;
121 ReleaseHolder<IMDInternalImport> pIMetaDataAssemblyImport;
122
123 PEKIND PeKind = peNone;
124
125 // Get the Metadata interface
126 DWORD dwPAFlags[2];
127 IF_FAIL_GO(BinderAcquireImport(pPEImage, &pIMetaDataAssemblyImport, dwPAFlags, fIsNativeImage));
128 IF_FAIL_GO(AssemblyBinder::TranslatePEToArchitectureType(dwPAFlags, &PeKind));
129
130 _ASSERTE(pIMetaDataAssemblyImport != NULL);
131
132 // Using the information we just got, initialize the assemblyname
133 SAFE_NEW(pAssemblyName, AssemblyName);
134 IF_FAIL_GO(pAssemblyName->Init(pIMetaDataAssemblyImport, PeKind));
135
136 // Validate architecture
137 if (!BINDER_SPACE::Assembly::IsValidArchitecture(pAssemblyName->GetArchitecture()))
138 {
139 IF_FAIL_GO(HRESULT_FROM_WIN32(ERROR_BAD_FORMAT));
140 }
141
142 // Ensure we are not being asked to bind to a TPA assembly
143 //
144 // Easy out for mscorlib
145 if (pAssemblyName->IsMscorlib())
146 {
147 IF_FAIL_GO(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
148 }
149
150 {
151 SString& simpleName = pAssemblyName->GetSimpleName();
152 SimpleNameToFileNameMap * tpaMap = GetAppContext()->GetTpaList();
153 if (tpaMap->LookupPtr(simpleName.GetUnicode()) != NULL)
154 {
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 */);
158 if (SUCCEEDED(hr))
159 {
160 if (pCoreCLRFoundAssembly->GetIsInGAC())
161 {
162 *ppAssembly = pCoreCLRFoundAssembly.Extract();
163 goto Exit;
164 }
165 }
166 }
167
168 hr = AssemblyBinder::BindUsingPEImage(&m_appContext, pAssemblyName, pPEImage, PeKind, pIMetaDataAssemblyImport, &pCoreCLRFoundAssembly);
169 if (hr == S_OK)
170 {
171 _ASSERTE(pCoreCLRFoundAssembly != NULL);
172 pCoreCLRFoundAssembly->SetBinder(this);
173 *ppAssembly = pCoreCLRFoundAssembly.Extract();
174 }
175 }
176Exit:;
177 }
178 EX_CATCH_HRESULT(hr);
179
180 return hr;
181}
182#endif // !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE)
183
184HRESULT CLRPrivBinderCoreCLR::GetBinderID(
185 UINT_PTR *pBinderId)
186{
187 *pBinderId = reinterpret_cast<UINT_PTR>(this);
188 return S_OK;
189}
190
191HRESULT CLRPrivBinderCoreCLR::SetupBindingPaths(SString &sTrustedPlatformAssemblies,
192 SString &sPlatformResourceRoots,
193 SString &sAppPaths,
194 SString &sAppNiPaths)
195{
196 HRESULT hr = S_OK;
197
198 EX_TRY
199 {
200 hr = m_appContext.SetupBindingPaths(sTrustedPlatformAssemblies, sPlatformResourceRoots, sAppPaths, sAppNiPaths, TRUE /* fAcquireLock */);
201 }
202 EX_CATCH_HRESULT(hr);
203 return hr;
204}
205
206// See code:BINDER_SPACE::AssemblyBinder::GetAssembly for info on fNgenExplicitBind
207// and fExplicitBindToNativeImage, and see code:CEECompileInfo::LoadAssemblyByPath
208// for an example of how they're used.
209HRESULT CLRPrivBinderCoreCLR::Bind(SString &assemblyDisplayName,
210 LPCWSTR wszCodeBase,
211 PEAssembly *pParentAssembly,
212 BOOL fNgenExplicitBind,
213 BOOL fExplicitBindToNativeImage,
214 ICLRPrivAssembly **ppAssembly)
215{
216 HRESULT hr = S_OK;
217 VALIDATE_ARG_RET(ppAssembly != NULL);
218
219 AssemblyName assemblyName;
220
221 ReleaseHolder<AssemblyName> pAssemblyName;
222
223 if (!assemblyDisplayName.IsEmpty())
224 {
225 // AssemblyDisplayName can be empty if wszCodeBase is specified.
226 SAFE_NEW(pAssemblyName, AssemblyName);
227 IF_FAIL_GO(pAssemblyName->Init(assemblyDisplayName));
228 }
229
230 EX_TRY
231 {
232 ReleaseHolder<BINDER_SPACE::Assembly> pAsm;
233 hr = AssemblyBinder::BindAssembly(&m_appContext,
234 pAssemblyName,
235 wszCodeBase,
236 pParentAssembly,
237 fNgenExplicitBind,
238 fExplicitBindToNativeImage,
239 false, // excludeAppPaths
240 &pAsm);
241 if(SUCCEEDED(hr))
242 {
243 _ASSERTE(pAsm != NULL);
244 pAsm->SetBinder(this);
245 *ppAssembly = pAsm.Extract();
246 }
247 }
248 EX_CATCH_HRESULT(hr);
249
250Exit:
251 return hr;
252}
253
254HRESULT CLRPrivBinderCoreCLR::GetLoaderAllocator(LPVOID* pLoaderAllocator)
255{
256 // Not supported by this binder
257 return E_FAIL;
258}
259
260#ifndef CROSSGEN_COMPILE
261HRESULT CLRPrivBinderCoreCLR::PreBindByteArray(PEImage *pPEImage, BOOL fInspectionOnly)
262{
263 HRESULT hr = S_OK;
264 VALIDATE_ARG_RET(pPEImage != NULL);
265
266 EX_TRY
267 {
268 hr = AssemblyBinder::PreBindByteArray(&m_appContext, pPEImage, fInspectionOnly);
269 }
270 EX_CATCH_HRESULT(hr);
271
272 return hr;
273}
274#endif // CROSSGEN_COMPILE
275