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 | |
10 | using namespace BINDER_SPACE; |
11 | |
12 | //============================================================================= |
13 | // Helper functions |
14 | //----------------------------------------------------------------------------- |
15 | |
16 | HRESULT 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 | // ============================================================================ |
47 | HRESULT 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 | |
103 | Exit:; |
104 | } |
105 | EX_CATCH_HRESULT(hr); |
106 | |
107 | return hr; |
108 | } |
109 | |
110 | #if !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE) |
111 | HRESULT 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 | } |
176 | Exit:; |
177 | } |
178 | EX_CATCH_HRESULT(hr); |
179 | |
180 | return hr; |
181 | } |
182 | #endif // !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE) |
183 | |
184 | HRESULT CLRPrivBinderCoreCLR::GetBinderID( |
185 | UINT_PTR *pBinderId) |
186 | { |
187 | *pBinderId = reinterpret_cast<UINT_PTR>(this); |
188 | return S_OK; |
189 | } |
190 | |
191 | HRESULT 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. |
209 | HRESULT 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 | |
250 | Exit: |
251 | return hr; |
252 | } |
253 | |
254 | HRESULT CLRPrivBinderCoreCLR::GetLoaderAllocator(LPVOID* pLoaderAllocator) |
255 | { |
256 | // Not supported by this binder |
257 | return E_FAIL; |
258 | } |
259 | |
260 | #ifndef CROSSGEN_COMPILE |
261 | HRESULT 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 | |