diff options
Diffstat (limited to 'src/vm/clrprivbinderfusion.cpp')
-rw-r--r-- | src/vm/clrprivbinderfusion.cpp | 819 |
1 files changed, 0 insertions, 819 deletions
diff --git a/src/vm/clrprivbinderfusion.cpp b/src/vm/clrprivbinderfusion.cpp deleted file mode 100644 index d31774f7b2..0000000000 --- a/src/vm/clrprivbinderfusion.cpp +++ /dev/null @@ -1,819 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - - - -#include "common.h" // precompiled header - -#ifndef DACCESS_COMPILE - -//===================================================================================================================== -#include "assemblyspec.hpp" -#include "corhdr.h" -#include "domainfile.h" -#include "fusion.h" -#include "policy.h" -#include "sstring.h" -#include "stackingallocator.h" -#include "threads.h" -#include "clrprivbinderfusion.h" -#include "clrprivbinderutil.h" -#include "fusionlogging.h" - -using namespace CLRPrivBinderUtil; - -//================================================================================================= -#define STDMETHOD_NOTIMPL(...) \ - STDMETHOD(__VA_ARGS__) \ - { \ - WRAPPER_NO_CONTRACT; \ - _ASSERTE_MSG(false, "Method not implemented."); \ - return E_NOTIMPL; \ - } - -//================================================================================================= -static HRESULT PropagateOutStringArgument( - __in LPCSTR pszValue, - __out_ecount_opt(*pcchArg) LPWSTR pwzArg, - __in DWORD cchArg, - __out DWORD * pcchArg) -{ - LIMITED_METHOD_CONTRACT; - - VALIDATE_PTR_RET(pszValue); - VALIDATE_CONDITION((pwzArg == nullptr || cchArg > 0), return E_INVALIDARG); - - HRESULT hr = S_OK; - - if (pwzArg != nullptr) - { - DWORD cchWritten = WszMultiByteToWideChar( - CP_UTF8, 0 /*flags*/, pszValue, -1, pwzArg, cchArg); - - if (cchWritten == 0) - { - hr = HRESULT_FROM_GetLastError(); - } - else if (pcchArg != nullptr) - { - *pcchArg = cchWritten; - } - } - - if (pcchArg != nullptr && (pwzArg == nullptr || hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER))) - { - *pcchArg = WszMultiByteToWideChar( - CP_UTF8, 0 /*flags*/, pszValue, -1, nullptr, 0); - - if (*pcchArg == 0) - { - hr = HRESULT_FROM_GetLastError(); - } - } - - return hr; -} - -//================================================================================================= -// This is needed to allow calls to IsAnyFrameworkAssembly in GC_NOTRIGGER/NO_FAULT regions (i.e., -// GC stack walking). CAssemblyName (which implements IAssemblyName in most other uses) allocates -// during construction and so cannot be used in this scenario. - -class AssemblySpecAsIAssemblyName - : public IAssemblyName -{ -public: - AssemblySpecAsIAssemblyName( - AssemblySpec * pSpec) - : m_pSpec(pSpec) - { LIMITED_METHOD_CONTRACT; } - - //============================================================================================= - // IUnknown methods - - // Not used by IsAnyFrameworkAssembly - STDMETHOD_(ULONG, AddRef()) - { - WRAPPER_NO_CONTRACT; - _ASSERTE_MSG(false, "Method not implemented."); - return E_NOTIMPL; - } - - // Not used by IsAnyFrameworkAssembly - STDMETHOD_(ULONG, Release()) - { - WRAPPER_NO_CONTRACT; - _ASSERTE_MSG(false, "Method not implemented."); - return E_NOTIMPL; - } - - // Not used by IsAnyFrameworkAssembly - STDMETHOD_NOTIMPL(QueryInterface( - REFIID riid, - void **ppvObject)); - - //============================================================================================= - // IAssemblyName methods - - STDMETHOD_NOTIMPL(SetProperty( - DWORD PropertyId, - void const * pvProperty, - DWORD cbProperty)); - -#define ASSURE_SUFFICIENT_BUFFER(SRCSIZE) \ - do { \ - if ((pvProperty == nullptr) || (*pcbProperty < SRCSIZE)) { \ - *pcbProperty = SRCSIZE; \ - return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); \ - } \ - } while (false) - - STDMETHOD(GetProperty)( - DWORD PropertyId, - LPVOID pvProperty, - LPDWORD pcbProperty) - { - LIMITED_METHOD_CONTRACT; - - VALIDATE_PTR_RET(pcbProperty); - VALIDATE_CONDITION((pvProperty == nullptr) == (*pcbProperty == 0), return E_INVALIDARG); - - HRESULT hr = S_OK; - - switch (PropertyId) - { - case ASM_NAME_NAME: - return PropagateOutStringArgument(m_pSpec->GetName(), (LPWSTR) pvProperty, - *pcbProperty / sizeof(WCHAR), pcbProperty); - - case ASM_NAME_MAJOR_VERSION: - ASSURE_SUFFICIENT_BUFFER(sizeof(USHORT)); - *reinterpret_cast<USHORT*>(pvProperty) = m_pSpec->GetContext()->usMajorVersion; - *pcbProperty = sizeof(USHORT); - return S_OK; - - case ASM_NAME_MINOR_VERSION: - ASSURE_SUFFICIENT_BUFFER(sizeof(USHORT)); - *reinterpret_cast<USHORT*>(pvProperty) = m_pSpec->GetContext()->usMinorVersion; - *pcbProperty = sizeof(USHORT); - return S_OK; - - case ASM_NAME_BUILD_NUMBER: - ASSURE_SUFFICIENT_BUFFER(sizeof(USHORT)); - *reinterpret_cast<USHORT*>(pvProperty) = m_pSpec->GetContext()->usBuildNumber; - *pcbProperty = sizeof(USHORT); - return S_OK; - - case ASM_NAME_REVISION_NUMBER: - ASSURE_SUFFICIENT_BUFFER(sizeof(USHORT)); - *reinterpret_cast<USHORT*>(pvProperty) = m_pSpec->GetContext()->usRevisionNumber; - *pcbProperty = sizeof(USHORT); - return S_OK; - - case ASM_NAME_CULTURE: - if (m_pSpec->GetContext()->szLocale == nullptr) - { - return FUSION_E_INVALID_NAME; - } - return PropagateOutStringArgument(m_pSpec->GetContext()->szLocale, (LPWSTR) pvProperty, - *pcbProperty / sizeof(WCHAR), pcbProperty); - - case ASM_NAME_PUBLIC_KEY_TOKEN: - { - if (!m_pSpec->HasPublicKeyToken()) - { - return FUSION_E_INVALID_NAME; - } - - PBYTE pbSN; - DWORD cbSN; - m_pSpec->GetPublicKeyToken(&pbSN, &cbSN); - ASSURE_SUFFICIENT_BUFFER(cbSN); - memcpy_s(pvProperty, *pcbProperty, pbSN, cbSN); - *pcbProperty = cbSN; - } - return S_OK; - - case ASM_NAME_RETARGET: - ASSURE_SUFFICIENT_BUFFER(sizeof(BOOL)); - *reinterpret_cast<BOOL*>(pvProperty) = m_pSpec->IsRetargetable(); - *pcbProperty = sizeof(BOOL); - return S_OK; - - default: - _ASSERTE_MSG(false, "Unexpected property requested."); - return E_INVALIDARG; - } - } - -#undef ASSURE_SUFFICIENT_BUFFER - - // Not used by IsAnyFrameworkAssembly - STDMETHOD_NOTIMPL(Finalize()); - - // Not used by IsAnyFrameworkAssembly - STDMETHOD_NOTIMPL(GetDisplayName( - __out_ecount_opt(*pccDisplayName) LPOLESTR szDisplayName, - __inout LPDWORD pccDisplayName, - DWORD dwDisplayFlags)); - - // Not used by IsAnyFrameworkAssembly - STDMETHOD_NOTIMPL(Reserved( - REFIID refIID, - IUnknown *pUnkReserved1, - IUnknown *pUnkReserved2, - LPCOLESTR szReserved, - LONGLONG llReserved, - LPVOID pvReserved, - DWORD cbReserved, - LPVOID *ppReserved)); - - - STDMETHOD(GetName)( - __inout LPDWORD lpcwBuffer, - __out_ecount_opt(*lpcwBuffer) WCHAR *pwzName) - { - LIMITED_METHOD_CONTRACT; - - VALIDATE_PTR_RET(lpcwBuffer); - return PropagateOutStringArgument( - m_pSpec->GetName(), pwzName, *lpcwBuffer, lpcwBuffer); - } - - STDMETHOD(GetVersion)( - LPDWORD pdwVersionHi, - LPDWORD pdwVersionLow) - { - LIMITED_METHOD_CONTRACT; - - HRESULT hr = S_OK; - - VALIDATE_PTR_RET(pdwVersionHi); - VALIDATE_PTR_RET(pdwVersionLow); - - AssemblyMetaDataInternal * pAMDI = m_pSpec->GetContext(); - - *pdwVersionHi = MAKELONG(pAMDI->usMinorVersion, pAMDI->usMajorVersion); - *pdwVersionLow = MAKELONG(pAMDI->usRevisionNumber, pAMDI->usBuildNumber); - - return S_OK; - } - - - // Exists exclusively to support fusion's IsSystem helper, which compares against 'mscorlib'. - STDMETHOD(IsEqual)( - IAssemblyName *pName, - DWORD dwCmpFlags) - { - LIMITED_METHOD_CONTRACT; - - HRESULT hr = S_OK; - - VALIDATE_PTR_RET(pName); - - // This function is here just to support checks against the name 'mscorlib'. - if ((dwCmpFlags & ASM_CMPF_NAME) != ASM_CMPF_NAME) - { - return E_NOTIMPL; - } - - DWORD cchName1 = 0; - WCHAR wzName1[_MAX_PATH]; - IfFailRet(pName->GetName(&cchName1, wzName1)); - _ASSERTE(SString::_wcsicmp(wzName1, W("mscorlib")) == 0); - - WCHAR wzName2[_MAX_PATH]; - DWORD cchName2 = WszMultiByteToWideChar( - CP_UTF8, 0 /*flags*/, m_pSpec->GetName(), -1, wzName2, (int) (sizeof(wzName2) / sizeof(wzName2[0]))); - - if (0 == cchName2) - { - _ASSERTE(HRESULT_FROM_GetLastError() != HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)); - return HRESULT_FROM_GetLastError(); - } - - if (cchName1 != cchName2) - { - return S_FALSE; - } - - return SString::_wcsnicmp(wzName1, wzName2, cchName1) == 0 - ? S_OK - : S_FALSE; - } - - STDMETHOD_NOTIMPL(Clone( - IAssemblyName **pName)); - -private: - AssemblySpec * m_pSpec; -}; - -//===================================================================================================================== -HRESULT CLRPrivBinderFusion::FindFusionAssemblyBySpec( - LPVOID pvAppDomain, - LPVOID pvAssemblySpec, - BindingScope kBindingScope, - HRESULT * pResult, - ICLRPrivAssembly ** ppAssembly) -{ - LIMITED_METHOD_CONTRACT;; - HRESULT hr = S_OK; - - AppDomain* pAppDomain = reinterpret_cast<AppDomain*>(pvAppDomain); - AssemblySpec* pAssemblySpec = reinterpret_cast<AssemblySpec*>(pvAssemblySpec); - VALIDATE_PTR_RET(pAppDomain); - VALIDATE_PTR_RET(pAssemblySpec); - VALIDATE_PTR_RET(pResult); - VALIDATE_PTR_RET(ppAssembly); - - if (pAssemblySpec->IsContentType_WindowsRuntime()) - { - return CLR_E_BIND_UNRECOGNIZED_IDENTITY_FORMAT; - } - - BOOL fIsSupportedInAppX; - { - AssemblySpecAsIAssemblyName asName(pAssemblySpec); - - if (Fusion::Util::IsAnyFrameworkAssembly(&asName, &fIsSupportedInAppX) != S_OK) - { // Not a framework assembly identity. - IfFailRet(CLR_E_BIND_UNRECOGNIZED_IDENTITY_FORMAT); - } - } - - if (kBindingScope == kBindingScope_FrameworkSubset) - { // We should allow only some framework assemblies to load - - // DevMode has to allow all FX assemblies, not just a subset - see code:PreBind for more info - { - // Disabling for now, as it causes too many violations. - //CONTRACT_VIOLATION(GCViolation | FaultViolation | ModeViolation); - //_ASSERTE(!AppX::IsAppXDesignMode()); - } - - if (!fIsSupportedInAppX) - { // Assembly is blocked for AppX, fail the load - *pResult = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); - *ppAssembly = nullptr; - return S_OK; - } - } - - return FindAssemblyBySpec(pvAppDomain, pvAssemblySpec, pResult, ppAssembly); -} - -//===================================================================================================================== -static -PEAssembly * FindCachedFile(AppDomain * pDomain, AssemblySpec * pSpec) -{ - // Look for cached bind result. Prefer a cached DomainAssembly, as it takes priority over a - // cached PEAssembly (which can be different from the one associated with the DomainAssembly). - DomainAssembly * pDomainAssembly = pDomain->FindCachedAssembly(pSpec, FALSE); - return (pDomainAssembly != nullptr) - ? (pDomainAssembly->GetFile()) - : (pDomain->FindCachedFile(pSpec, FALSE)); -} - -//===================================================================================================================== -// There is no need to create a separate binding record, since we can always just look in the AppDomain's -// AssemblySpecBindingCache for an answer (which is precisely what this function does). - -HRESULT CLRPrivBinderFusion::FindAssemblyBySpec( - LPVOID pvAppDomain, - LPVOID pvAssemblySpec, - HRESULT * pResult, - ICLRPrivAssembly ** ppAssembly) -{ - LIMITED_METHOD_CONTRACT;; - HRESULT hr = S_OK; - - AppDomain* pAppDomain = reinterpret_cast<AppDomain*>(pvAppDomain); - AssemblySpec* pAssemblySpec = reinterpret_cast<AssemblySpec*>(pvAssemblySpec); - VALIDATE_PTR_RET(pAppDomain); - VALIDATE_PTR_RET(pAssemblySpec); - VALIDATE_PTR_RET(pResult); - VALIDATE_PTR_RET(ppAssembly); - - // For the Architecture property, canonicalize peMSIL to peNone (which are considered equivalent), - // to ensure consistent lookups in the AssemblySpecBindingCache for the CLRPrivBinderFusion binder. - if (pAssemblySpec->GetPEKIND() == peMSIL) - { - pAssemblySpec->SetPEKIND(peNone); - } - - PEAssembly * pPEAssembly = FindCachedFile(pAppDomain, pAssemblySpec); - if (pPEAssembly == nullptr) - { - return E_FAIL; - } - - // Could be racing with another thread that has just added the PEAssembly to the binding cache - // but not yet allocated and assigned a host assembly. - if (!pPEAssembly->HasHostAssembly()) - { - return E_FAIL; - } - - *pResult = S_OK; - *ppAssembly = clr::SafeAddRef(pPEAssembly->GetHostAssembly()); - - return S_OK; -} - -//===================================================================================================================== -HRESULT CLRPrivBinderFusion::BindAssemblyByNameWorker( - IAssemblyName * pAssemblyName, - ICLRPrivAssembly ** ppAssembly) -{ - STANDARD_VM_CONTRACT; - PRECONDITION(CheckPointer(pAssemblyName)); - PRECONDITION(CheckPointer(ppAssembly)); - - HRESULT hr = S_OK; - - AppDomain * pCurDomain = AppDomain::GetCurrentDomain(); - if (pCurDomain == nullptr) - ThrowHR(E_UNEXPECTED); - - AssemblySpec prePolicySpec; - AssemblySpec postPolicySpec; - - prePolicySpec.InitializeSpec(pAssemblyName); - - // For the Architecture property, canonicalize peMSIL to peNone (which are considered equivalent), - // to ensure consistent lookups in the AssemblySpecBindingCache for the CLRPrivBinderFusion binder. - if (prePolicySpec.GetPEKIND() == peMSIL) - { - prePolicySpec.SetPEKIND(peNone); - } - - AssemblySpec * pBindSpec = &prePolicySpec; - PEAssemblyHolder pPEAssembly = clr::SafeAddRef(FindCachedFile(pCurDomain, pBindSpec)); - - if (pPEAssembly == nullptr) - { - // Early on in domain setup there may not be a fusion context, so skip ApplyPolicy then. - _ASSERTE(pCurDomain->GetFusionContext() != nullptr || prePolicySpec.IsMscorlib()); - if (pCurDomain->GetFusionContext() != nullptr) - { - ReleaseHolder<IAssemblyName> pPolicyAssemblyName; - DWORD dwPolicyApplied = 0; - ApplyPolicy(pAssemblyName, pCurDomain->GetFusionContext(), nullptr, &pPolicyAssemblyName, nullptr, nullptr, &dwPolicyApplied); - - if (dwPolicyApplied != 0) - { - postPolicySpec.InitializeSpec(pPolicyAssemblyName); - pBindSpec = &postPolicySpec; - pPEAssembly = clr::SafeAddRef(FindCachedFile(pCurDomain, pBindSpec)); - } - } - - if (pPEAssembly == nullptr) - { - // Trigger a load. - pPEAssembly = pCurDomain->BindAssemblySpec( - pBindSpec, // AssemblySpec - TRUE, // ThrowOnFileNotFound - FALSE, // RaisePrebindEvents - nullptr, // CallerStackMark - nullptr, // AssemblyLoadSecurity - FALSE); // fUseHostBinderIfAvailable - to avoid infinite recursion - _ASSERTE(FindCachedFile(pCurDomain, pBindSpec) == pPEAssembly || pBindSpec->IsMscorlib()); - } - - // If a post-policy spec was used, add the pre-policy spec to the binding cache - // so that it can be found by FindAssemblyBySpec. - if (&prePolicySpec != pBindSpec) - { - // Failure to add simply means someone else beat us to it. In that case - // the FindCachedFile call below (after catch block) will update result - // to the cached value. - INDEBUG(BOOL fRes =) pCurDomain->AddFileToCache(&prePolicySpec, pPEAssembly, TRUE /* fAllowFailure */); - _ASSERTE(!fRes || prePolicySpec.IsMscorlib() || FindCachedFile(pCurDomain, &prePolicySpec) == pPEAssembly); - } - - // Ensure that the assembly is discoverable through a consistent assembly name (the assembly def name of the assembly) - AssemblySpec specAssemblyDef; - specAssemblyDef.InitializeSpec(pPEAssembly); - - // It is expected that all assemlbies found here will be unified assemblies, and therefore have a public key. - _ASSERTE(specAssemblyDef.IsStrongNamed()); - - // Convert public key into the format that matches the garaunteed cache in the AssemblySpecBindingCache ... see the extended logic - // in Module::GetAssemblyIfLoaded. - if (specAssemblyDef.IsStrongNamed() && specAssemblyDef.HasPublicKey()) - { - specAssemblyDef.ConvertPublicKeyToToken(); - } - pCurDomain->AddFileToCache(&specAssemblyDef, pPEAssembly, TRUE); - } - - if (!pPEAssembly->HasHostAssembly()) - { - // This can happen if we just loaded the PEAssembly with BindAssemblySpec above, or if the PEAssembly - // Was not loaded through this binder. (NGEN Case) - - // Note: There can be multiple PEAssembly objects for the same file, however we have to create unique - // CLRPrivAssemblyFusion object, otherwise code:AppDomain::FindAssembly will not recognize the duplicates which - // will lead to creation of multiple code:DomainAssembly objects for the same file in the same AppDomain. - - InlineSString<128> ssPEAssemblyName; - FusionBind::GetAssemblyNameDisplayName(pPEAssembly->GetFusionAssemblyName(), ssPEAssemblyName, ASM_DISPLAYF_FULL); - NewHolder<CLRPrivAssemblyFusion> pAssemblyObj = new CLRPrivAssemblyFusion(ssPEAssemblyName.GetUnicode(), this); - - { - CrstHolder lock(&m_SetHostAssemblyLock); - if (!pPEAssembly->HasHostAssembly()) - { - // Add the host assembly to the PEAssembly. - pPEAssembly->SetHostAssembly(pAssemblyObj.Extract()); - } - } - } - - // Trigger a load so that a DomainAssembly is associated with the ICLRPrivAssembly created above. - pPEAssembly = clr::SafeAddRef(pCurDomain->LoadDomainAssembly(pBindSpec, pPEAssembly, FILE_LOADED)->GetFile()); - - _ASSERTE(pPEAssembly != nullptr); - _ASSERTE(pPEAssembly->HasHostAssembly()); - _ASSERTE(pCurDomain->FindAssembly(pPEAssembly->GetHostAssembly()) != nullptr); - - fusion::logging::LogMessage(0, ID_FUSLOG_BINDING_STATUS_FOUND, pPEAssembly->GetPath().GetUnicode()); - - *ppAssembly = clr::SafeAddRef(pPEAssembly->GetHostAssembly()); - - return hr; -} - -//===================================================================================================================== -void CLRPrivBinderFusion::BindMscorlib( - PEAssembly * pPEAssembly) -{ - STANDARD_VM_CONTRACT; - -#ifdef _DEBUG - NewArrayHolder<WCHAR> dbg_wszAssemblySimpleName; - _ASSERTE(SUCCEEDED(fusion::util::GetProperty(pPEAssembly->GetFusionAssemblyName(), ASM_NAME_NAME, &dbg_wszAssemblySimpleName))); - - _ASSERTE(wcscmp(dbg_wszAssemblySimpleName, W("mscorlib")) == 0); -#endif //_DEBUG - - NewHolder<CLRPrivAssemblyFusion> pPrivAssembly = new CLRPrivAssemblyFusion(W("mscorlib"), this); - - pPEAssembly->SetHostAssembly(pPrivAssembly.Extract()); -} - -//===================================================================================================================== -HRESULT CLRPrivBinderFusion::BindFusionAssemblyByName( - IAssemblyName * pAssemblyName, - BindingScope kBindingScope, - ICLRPrivAssembly ** ppAssembly) -{ - STANDARD_VM_CONTRACT; - HRESULT hr = S_OK; - - fusion::logging::StatusScope logStatus(0, ID_FUSLOG_BINDING_STATUS_FRAMEWORK, &hr); - - DWORD dwContentType = AssemblyContentType_Default; - IfFailRet(fusion::util::GetProperty(pAssemblyName, ASM_NAME_CONTENT_TYPE, &dwContentType)); - if ((hr == S_OK) && (dwContentType != AssemblyContentType_Default)) - { // Not a NetFX content type. - IfFailRet(CLR_E_BIND_UNRECOGNIZED_IDENTITY_FORMAT); - } - - BOOL fIsSupportedInAppX; - if (Fusion::Util::IsAnyFrameworkAssembly(pAssemblyName, &fIsSupportedInAppX) != S_OK) - { // Not a framework assembly identity. - IfFailRet(CLR_E_BIND_UNRECOGNIZED_IDENTITY_FORMAT); - } - if (kBindingScope == kBindingScope_FrameworkSubset) - { // We should allow only some framework assemblies to load - - // DevMode has to allow all FX assemblies, not just a subset - see code:PreBind for more info - _ASSERTE(!AppX::IsAppXDesignMode()); - - if (!fIsSupportedInAppX) - { // Assembly is blocked for AppX, fail the load - fusion::logging::LogMessage(0, ID_FUSLOG_BINDING_STATUS_FX_ASSEMBLY_BLOCKED); - - IfFailRet(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)); - } - } - - return (hr = BindAssemblyByNameWorker(pAssemblyName, ppAssembly)); -} - -//===================================================================================================================== -// Implements code:ICLRPrivBinder::BindAssemblyByName -HRESULT CLRPrivBinderFusion::BindAssemblyByName( - IAssemblyName * pAssemblyName, - ICLRPrivAssembly ** ppAssembly) -{ - WRAPPER_NO_CONTRACT; - return BindAssemblyByNameWorker( - pAssemblyName, - ppAssembly); -} - -//===================================================================================================================== -// Implements code:ICLRPrivBinder::GetBinderID -HRESULT CLRPrivBinderFusion::GetBinderID( - UINT_PTR *pBinderId) -{ - LIMITED_METHOD_CONTRACT; - - *pBinderId = (UINT_PTR)this; - return S_OK; -} - -//===================================================================================================================== -// Implements code:IBindContext::PreBind -HRESULT CLRPrivBinderFusion::PreBind( - IAssemblyName * pIAssemblyName, - DWORD dwPreBindFlags, - IBindResult ** ppIBindResult) -{ - STANDARD_BIND_CONTRACT; - PRECONDITION(CheckPointer(pIAssemblyName)); - PRECONDITION(CheckPointer(ppIBindResult)); - - HRESULT hr = S_OK; - - BOOL fIsSupportedInAppX; - if (Fusion::Util::IsAnyFrameworkAssembly(pIAssemblyName, &fIsSupportedInAppX) != S_OK) - { // Not a framework assembly identity. - return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); - } - - EX_TRY - { - // Create new IL binding scope. - fusion::logging::BindingScope defaultScope(pIAssemblyName, FUSION_BIND_LOG_CATEGORY_DEFAULT); - - // Ideally the caller would give us arg kBindingContext like in code:BindFusionAssemblyByName, so we can give the same answer. - // That is not easy, so we will make the decision here: - // - DevMode will allow all FX assemblies (that covers designer binding context scenario for designers that need to - // load WPF with ngen images for perf reasons). - // We know that the real bind via code:BindFusionAssemblyByName will succeed for the assemblies (because we are in DevMode). - // - Normal mode (non-DevMode) we will allow only subset of FX assemblies. - // It implies that designer binding context (used by debuggers) will not use ngen images for blocked FX assemblies - // (transitively). That is acceptable performance trade-off. - if (!AppX::IsAppXDesignMode()) - { // We should allow only some framework assemblies to load - if (!fIsSupportedInAppX) - { // Assembly is blocked for AppX, fail the load - fusion::logging::LogMessage(0, ID_FUSLOG_BINDING_STATUS_FX_ASSEMBLY_BLOCKED); - - hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); - } - } - - if (SUCCEEDED(hr)) - { - AppDomain * pDomain = AppDomain::GetCurrentDomain(); - ReleaseHolder<IBindContext> pIBindContext; - if (SUCCEEDED(hr = GetBindContextFromApplicationContext(pDomain->CreateFusionContext(), &pIBindContext))) - { - hr = pIBindContext->PreBind(pIAssemblyName, dwPreBindFlags, ppIBindResult); - } - } - } - EX_CATCH_HRESULT(hr); - - return hr; -} - -//===================================================================================================================== -HRESULT CLRPrivBinderFusion::PreBindFusionAssemblyByName( - IAssemblyName *pIAssemblyName, - DWORD dwPreBindFlags, - IBindResult **ppIBindResult) -{ - STANDARD_VM_CONTRACT; - HRESULT hr = S_OK; - - DWORD dwContentType = AssemblyContentType_Default; - IfFailRet(fusion::util::GetProperty(pIAssemblyName, ASM_NAME_CONTENT_TYPE, &dwContentType)); - if ((hr == S_OK) && (dwContentType != AssemblyContentType_Default)) - { // Not a NetFX content type. - IfFailRet(CLR_E_BIND_UNRECOGNIZED_IDENTITY_FORMAT); - } - - IfFailRet(PreBind(pIAssemblyName, dwPreBindFlags, ppIBindResult)); - _ASSERTE(*ppIBindResult != nullptr); - - if (*ppIBindResult == nullptr) - IfFailRet(E_UNEXPECTED); - - return S_OK; -} - -//===================================================================================================================== -// Implements code:IBindContext::IsDefaultContext -HRESULT CLRPrivBinderFusion::IsDefaultContext() -{ - STANDARD_BIND_CONTRACT; - return S_OK; -} - -//===================================================================================================================== -CLRPrivBinderFusion::~CLRPrivBinderFusion() -{ - WRAPPER_NO_CONTRACT; -} - -//===================================================================================================================== -CLRPrivAssemblyFusion::CLRPrivAssemblyFusion( - LPCWSTR wszName, - CLRPrivBinderFusion * pBinder) - : m_pBinder(clr::SafeAddRef(pBinder)), - m_wszName(DuplicateStringThrowing(wszName)) -{ - STANDARD_VM_CONTRACT; -} - -//===================================================================================================================== -LPCWSTR CLRPrivAssemblyFusion::GetName() const -{ - LIMITED_METHOD_CONTRACT; - - return m_wszName; -} - -//===================================================================================================================== -// Implements code:IUnknown::Release -ULONG CLRPrivAssemblyFusion::Release() -{ - LIMITED_METHOD_CONTRACT; - STATIC_CONTRACT_CAN_TAKE_LOCK; - _ASSERTE(m_cRef > 0); - - ULONG cRef = InterlockedDecrement(&m_cRef); - - if (cRef == 0) - { - delete this; - } - - return cRef; -} - -//===================================================================================================================== -// Implements code:ICLRPrivBinder::BindAssemblyByName -HRESULT CLRPrivAssemblyFusion::BindAssemblyByName( - IAssemblyName * pAssemblyName, - ICLRPrivAssembly ** ppAssembly) -{ - WRAPPER_NO_CONTRACT; - return m_pBinder->BindAssemblyByName( - pAssemblyName, - ppAssembly); -} - -//===================================================================================================================== -// Implements code:ICLRPrivBinder::GetBinderID -HRESULT CLRPrivAssemblyFusion::GetBinderID( - UINT_PTR *pBinderId) -{ - LIMITED_METHOD_CONTRACT; - - *pBinderId = reinterpret_cast<UINT_PTR>(m_pBinder.GetValue()); - return S_OK; -} - -//===================================================================================================================== -// Implements code:ICLRPrivAssembly::IsShareable -HRESULT CLRPrivAssemblyFusion::IsShareable( - BOOL * pbIsShareable) -{ - LIMITED_METHOD_CONTRACT; - *pbIsShareable = TRUE; // These things are only used in the AppX scenario, where all fusion assemblies are unified, shareable assemblies. - return S_OK; -} - -//===================================================================================================================== -// Implements code:ICLRPrivAssembly::GetAvailableImageTypes -HRESULT CLRPrivAssemblyFusion::GetAvailableImageTypes( - LPDWORD pdwImageTypes) -{ - LIMITED_METHOD_CONTRACT; - _ASSERTE(!"CLRPrivAssemblyFusion::GetAvailableImageTypes"); - return E_NOTIMPL; -} - -//===================================================================================================================== -// Implements code:ICLRPrivAssembly::GetImageResource -HRESULT CLRPrivAssemblyFusion::GetImageResource( - DWORD dwImageType, - DWORD *pdwImageType, - ICLRPrivResource ** ppIResource) -{ - LIMITED_METHOD_CONTRACT; - _ASSERTE(!"CLRPrivAssemblyFusion::GetImageResource"); - return E_NOTIMPL; -} - -#endif // !DACCESS_COMPILE - |