summaryrefslogtreecommitdiff
path: root/src/vm/clrprivbinderutil.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/vm/clrprivbinderutil.cpp')
-rw-r--r--src/vm/clrprivbinderutil.cpp831
1 files changed, 831 insertions, 0 deletions
diff --git a/src/vm/clrprivbinderutil.cpp b/src/vm/clrprivbinderutil.cpp
new file mode 100644
index 0000000000..b6871123d9
--- /dev/null
+++ b/src/vm/clrprivbinderutil.cpp
@@ -0,0 +1,831 @@
+// 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.
+//
+
+//
+// Contains helper types for assembly binding host infrastructure.
+
+#include "common.h"
+
+#include "utilcode.h"
+#include "strsafe.h"
+
+#include "clrprivbinderutil.h"
+
+inline
+LPWSTR CopyStringThrowing(
+ LPCWSTR wszString)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_NOTRIGGER;
+ }
+ CONTRACTL_END;
+
+ NewArrayHolder<WCHAR> wszDup = NULL;
+ if (wszString != NULL)
+ {
+ size_t wszLen = wcslen(wszString);
+ wszDup = new WCHAR[wszLen + 1];
+ IfFailThrow(StringCchCopy(wszDup, wszLen + 1, wszString));
+ }
+ wszDup.SuppressRelease();
+
+ return wszDup;
+}
+
+
+namespace CLRPrivBinderUtil
+{
+#ifdef FEATURE_FUSION
+ //-----------------------------------------------------------------------------------------------------------------
+ CLRPrivAssemblyBindResultWrapper::CLRPrivAssemblyBindResultWrapper(
+ IAssemblyName *pIAssemblyName,
+ PCWSTR wzAssemblyPath,
+ IILFingerprintFactory *pILFingerprintFactory
+ ) :
+ m_wzAssemblyPath(DuplicateStringThrowing(wzAssemblyPath)),
+ m_pIAssemblyName(clr::SafeAddRef(pIAssemblyName)),
+ m_bIBindResultNISet(false),
+ m_pIBindResultNI(nullptr),
+ m_pIILFingerprint(nullptr),
+ m_pILFingerprintFactory(clr::SafeAddRef(pILFingerprintFactory)),
+ m_lock(CrstLeafLock)
+ {
+ STANDARD_VM_CONTRACT;
+ VALIDATE_ARG_THROW(pIAssemblyName != nullptr && wzAssemblyPath != nullptr);
+ }
+
+ //-----------------------------------------------------------------------------------------------------------------
+ CLRPrivAssemblyBindResultWrapper::~CLRPrivAssemblyBindResultWrapper()
+ {
+ clr::SafeRelease(m_pIAssemblyName);
+ clr::SafeRelease(m_pIILFingerprint);
+ clr::SafeRelease(m_pIBindResultNI);
+ }
+
+ //=================================================================================================================
+ // IBindResult methods
+
+ //-----------------------------------------------------------------------------------------------------------------
+ HRESULT CLRPrivAssemblyBindResultWrapper::GetAssemblyNameDef(
+ /*out*/ IAssemblyName **ppIAssemblyNameDef)
+ {
+ LIMITED_METHOD_CONTRACT;
+
+ VALIDATE_ARG_RET(ppIAssemblyNameDef != nullptr);
+ *ppIAssemblyNameDef = clr::SafeAddRef(m_pIAssemblyName);
+ return S_OK;
+ }
+
+ //-----------------------------------------------------------------------------------------------------------------
+ HRESULT CLRPrivAssemblyBindResultWrapper::GetNextAssemblyModuleName(
+ /*in*/ DWORD dwNIndex,
+ __inout_ecount(*pdwCCModuleName) LPWSTR pwzModuleName,
+ /*in, out, annotation("__inout")*/ LPDWORD pdwCCModuleName)
+ {
+ STANDARD_BIND_CONTRACT;
+ _ASSERTE(!("E_NOTIMPL: " __FUNCTION__));
+ return E_NOTIMPL;
+ }
+
+ //-----------------------------------------------------------------------------------------------------------------
+ HRESULT CLRPrivAssemblyBindResultWrapper::GetAssemblyLocation(
+ /*out*/ IAssemblyLocation **ppIAssemblyLocation)
+ {
+ STANDARD_BIND_CONTRACT;
+ VALIDATE_ARG_RET(ppIAssemblyLocation != nullptr);
+ return this->QueryInterface(ppIAssemblyLocation);
+ }
+
+ //-----------------------------------------------------------------------------------------------------------------
+ HRESULT CLRPrivAssemblyBindResultWrapper::GetNativeImage(
+ /*out*/ IBindResult **ppIBindResultNI,
+ /*out*/ BOOL *pfIBindResultNIProbed)
+ {
+ LIMITED_METHOD_CONTRACT;
+
+ // m_bIBindResultNISet must always be read *before* m_pIBindResultNI
+ bool bIBindResultNISet = m_bIBindResultNISet;
+
+ if (pfIBindResultNIProbed != nullptr)
+ *pfIBindResultNIProbed = bIBindResultNISet;
+
+ if (bIBindResultNISet && ppIBindResultNI != nullptr)
+ *ppIBindResultNI = clr::SafeAddRef(m_pIBindResultNI);
+
+ return S_OK;
+ }
+
+ //-----------------------------------------------------------------------------------------------------------------
+ HRESULT CLRPrivAssemblyBindResultWrapper::SetNativeImage(
+ /*in*/ IBindResult *pIBindResultNI,
+ /*out*/ IBindResult **ppIBindResultNIFinal)
+ {
+ STANDARD_BIND_CONTRACT;
+ HRESULT hr = S_OK;
+
+ EX_TRY
+ {
+ // Native Binder needs S_FALSE returned if it loses the race.
+ hr = S_FALSE;
+
+ if (!m_bIBindResultNISet)
+ {
+ CrstHolder lock(&m_lock);
+ if (!m_bIBindResultNISet)
+ {
+ m_pIBindResultNI = clr::SafeAddRef(pIBindResultNI);
+ m_bIBindResultNISet = true;
+
+ // Won the race!
+ hr = S_OK;
+ }
+ }
+ }
+ EX_CATCH_HRESULT(hr);
+
+ if (ppIBindResultNIFinal != nullptr)
+ *ppIBindResultNIFinal = clr::SafeAddRef(m_pIBindResultNI);
+
+ return hr;
+ }
+
+ //-----------------------------------------------------------------------------------------------------------------
+ HRESULT CLRPrivAssemblyBindResultWrapper::IsEqual(
+ /*in*/ IUnknown *pIUnk)
+ {
+ STANDARD_BIND_CONTRACT;
+ HRESULT hr = S_OK;
+
+ VALIDATE_ARG_RET(pIUnk != nullptr);
+
+ ReleaseHolder<IBindResult> pIBindResult;
+
+ hr = pIUnk->QueryInterface(__uuidof(IBindResult), (void **)&pIBindResult);
+ if (SUCCEEDED(hr))
+ {
+ hr = pIBindResult == static_cast<IBindResult*>(this) ? S_OK : S_FALSE;
+ }
+ else if (hr == E_NOINTERFACE)
+ {
+ hr = S_FALSE;
+ }
+
+ return hr;
+ }
+
+ //-----------------------------------------------------------------------------------------------------------------
+ HRESULT CLRPrivAssemblyBindResultWrapper::GetNextAssemblyNameRef(
+ /*in*/ DWORD dwNIndex,
+ /*out*/ IAssemblyName **ppIAssemblyNameRef)
+ {
+ STANDARD_BIND_CONTRACT;
+ _ASSERTE(!("E_UNEXPECTED: " __FUNCTION__));
+ return E_UNEXPECTED;
+ }
+
+ //-----------------------------------------------------------------------------------------------------------------
+ HRESULT CLRPrivAssemblyBindResultWrapper::GetNextDependentAssembly(
+ /*in*/ DWORD dwNIndex,
+ /*out*/ IUnknown **ppIUnknownAssembly)
+ {
+ STANDARD_BIND_CONTRACT;
+ _ASSERTE(!("E_UNEXPECTED: " __FUNCTION__));
+ return E_UNEXPECTED;
+ }
+
+ //-----------------------------------------------------------------------------------------------------------------
+ HRESULT CLRPrivAssemblyBindResultWrapper::GetAssemblyLocationOfILImage(
+ /*out*/ IAssemblyLocation **ppAssemblyLocation)
+ {
+ LIMITED_METHOD_CONTRACT;
+ return this->QueryInterface(ppAssemblyLocation);
+ }
+
+ //-----------------------------------------------------------------------------------------------------------------
+ HRESULT CLRPrivAssemblyBindResultWrapper::GetILFingerprint(
+ /*out*/ IILFingerprint **ppFingerprint)
+ {
+ STANDARD_BIND_CONTRACT;
+ HRESULT hr = S_OK;
+
+ VALIDATE_ARG_RET(ppFingerprint != nullptr);
+
+ EX_TRY
+ {
+ *ppFingerprint = m_pIILFingerprint;
+ if (*ppFingerprint == nullptr)
+ {
+ ReleaseHolder<IILFingerprint> pFingerprint;
+ if (SUCCEEDED(hr = m_pILFingerprintFactory->GetILFingerprintForPath(GetILAssemblyPath(), &pFingerprint)))
+ {
+ if (InterlockedCompareExchangeT<IILFingerprint>(&m_pIILFingerprint, pFingerprint, nullptr) == nullptr)
+ {
+ pFingerprint.SuppressRelease();
+ }
+ }
+ }
+ *ppFingerprint = clr::SafeAddRef(m_pIILFingerprint);
+ }
+ EX_CATCH_HRESULT(hr);
+
+ return hr;
+ }
+
+ //-----------------------------------------------------------------------------------------------------------------
+ HRESULT CLRPrivAssemblyBindResultWrapper::GetSourceILTimestamp(
+ /*out*/ FILETIME* pFileTime)
+ {
+ STANDARD_BIND_CONTRACT;
+ HRESULT hr = S_OK;
+
+ VALIDATE_ARG_RET(pFileTime != nullptr);
+
+ EX_TRY
+ {
+ WIN32_FILE_ATTRIBUTE_DATA wfd;
+ if (!WszGetFileAttributesEx(GetILAssemblyPath(), GetFileExInfoStandard, &wfd))
+ ThrowLastError();
+ *pFileTime = wfd.ftLastWriteTime;
+ }
+ EX_CATCH_HRESULT(hr);
+
+ return hr;
+ }
+
+ //-----------------------------------------------------------------------------------------------------------------
+ HRESULT CLRPrivAssemblyBindResultWrapper::GetSourceILSize(
+ /*out*/ DWORD* pSize)
+ {
+ STANDARD_BIND_CONTRACT;
+ HRESULT hr = S_OK;
+
+ VALIDATE_ARG_RET(pSize != nullptr);
+
+ EX_TRY
+ {
+ WIN32_FILE_ATTRIBUTE_DATA wfd;
+ if (!WszGetFileAttributesEx(GetILAssemblyPath(), GetFileExInfoStandard, &wfd))
+ ThrowLastError();
+ if(wfd.nFileSizeHigh != 0)
+ ThrowHR(COR_E_OVERFLOW);
+ *pSize = wfd.nFileSizeLow;
+ }
+ EX_CATCH_HRESULT(hr);
+
+ return hr;
+ }
+
+ //-----------------------------------------------------------------------------------------------------------------
+ HRESULT CLRPrivAssemblyBindResultWrapper::GetNIInfo(
+ /*out*/ INativeImageInstallInfo** pInfo)
+ {
+ STANDARD_BIND_CONTRACT;
+ _ASSERTE(!("E_UNEXPECTED: " __FUNCTION__));
+ return E_UNEXPECTED;
+ }
+
+ //-----------------------------------------------------------------------------------------------------------------
+ HRESULT CLRPrivAssemblyBindResultWrapper::GetFlags(
+ /*out*/ DWORD * pdwFlags)
+ {
+ STANDARD_BIND_CONTRACT;
+ PRECONDITION(CheckPointer(pdwFlags));
+ if (pdwFlags == nullptr)
+ {
+ return E_POINTER;
+ }
+
+ // Currently, no effort is made to open assemblies and build a full IAssemblyName - this currently
+ // only contains the simple name. Since AppX packages cannot be in-place updated we can be confident
+ // that the binding environment will remain unchanged between NGEN and runtime. As such, return the
+ // flag to indicate that the native image binder should skip self assembly definition validation.
+ *pdwFlags = IBindResultFlag_AssemblyNameDefIncomplete;
+
+ return S_OK;
+ }
+
+ //-----------------------------------------------------------------------------------------------------------------
+ HRESULT CLRPrivAssemblyBindResultWrapper::GetLocationType(
+ /*out*/DWORD *pdwLocationType)
+ {
+ LIMITED_METHOD_CONTRACT;
+ VALIDATE_ARG_RET(pdwLocationType != nullptr);
+
+ if (pdwLocationType == nullptr)
+ return E_INVALIDARG;
+ *pdwLocationType = ASSEMBLY_LOCATION_PATH;
+ return S_OK;
+ }
+
+ //-----------------------------------------------------------------------------------------------------------------
+ HRESULT CLRPrivAssemblyBindResultWrapper::GetPath(
+ __inout_ecount(*pdwccAssemblyPath) LPWSTR pwzAssemblyPath,
+ /*in, annotation("__inout")*/ LPDWORD pdwccAssemblyPath)
+ {
+ STANDARD_BIND_CONTRACT;
+ HRESULT hr = S_OK;
+
+ VALIDATE_ARG_RET(pdwccAssemblyPath != nullptr);
+
+ EX_TRY
+ {
+ DWORD cchILAssemblyPath = static_cast<DWORD>(wcslen(GetILAssemblyPath())) + 1;
+ if (pwzAssemblyPath != nullptr && cchILAssemblyPath <= *pdwccAssemblyPath)
+ {
+ IfFailThrow(StringCchCopy(pwzAssemblyPath, *pdwccAssemblyPath, GetILAssemblyPath()));
+ *pdwccAssemblyPath = cchILAssemblyPath;
+ hr = S_OK;
+ }
+ else
+ {
+ *pdwccAssemblyPath = cchILAssemblyPath;
+ hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
+ }
+ }
+ EX_CATCH_HRESULT(hr);
+
+ return hr;
+ }
+
+ //-----------------------------------------------------------------------------------------------------------------
+ HRESULT CLRPrivAssemblyBindResultWrapper::GetHostID(
+ /*out*/ UINT64 *puiHostID)
+ {
+ STANDARD_BIND_CONTRACT;
+ _ASSERTE(!("E_UNEXPECTED: " __FUNCTION__));
+ return E_UNEXPECTED;
+ }
+#endif //FEATURE_FUSION
+
+ //-----------------------------------------------------------------------------------------------------------------
+ HRESULT VerifyBind(
+ IAssemblyName *pRefAssemblyName,
+ ICLRPrivAssemblyInfo *pDefAssemblyInfo)
+ {
+ STANDARD_BIND_CONTRACT;
+
+ HRESULT hr = S_OK;
+ VALIDATE_PTR_RET(pRefAssemblyName);
+ VALIDATE_PTR_RET(pDefAssemblyInfo);
+
+ AssemblyIdentity refIdentity;
+ IfFailRet(refIdentity.Initialize(pRefAssemblyName));
+
+ AssemblyIdentity defIdentity;
+ IfFailRet(defIdentity.Initialize(pDefAssemblyInfo));
+
+ return VerifyBind(refIdentity, defIdentity);
+ }
+
+ //-----------------------------------------------------------------------------------------------------------------
+ HRESULT VerifyBind(
+ CLRPrivBinderUtil::AssemblyIdentity const & refIdentity,
+ CLRPrivBinderUtil::AssemblyIdentity const & defIdentity)
+ {
+ LIMITED_METHOD_CONTRACT;
+
+ //
+ // Compare versions. Success conditions are the same as those in Silverlight:
+ // 1. Reference identity has no version.
+ // 2. Both identities have versions, and ref.version <= def.version.
+ //
+ // Since the default value of AssemblyVersion is 0.0.0.0, then if the
+ // ref has no value set then the comparison will use 0.0.0.0, which will
+ // always compare as true to the version contained in the def.
+ //
+
+ if (defIdentity.Version < refIdentity.Version)
+ { // Bound assembly has a lower version number than the reference.
+ return CLR_E_BIND_ASSEMBLY_VERSION_TOO_LOW;
+ }
+
+ //
+ // Compare public key tokens. Success conditions are:
+ // 1. Reference identity has no PKT.
+ // 2. Both identities have identical PKT values.
+ //
+
+ if (refIdentity.KeyToken.GetSize() != 0 && // Ref without PKT always passes.
+ refIdentity.KeyToken != defIdentity.KeyToken) // Otherwise Def must have matching PKT.
+ {
+ return CLR_E_BIND_ASSEMBLY_PUBLIC_KEY_MISMATCH;
+ }
+
+ return S_OK;
+ }
+
+ //---------------------------------------------------------------------------------------------
+ CLRPrivResourcePathImpl::CLRPrivResourcePathImpl(LPCWSTR wzPath)
+ : m_wzPath(CopyStringThrowing(wzPath))
+ { STANDARD_VM_CONTRACT; }
+
+ //---------------------------------------------------------------------------------------------
+ HRESULT CLRPrivResourcePathImpl::GetPath(
+ DWORD cchBuffer,
+ LPDWORD pcchBuffer,
+ __inout_ecount_part(cchBuffer, *pcchBuffer) LPWSTR wzBuffer)
+ {
+ LIMITED_METHOD_CONTRACT;
+ HRESULT hr = S_OK;
+
+ if (pcchBuffer == nullptr)
+ IfFailRet(E_INVALIDARG);
+
+ *pcchBuffer = (DWORD)wcslen(m_wzPath);
+
+ if (wzBuffer != nullptr)
+ {
+ if (FAILED(StringCchCopy(wzBuffer, cchBuffer, m_wzPath)))
+ IfFailRet(HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER));
+ }
+
+ return hr;
+ }
+
+ //---------------------------------------------------------------------------------------------
+ CLRPrivResourceStreamImpl::CLRPrivResourceStreamImpl(IStream * pStream)
+ : m_pStream(pStream)
+ {
+ LIMITED_METHOD_CONTRACT;
+ pStream->AddRef();
+ }
+
+ //---------------------------------------------------------------------------------------------
+ HRESULT CLRPrivResourceStreamImpl::GetStream(
+ REFIID riid,
+ LPVOID * ppvStream)
+ {
+ LIMITED_METHOD_CONTRACT;
+ return m_pStream->QueryInterface(riid, ppvStream);
+ }
+
+ //---------------------------------------------------------------------------------------------
+ HRESULT AssemblyVersion::Initialize(
+ IAssemblyName * pAssemblyName)
+ {
+ WRAPPER_NO_CONTRACT;
+ HRESULT hr = pAssemblyName->GetVersion(&dwMajorMinor, &dwBuildRevision);
+ if (hr == FUSION_E_INVALID_NAME)
+ {
+ hr = S_FALSE;
+ }
+ return hr;
+ }
+
+ //---------------------------------------------------------------------------------------------
+ HRESULT AssemblyVersion::Initialize(
+ ICLRPrivAssemblyInfo * pAssemblyInfo)
+ {
+ WRAPPER_NO_CONTRACT;
+ return pAssemblyInfo->GetAssemblyVersion(&wMajor, &wMinor, &wBuild, &wRevision);
+ }
+
+ //---------------------------------------------------------------------------------------------
+ HRESULT PublicKey::Initialize(
+ ICLRPrivAssemblyInfo * pAssemblyInfo)
+ {
+ LIMITED_METHOD_CONTRACT;
+ HRESULT hr = S_OK;
+
+ VALIDATE_PTR_RET(pAssemblyInfo);
+
+ Uninitialize();
+
+ DWORD cbKeyDef = 0;
+ hr = pAssemblyInfo->GetAssemblyPublicKey(cbKeyDef, &cbKeyDef, nullptr);
+
+ if (hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER))
+ {
+ if (cbKeyDef != 0)
+ {
+ NewArrayHolder<BYTE> pbKeyDef = new (nothrow) BYTE[cbKeyDef];
+ IfNullRet(pbKeyDef);
+
+ if (SUCCEEDED(hr = pAssemblyInfo->GetAssemblyPublicKey(cbKeyDef, &cbKeyDef, pbKeyDef)))
+ {
+ m_key = pbKeyDef.Extract();
+ m_key_owned = true;
+ m_size = cbKeyDef;
+ }
+ }
+ }
+
+ return hr;
+ }
+
+ //---------------------------------------------------------------------------------------------
+ HRESULT PublicKeyToken::Initialize(
+ BYTE * pbKeyToken,
+ DWORD cbKeyToken)
+ {
+ LIMITED_METHOD_CONTRACT;
+
+ VALIDATE_CONDITION((pbKeyToken == nullptr) == (cbKeyToken == 0), return E_INVALIDARG);
+ VALIDATE_ARG_RET(cbKeyToken == 0 || cbKeyToken == PUBLIC_KEY_TOKEN_LEN1);
+
+ m_cbKeyToken = cbKeyToken;
+
+ if (pbKeyToken != nullptr)
+ {
+ memcpy(m_rbKeyToken, pbKeyToken, PUBLIC_KEY_TOKEN_LEN1);
+ }
+ else
+ {
+ memset(m_rbKeyToken, 0, PUBLIC_KEY_TOKEN_LEN1);
+ }
+
+ return S_OK;
+ }
+
+ //---------------------------------------------------------------------------------------------
+ HRESULT PublicKeyToken::Initialize(
+ PublicKey const & pk)
+ {
+ LIMITED_METHOD_CONTRACT;
+
+ StrongNameBufferHolder<BYTE> pbKeyToken;
+ DWORD cbKeyToken;
+
+ if (!StrongNameTokenFromPublicKey(const_cast<BYTE*>(pk.GetKey()), pk.GetSize(), &pbKeyToken, &cbKeyToken))
+ {
+ return static_cast<HRESULT>(StrongNameErrorInfo());
+ }
+
+ return Initialize(pbKeyToken, cbKeyToken);
+ }
+
+ //=====================================================================================================================
+ HRESULT PublicKeyToken::Initialize(
+ IAssemblyName * pName)
+ {
+ LIMITED_METHOD_CONTRACT;
+
+ HRESULT hr = S_OK;
+
+ DWORD cbKeyToken = sizeof(m_rbKeyToken);
+ hr = pName->GetProperty(ASM_NAME_PUBLIC_KEY_TOKEN, m_rbKeyToken, &cbKeyToken);
+ if (SUCCEEDED(hr))
+ {
+ m_cbKeyToken = cbKeyToken;
+ }
+
+ if (hr == FUSION_E_INVALID_NAME)
+ {
+ hr = S_FALSE;
+ }
+
+ return hr;
+ }
+
+ //=====================================================================================================================
+ HRESULT PublicKeyToken::Initialize(
+ ICLRPrivAssemblyInfo * pName)
+ {
+ LIMITED_METHOD_CONTRACT;
+
+ HRESULT hr = S_OK;
+
+ PublicKey pk;
+ IfFailRet(pk.Initialize(pName));
+
+ if (hr == S_OK) // Can return S_FALSE if no public key/token defined.
+ {
+ hr = Initialize(pk);
+ }
+
+ return hr;
+ }
+
+ //=====================================================================================================================
+ bool operator==(
+ PublicKeyToken const & lhs,
+ PublicKeyToken const & rhs)
+ {
+ LIMITED_METHOD_CONTRACT;
+
+ // Sizes must match
+ if (lhs.GetSize() != rhs.GetSize())
+ {
+ return false;
+ }
+
+ // Empty PKT values are considered to be equal.
+ if (lhs.GetSize() == 0)
+ {
+ return true;
+ }
+
+ // Compare values.
+ return memcmp(lhs.GetToken(), rhs.GetToken(), lhs.GetSize()) == 0;
+ }
+
+ //=====================================================================================================================
+ HRESULT AssemblyIdentity::Initialize(
+ LPCWSTR wzName)
+ {
+ LIMITED_METHOD_CONTRACT;
+ return StringCchCopy(Name, sizeof(Name) / sizeof(Name[0]), wzName);
+ }
+
+ //=====================================================================================================================
+ HRESULT AssemblyIdentity::Initialize(
+ ICLRPrivAssemblyInfo * pAssemblyInfo)
+ {
+ STANDARD_BIND_CONTRACT;
+ HRESULT hr = S_OK;
+
+ DWORD cchName = sizeof(Name) / sizeof(Name[0]);
+ IfFailRet(pAssemblyInfo->GetAssemblyName(cchName, &cchName, Name));
+ IfFailRet(Version.Initialize(pAssemblyInfo));
+ IfFailRet(KeyToken.Initialize(pAssemblyInfo));
+
+ return hr;
+ }
+
+ //=====================================================================================================================
+ HRESULT AssemblyIdentity::Initialize(
+ IAssemblyName * pAssemblyName)
+ {
+ STANDARD_BIND_CONTRACT;
+ HRESULT hr = S_OK;
+
+ DWORD cchName = sizeof(Name) / sizeof(Name[0]);
+ IfFailRet(pAssemblyName->GetName(&cchName, Name));
+ IfFailRet(Version.Initialize(pAssemblyName));
+ IfFailRet(KeyToken.Initialize(pAssemblyName));
+
+ return hr;
+ }
+
+#ifdef FEATURE_FUSION
+ //=====================================================================================================================
+ HRESULT AssemblyIdentity::Initialize(
+ AssemblySpec * pSpec)
+ {
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ FORBID_FAULT;
+ MODE_ANY;
+ CAN_TAKE_LOCK;
+ }
+ CONTRACTL_END
+
+ HRESULT hr = S_OK;
+
+ if (0 == WszMultiByteToWideChar(
+ CP_UTF8, 0 /*flags*/, pSpec->GetName(), -1, Name, (int) (sizeof(Name) / sizeof(Name[0]))))
+ {
+ return HRESULT_FROM_GetLastError();
+ }
+
+ AssemblyMetaDataInternal * pAMDI = pSpec->GetContext();
+ if (pAMDI != nullptr)
+ {
+ Version.wMajor = pAMDI->usMajorVersion;
+ Version.wMinor = pAMDI->usMinorVersion;
+ Version.wBuild = pAMDI->usBuildNumber;
+ Version.wRevision = pAMDI->usRevisionNumber;
+ }
+
+ if (pSpec->HasPublicKeyToken())
+ {
+ PBYTE pbKey;
+ DWORD cbKey;
+ pSpec->GetPublicKeyToken(&pbKey, &cbKey);
+ IfFailRet(KeyToken.Initialize(pbKey, cbKey));
+ }
+
+ return hr;
+ }
+#endif
+
+
+ //=====================================================================================================================
+ // Destroys list of strings (code:WStringList).
+ void
+ WStringList_Delete(
+ WStringList * pList)
+ {
+ LIMITED_METHOD_CONTRACT;
+
+ if (pList != nullptr)
+ {
+ for (WStringListElem * pElem = pList->RemoveHead(); pElem != nullptr; pElem = pList->RemoveHead())
+ {
+ // Delete the string
+ delete [] pElem->GetValue();
+ delete pElem;
+ }
+
+ delete pList;
+ }
+ }
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+///// ----------------------------- Direct calls to VM -------------------------------------------
+////////////////////////////////////////////////////////////////////////////////////////////////////
+#if defined(FEATURE_APPX_BINDER)
+ ICLRPrivAssembly* RaiseAssemblyResolveEvent(IAssemblyName *pAssemblyName, ICLRPrivAssembly* pRequestingAssembly)
+ {
+ CONTRACT(ICLRPrivAssembly*)
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_ANY;
+ PRECONDITION(AppX::IsAppXProcess());
+ PRECONDITION(AppDomain::GetCurrentDomain()->IsDefaultDomain());
+ POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
+ INJECT_FAULT(COMPlusThrowOM(););
+ }
+ CONTRACT_END;
+
+ BinderMethodID methodId;
+
+ methodId = METHOD__APP_DOMAIN__ON_ASSEMBLY_RESOLVE; // post-bind execution event (the classic V1.0 event)
+
+ // Elevate threads allowed loading level. This allows the host to load an assembly even in a restricted
+ // condition. Note, however, that this exposes us to possible recursion failures, if the host tries to
+ // load the assemblies currently being loaded. (Such cases would then throw an exception.)
+
+ OVERRIDE_LOAD_LEVEL_LIMIT(FILE_ACTIVE);
+ OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOADED);
+
+ DomainAssembly* pDomainAssembly = AppDomain::GetCurrentDomain()->FindAssembly(pRequestingAssembly);
+
+ GCX_COOP();
+
+ Assembly* pAssembly = NULL;
+
+ struct _gc {
+ OBJECTREF AppDomainRef;
+ OBJECTREF AssemblyRef;
+ STRINGREF str;
+ } gc;
+ ZeroMemory(&gc, sizeof(gc));
+
+ SString ssAssemblyName;
+ FusionBind::GetAssemblyNameDisplayName(pAssemblyName, ssAssemblyName);
+
+ GCPROTECT_BEGIN(gc);
+ if ((gc.AppDomainRef = GetAppDomain()->GetRawExposedObject()) != NULL)
+ {
+ gc.AssemblyRef = pDomainAssembly->GetExposedAssemblyObject();
+
+ MethodDescCallSite onAssemblyResolve(methodId, &gc.AppDomainRef);
+
+ gc.str = StringObject::NewString(ssAssemblyName.GetUnicode());
+ ARG_SLOT args[3] = {
+ ObjToArgSlot(gc.AppDomainRef),
+ ObjToArgSlot(gc.AssemblyRef),
+ ObjToArgSlot(gc.str)
+ };
+ ASSEMBLYREF ResultingAssemblyRef = (ASSEMBLYREF) onAssemblyResolve.Call_RetOBJECTREF(args);
+ if (ResultingAssemblyRef != NULL)
+ {
+ pAssembly = ResultingAssemblyRef->GetAssembly();
+ }
+ }
+ GCPROTECT_END();
+
+ if (pAssembly != NULL)
+ {
+ if (pAssembly->IsIntrospectionOnly())
+ {
+ // Cannot return an introspection assembly from an execution callback or vice-versa
+ COMPlusThrow(kFileLoadException, IDS_CLASSLOAD_ASSEMBLY_RESOLVE_RETURNED_INTROSPECTION );
+ }
+ if (pAssembly->IsCollectible())
+ {
+ COMPlusThrow(kNotSupportedException, W("NotSupported_CollectibleAssemblyResolve"));
+ }
+
+ // Check that the public key token matches the one specified in the spec
+ // MatchPublicKeys throws as appropriate.
+
+ StackScratchBuffer ssBuffer;
+ AssemblySpec spec;
+ IfFailThrow(spec.Init(ssAssemblyName.GetUTF8(ssBuffer)));
+ spec.MatchPublicKeys(pAssembly);
+
+ }
+
+ if (pAssembly == nullptr)
+ ThrowHR(COR_E_FILENOTFOUND);
+
+ RETURN pAssembly->GetManifestFile()->GetHostAssembly();
+ }
+
+ BOOL CompareHostBinderSpecs(AssemblySpec * a1, AssemblySpec * a2)
+ {
+ WRAPPER_NO_CONTRACT;
+ return a1->CompareEx(a2, AssemblySpec::ASC_Default);
+ }
+#endif // FEATURE_APPX
+} // namespace CLRPrivBinderUtil