| 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 | |