summaryrefslogtreecommitdiff
path: root/src/vm/clrprivbinderappx.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/vm/clrprivbinderappx.cpp')
-rw-r--r--src/vm/clrprivbinderappx.cpp1057
1 files changed, 0 insertions, 1057 deletions
diff --git a/src/vm/clrprivbinderappx.cpp b/src/vm/clrprivbinderappx.cpp
deleted file mode 100644
index b55ece4556..0000000000
--- a/src/vm/clrprivbinderappx.cpp
+++ /dev/null
@@ -1,1057 +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
-#include "assemblyusagelogmanager.h"
-
-//=====================================================================================================================
-#include "clrprivbinderappx.h"
-//CLRPrivBinderAppX * CLRPrivBinderAppX::s_pSingleton = nullptr;
-SPTR_IMPL_INIT(CLRPrivBinderAppX, CLRPrivBinderAppX, s_pSingleton, nullptr);
-
-#ifndef DACCESS_COMPILE
-//=====================================================================================================================
-#include "appxutil.h"
-#include "clrprivbinderutil.h"
-#include "fusionlogging.h"
-#include "clrprivtypecachewinrt.h"
-#include "fusionp.h"
-
-using namespace CLRPrivBinderUtil;
-
-//=====================================================================================================================
-CLRPrivBinderAppX::CLRPrivBinderAppX(LPCWSTR * rgwzAltPath, UINT cAltPaths)
- : m_MapReadLock(CrstCLRPrivBinderMaps,
- static_cast<CrstFlags>(CRST_DEBUG_ONLY_CHECK_FORBID_SUSPEND_THREAD |
- CRST_GC_NOTRIGGER_WHEN_TAKEN |
- CRST_DEBUGGER_THREAD |
- // FindAssemblyBySpec complicates matters, which needs to take the m_MapReadLock.
- // But FindAssemblyBySpec cannot switch to preemptive mode, as that would trigger
- // a GC. Since this is a leaf lock, and since it does not make any calls out of
- // the runtime, this lock can be taken in cooperative mode if the locked scope is
- // also marked as ForbidSuspend (since FindAssemblyBySpec can be called by
- // the debugger and the profiler). TODO: it would be nice to be able to specify
- // this flag for just the specific places where it is necessary rather than for
- // the lock as a whole.
- CRST_UNSAFE_ANYMODE)),
- m_MapWriteLock(CrstCLRPrivBinderMapsAdd, CRST_DEFAULT),
- m_cAltPaths(cAltPaths),
- m_fCanUseNativeImages(TRUE),
- m_pParentBinder(nullptr),
- m_pFusionBinder(nullptr),
- m_pWinRTBinder(nullptr),
-
- // Note: the first CLRPrivBinderAppX object is created prior to runtime startup, so this code cannot call
- // AppX::IsAppXDesignMode; however, FindAssemblyBySpec cannot call IsAppXDesignMode either because that would
- // cause a GC_TRIGGERS violation for the GetAssemblyIfLoaded scenario. However this doesn't matter because
- // the assembly map will be empty until at least the first call to BindAssemblyByName is made, at which point
- // a call to IsAppXDesignMode can be made. Thus, we default to the most conversative setting and overwrite this
- // value in BindAssemblyByName.
- m_fusionBindingScope(CLRPrivBinderFusion::kBindingScope_FrameworkSubset)
-{
- STANDARD_VM_CONTRACT;
-
- // Copy altpaths
- if (cAltPaths > 0)
- {
- m_rgAltPathsHolder = new NewArrayHolder<WCHAR>[cAltPaths];
- m_rgAltPaths = new WCHAR *[cAltPaths];
-
- for (UINT iAltPath = 0; iAltPath < cAltPaths; iAltPath++)
- {
- size_t cchAltPath = wcslen(rgwzAltPath[iAltPath]);
- m_rgAltPathsHolder[iAltPath] = m_rgAltPaths[iAltPath] = new WCHAR[cchAltPath + 1];
- wcscpy_s(m_rgAltPaths[iAltPath], cchAltPath + 1, rgwzAltPath[iAltPath]);
- }
- }
-
-#ifdef FEATURE_FUSION
- IfFailThrow(RuntimeCreateCachingILFingerprintFactory(&m_pFingerprintFactory));
-#endif
-}
-
-//=====================================================================================================================
-CLRPrivBinderFusion::BindingScope CLRPrivBinderAppX::GetFusionBindingScope()
-{
- WRAPPER_NO_CONTRACT;
-
- m_fusionBindingScope = (AppX::IsAppXDesignMode() || (m_pParentBinder != nullptr))
- ? CLRPrivBinderFusion::kBindingScope_FrameworkAll
- : CLRPrivBinderFusion::kBindingScope_FrameworkSubset;
-
- return m_fusionBindingScope;
-}
-
-//=====================================================================================================================
-CLRPrivBinderAppX::~CLRPrivBinderAppX()
-{
- WRAPPER_NO_CONTRACT;
-
- m_NameToAssemblyMap.RemoveAll();
- AssemblyUsageLogManager::UnRegisterBinderFromUsageLog((UINT_PTR)this);
-
- clr::SafeRelease(m_pWinRTBinder);
-}
-
-//=====================================================================================================================
-CLRPrivBinderAppX *
-CLRPrivBinderAppX::GetOrCreateBinder()
-{
- STANDARD_VM_CONTRACT;
- HRESULT hr = S_OK;
-
- if (s_pSingleton == nullptr)
- {
- ReleaseHolder<IAssemblyUsageLog> pNewUsageLog;
- IfFailThrow(AssemblyUsageLogManager::GetUsageLogForContext(W("App"), AppX::GetHeadPackageMoniker(), &pNewUsageLog));
-
- ReleaseHolder<CLRPrivBinderAppX> pBinder;
- pBinder = clr::SafeAddRef(new CLRPrivBinderAppX(nullptr, 0));
-
- pBinder->m_pFusionBinder = clr::SafeAddRef(new CLRPrivBinderFusion());
-
- CLRPrivTypeCacheWinRT * pWinRtTypeCache = CLRPrivTypeCacheWinRT::GetOrCreateTypeCache();
- pBinder->m_pWinRTBinder = clr::SafeAddRef(new CLRPrivBinderWinRT(
- pBinder,
- pWinRtTypeCache,
- nullptr, // rgwzAltPath
- 0, // cAltPaths
- CLRPrivBinderWinRT::NamespaceResolutionKind_WindowsAPI,
- TRUE // fCanUseNativeImages
- ));
-
- if (InterlockedCompareExchangeT<decltype(s_pSingleton)>(&s_pSingleton, pBinder, nullptr) == nullptr)
- pBinder.SuppressRelease();
-
- // Register binder with usagelog infrastructure.
- UINT_PTR binderId;
- IfFailThrow(pBinder->GetBinderID(&binderId));
- IfFailThrow(AssemblyUsageLogManager::RegisterBinderWithUsageLog(binderId, pNewUsageLog));
-
- // Create and register WinRT usage log
- ReleaseHolder<IAssemblyUsageLog> pNewWinRTUsageLog;
- IfFailThrow(AssemblyUsageLogManager::GetUsageLogForContext(W("WinRT"), AppX::GetHeadPackageMoniker(), &pNewWinRTUsageLog));
-
- UINT_PTR winRTBinderId;
- IfFailThrow(pBinder->m_pWinRTBinder->GetBinderID(&winRTBinderId));
- IfFailThrow(AssemblyUsageLogManager::RegisterBinderWithUsageLog(winRTBinderId, pNewWinRTUsageLog));
- }
-
- return s_pSingleton;
-}
-
-//=====================================================================================================================
-// Used only for designer binding context
-CLRPrivBinderAppX * CLRPrivBinderAppX::CreateParentedBinder(
- ICLRPrivBinder * pParentBinder,
- CLRPrivTypeCacheWinRT * pWinRtTypeCache,
- LPCWSTR * rgwzAltPath,
- UINT cAltPaths,
- BOOL fCanUseNativeImages)
-{
- STANDARD_VM_CONTRACT;
- HRESULT hr = S_OK;
-
- ReleaseHolder<CLRPrivBinderAppX> pBinder;
- pBinder = clr::SafeAddRef(new CLRPrivBinderAppX(rgwzAltPath, cAltPaths));
-
- pBinder->m_pParentBinder = clr::SafeAddRef(pParentBinder);
- pBinder->m_fCanUseNativeImages = fCanUseNativeImages;
-
- // We want to share FusionBinder with pParentBinder (which bubbles up through the chain of binders to the global AppXBinder code:s_pSingleton)
- // Ideally we would get the FusionBinder from pParentBinder (via casting to a new interface). It is much easier just to fetch it from
- // the global AppX binder directly
- pBinder->m_pFusionBinder = clr::SafeAddRef(s_pSingleton->GetFusionBinder());
-
- if (cAltPaths > 0)
- {
- pBinder->m_pWinRTBinder = clr::SafeAddRef(new CLRPrivBinderWinRT(
- pBinder,
- pWinRtTypeCache,
- rgwzAltPath,
- cAltPaths,
- CLRPrivBinderWinRT::NamespaceResolutionKind_WindowsAPI,
- fCanUseNativeImages));
- }
-
- pBinder.SuppressRelease();
- return pBinder;
-}
-
-//=====================================================================================================================
-HRESULT CLRPrivBinderAppX::BindAppXAssemblyByNameWorker(
- IAssemblyName * pIAssemblyName,
- DWORD dwAppXBindFlags,
- CLRPrivAssemblyAppX ** ppAssembly)
-{
- STANDARD_VM_CONTRACT;
- HRESULT hr = S_OK;
-
- fusion::logging::StatusScope logStatus(0, ID_FUSLOG_BINDING_STATUS_IMMERSIVE, &hr);
-
- VALIDATE_ARG_RET(pIAssemblyName != nullptr);
- VALIDATE_ARG_RET((dwAppXBindFlags & ABF_BindIL) == ABF_BindIL);
- VALIDATE_ARG_RET(ppAssembly != nullptr);
-
- DWORD dwContentType = AssemblyContentType_Default;
- IfFailRet(hr = fusion::util::GetProperty(pIAssemblyName, ASM_NAME_CONTENT_TYPE, &dwContentType));
- if ((hr == S_OK) && (dwContentType != AssemblyContentType_Default))
- {
- IfFailRet(CLR_E_BIND_UNRECOGNIZED_IDENTITY_FORMAT);
- }
-
- ReleaseHolder<CLRPrivAssemblyAppX> pAssembly;
-
- // Get the simple name.
- WCHAR wzSimpleName[_MAX_PATH];
- DWORD cchSimpleName = _MAX_PATH;
- IfFailRet(pIAssemblyName->GetName(&cchSimpleName, wzSimpleName));
-
- { // Look for previous successful bind. Host callouts are now forbidden.
- ForbidSuspendThreadCrstHolder lock(&m_MapReadLock);
- pAssembly = clr::SafeAddRef(m_NameToAssemblyMap.Lookup(wzSimpleName));
- }
-
- if (pAssembly == nullptr)
- {
- ReleaseHolder<ICLRPrivResource> pResourceIL;
- ReleaseHolder<ICLRPrivResource> pResourceNI;
-
- // Create assembly identity using the simple name. For successful binds this will be updated
- // with the full assembly identity in the VerifyBind callback.
- NewHolder<AssemblyIdentity> pIdentity = new AssemblyIdentity();
- IfFailRet(pIdentity->Initialize(wzSimpleName));
-
- //
- // Check the head package first to see if this matches an EXE, then check
- // all packages to see if this matches a DLL.
- //
- WCHAR wzFilePath[_MAX_PATH];
- {
- hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
-
- if (FAILED(hr))
- {
- // Create simple name with .EXE extension
- WCHAR wzSimpleFileName[_MAX_PATH];
- wcscpy_s(wzSimpleFileName, NumItems(wzSimpleFileName), wzSimpleName);
- wcscat_s(wzSimpleFileName, NumItems(wzSimpleFileName), W(".EXE"));
-
- // Search for the file using AppX::FileFileInCurrentPackage helper.
- UINT32 cchFilePath = NumItems(wzFilePath);
- hr = AppX::FindFileInCurrentPackage(
- wzSimpleFileName,
- &cchFilePath,
- wzFilePath,
- PACKAGE_FILTER_CLR_DEFAULT,
- (PCWSTR *)(void *)m_rgAltPaths,
- m_cAltPaths,
- m_pParentBinder != NULL ? AppX::FindFindInPackageFlags_SkipCurrentPackageGraph : AppX::FindFindInPackageFlags_None);
- }
-
- if (FAILED(hr))
- {
- // Create simple name with .DLL extension
- WCHAR wzSimpleFileName[_MAX_PATH];
- wcscpy_s(wzSimpleFileName, NumItems(wzSimpleFileName), wzSimpleName);
- wcscat_s(wzSimpleFileName, NumItems(wzSimpleFileName), W(".DLL"));
-
- // Search for the file using AppX::FileFileInCurrentPackage helper
- UINT32 cchFilePath = NumItems(wzFilePath);
- hr = AppX::FindFileInCurrentPackage(
- wzSimpleFileName,
- &cchFilePath,
- wzFilePath,
- PACKAGE_FILTER_CLR_DEFAULT,
- (PCWSTR *)(void *)m_rgAltPaths,
- m_cAltPaths,
- m_pParentBinder != NULL ? AppX::FindFindInPackageFlags_SkipCurrentPackageGraph : AppX::FindFindInPackageFlags_None);
- }
-
- if (SUCCEEDED(hr))
- {
- fusion::logging::LogMessage(0, ID_FUSLOG_BINDING_STATUS_FOUND, wzFilePath);
- }
- else
- {
- // Cache the bind failure result before returning. Careful not to overwrite the bind result with the cache insertion result.
- HRESULT hrResult = hr;
- IfFailRet(CacheBindResult(pIdentity, hr));
- if (hr == S_OK)
- { // Cache now owns identity object lifetime.
- pIdentity.SuppressRelease();
- }
- hr = hrResult;
- }
- IfFailRet(hr);
- }
-
- NewHolder<CLRPrivResourcePathImpl> pResourcePath = new CLRPrivResourcePathImpl(wzFilePath);
- IfFailRet(pResourcePath->QueryInterface(__uuidof(ICLRPrivResource), (LPVOID*)&pResourceIL));
- pResourcePath.SuppressRelease();
-
- // Create an IBindResult and provide it to the new CLRPrivAssemblyAppX object.
- ReleaseHolder<IBindResult> pIBindResult = ToInterface<IBindResult>(
- new CLRPrivAssemblyBindResultWrapper(pIAssemblyName, wzFilePath, m_pFingerprintFactory));
-
-
- // Create the new CLRPrivAssemblyAppX object.
- NewHolder<CLRPrivAssemblyAppX> pAssemblyObj =
- new CLRPrivAssemblyAppX(pIdentity, this, pResourceIL, pIBindResult);
-
- //
- // Check cache. If someone beat us then use it instead; otherwise add new ICLRPrivAssembly.
- //
- do
- {
- // Because the read lock must be taken within a ForbidSuspend region, use AddInPhases.
- if (m_NameToAssemblyMap.CheckAddInPhases<ForbidSuspendThreadCrstHolder, CrstHolder>(
- pAssemblyObj, m_MapReadLock, m_MapWriteLock, pAssemblyObj.GetValue()))
- {
- { // Careful not to allow the cache insertion result to overwrite the bind result.
- HRESULT hrResult = hr;
- IfFailRet(CacheBindResult(pIdentity, hr));
- if (hr == S_OK)
- { // Cache now owns identity object lifetime, but ~CLRPrivBinderAssembly
- // can also remove the identity from the cache prior to cache deletion.
- pIdentity.SuppressRelease();
- }
- hr = hrResult;
- }
-
- pAssembly = pAssemblyObj.Extract();
- }
- else
- {
- ForbidSuspendThreadCrstHolder lock(&m_MapReadLock);
- pAssembly = clr::SafeAddRef(m_NameToAssemblyMap.Lookup(wzSimpleName));
- }
- }
- while (pAssembly == nullptr); // Keep looping until we find the existing one, or add a new one
- }
-
- _ASSERTE(pAssembly != nullptr);
-
- if (((dwAppXBindFlags & ABF_BindNI) == ABF_BindNI) &&
- m_fCanUseNativeImages)
- {
- //
- // Look to see if there's a native image available.
- //
-
- // Fire BindingNgenPhaseStart ETW event if enabled.
- {
- InlineSString<128> ssAssemblyName;
- FireEtwBindingNgenPhaseStart(
- (AppDomain::GetCurrentDomain()->GetId().m_dwId),
- LOADCTX_TYPE_HOSTED,
- ETWFieldUnused,
- ETWLoaderLoadTypeNotAvailable,
- NULL,
- FusionBind::GetAssemblyNameDisplayName(pIAssemblyName, ssAssemblyName, ASM_DISPLAYF_FULL).GetUnicode(),
- GetClrInstanceId());
- }
-
- ReleaseHolder<IBindResult> pIBindResultIL;
- IfFailRet(pAssembly->GetIBindResult(&pIBindResultIL));
- _ASSERTE(pIBindResultIL != nullptr);
-
- NewArrayHolder<WCHAR> wzZapSet = DuplicateStringThrowing(g_pConfig->ZapSet());
- NativeConfigData cfgData = {
- wzZapSet,
- PEFile::GetNativeImageConfigFlags()
- };
-
- IfFailRet(BindToNativeAssembly(
- pIBindResultIL, &cfgData, static_cast<IBindContext*>(this), fusion::logging::GetCurrentFusionBindLog()));
-
- // Ensure that the native image found above in BindToNativeAssembly is reported as existing in the CLRPrivAssembly object
- if (hr == S_OK)
- {
- ReleaseHolder<ICLRPrivResource> pNIImageResource;
- // This will make GetAvailableImageTypes return that a native image exists.
- IfFailRet(pAssembly->GetImageResource(ASSEMBLY_IMAGE_TYPE_NATIVE, NULL, &pNIImageResource));
-#ifdef _DEBUG
- DWORD dwImageTypes;
-
- _ASSERTE(SUCCEEDED(pAssembly->GetAvailableImageTypes(&dwImageTypes)));
- _ASSERTE((dwImageTypes & ASSEMBLY_IMAGE_TYPE_NATIVE) == ASSEMBLY_IMAGE_TYPE_NATIVE);
-#endif
- }
-
- // Fire BindingNgenPhaseEnd ETW event if enabled.
- {
- InlineSString<128> ssAssemblyName;
- FireEtwBindingNgenPhaseEnd(
- (AppDomain::GetCurrentDomain()->GetId().m_dwId),
- LOADCTX_TYPE_HOSTED,
- ETWFieldUnused,
- ETWLoaderLoadTypeNotAvailable,
- NULL,
- FusionBind::GetAssemblyNameDisplayName(pIAssemblyName, ssAssemblyName, ASM_DISPLAYF_FULL).GetUnicode(),
- GetClrInstanceId());
- }
-
- // BindToNativeAssembly can return S_FALSE, but this could be misleading.
- if (hr == S_FALSE)
- hr = S_OK;
- }
-
- if (SUCCEEDED(hr))
- {
- *ppAssembly = pAssembly.Extract();
- }
-
- return hr;
-}
-
-//=====================================================================================================================
-HRESULT CLRPrivBinderAppX::BindAppXAssemblyByName(
- IAssemblyName * pIAssemblyName,
- DWORD dwAppXBindFlags,
- ICLRPrivAssembly ** ppPrivAssembly)
-{
- STANDARD_VM_CONTRACT;
- HRESULT hr = S_OK;
-
- ReleaseHolder<CLRPrivAssemblyAppX> pAppXAssembly;
- IfFailRet(BindAppXAssemblyByNameWorker(pIAssemblyName, dwAppXBindFlags, &pAppXAssembly));
- IfFailRet(pAppXAssembly->QueryInterface(__uuidof(ICLRPrivAssembly), (LPVOID*)ppPrivAssembly));
-
- return hr;
-}
-
-//=====================================================================================================================
-HRESULT CLRPrivBinderAppX::PreBindAppXAssemblyByName(
- IAssemblyName * pIAssemblyName,
- DWORD dwAppXBindFlags,
- IBindResult ** ppIBindResult)
-{
- STANDARD_VM_CONTRACT;
- HRESULT hr = S_OK;
-
- VALIDATE_ARG_RET(pIAssemblyName != nullptr);
- VALIDATE_ARG_RET(ppIBindResult != nullptr);
-
-
- ReleaseHolder<CLRPrivAssemblyAppX> pAppXAssembly;
- IfFailRet(BindAppXAssemblyByNameWorker(pIAssemblyName, dwAppXBindFlags, &pAppXAssembly));
- IfFailRet(pAppXAssembly->GetIBindResult(ppIBindResult));
-
- return hr;
-}
-
-//=====================================================================================================================
-HRESULT CLRPrivBinderAppX::FindAssemblyBySpec(
- LPVOID pvAppDomain,
- LPVOID pvAssemblySpec,
- HRESULT * pResult,
- ICLRPrivAssembly ** ppAssembly)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- FORBID_FAULT;
- MODE_ANY;
- CAN_TAKE_LOCK;
- }
- CONTRACTL_END
-
- 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);
-
- //
- // Follow the same order as a bind.
- //
-
- hr = CLR_E_BIND_UNRECOGNIZED_IDENTITY_FORMAT;
-
- if (FAILED(hr))
- {
- _ASSERTE(m_pFusionBinder != nullptr);
- hr = m_pFusionBinder->FindFusionAssemblyBySpec(pAppDomain, pAssemblySpec, m_fusionBindingScope, pResult, ppAssembly);
- }
-
- // See comment in code:CLRPrivBinderAppX::BindAssemblyByName for explanation of this conditional.
- if (hr == CLR_E_BIND_UNRECOGNIZED_IDENTITY_FORMAT)
- {
- if (FAILED(hr) && (m_pWinRTBinder != nullptr))
- {
- hr = m_pWinRTBinder->FindWinRTAssemblyBySpec(pAppDomain, pAssemblySpec, pResult, ppAssembly);
- }
-
- if (FAILED(hr))
- {
- AssemblyIdentity refId;
- IfFailRet(refId.Initialize(pAssemblySpec));
- bool fCheckParent = false;
-
- { // Check for a previously-recorded bind. Host callouts are now forbidden.
- ForbidSuspendThreadCrstHolder lock(&m_MapReadLock);
- BindingRecordMap::element_t const * pKeyVal = m_BindingRecordMap.LookupPtr(&refId);
-
- if (pKeyVal != nullptr)
- {
- //
- // Previous bind occurred. If a failure result is cached then the binder would
- // have tried the parent binder (if available) before returning.
- //
-
- AssemblyIdentity const & defId(*pKeyVal->Key());
- BindingRecord const & record(pKeyVal->Value());
-
- *ppAssembly = nullptr;
- *pResult = record.hr;
-
- if (SUCCEEDED(*pResult))
- {
- //
- // Previous bind succeeded. Get the corresponding ICLRPrivAssembly.
- //
-
- // Check this binder for a match. Host callouts are now forbidden.
- CLRPrivAssemblyAppX* pPrivAssembly = m_NameToAssemblyMap.Lookup(defId.Name);
-
- if (pPrivAssembly == nullptr)
- {
- _ASSERTE_MSG(false, "Should never see success value and a null CLRPrivAssemblyAppX pointer.");
- return (*pResult = E_UNEXPECTED);
- }
-
- _ASSERTE(pPrivAssembly->m_pIdentity != nullptr);
- _ASSERTE(pPrivAssembly->m_pIdentity == &defId);
-
- // Now check that the version and PKT values are compatible.
- *pResult = CLRPrivBinderUtil::VerifyBind(refId, *pPrivAssembly->m_pIdentity);
-
- if (SUCCEEDED(*pResult))
- {
- VERIFY(SUCCEEDED(pPrivAssembly->QueryInterface(__uuidof(ICLRPrivAssembly), (LPVOID*)ppAssembly)));
- }
-
- return S_OK;
- }
- else
- {
- //
- // Previous bind failed. Check the parent binder (if available), but do it outside of this binder's lock.
- //
-
- fCheckParent = true;
- }
- }
- else
- {
- //
- // No previous bind occurred. Do not check the parent binder since this could result
- // in an incorrect bind (if this binder would have bound to a different assembly).
- //
-
- return E_FAIL;
- }
- }
-
- if (fCheckParent && m_pParentBinder != nullptr)
- { // Check the parent (shared designer context) for a match.
- hr = m_pParentBinder->FindAssemblyBySpec(pAppDomain, pAssemblySpec, pResult, ppAssembly);
- }
- }
- }
-
- // There are three possibilities upon exit:
- // 1. Cache lookup failed, in which case FAILED(hr) == true
- // 2. A binding failure was cached, in which case (1) == false && FAILED(*pResult) == true
- // 3. A binding success was cached, in which case we must find an assembly:
- // (1) == false && (2) == false && *ppAssembly != nullptr
- _ASSERTE(FAILED(hr) || FAILED(*pResult) || *ppAssembly != nullptr);
- return hr;
-}
-
-//=====================================================================================================================
-// Record the binding result to support cache-based lookups (using ICLRPrivCachedBinder::FindAssemblyBySpec).
-
-HRESULT CLRPrivBinderAppX::CacheBindResult(
- AssemblyIdentity * pIdentity, // On success, will assume object lifetime ownership.
- HRESULT hrResult)
-{
- STANDARD_VM_CONTRACT;
-
- HRESULT hr = S_OK;
-
- VALIDATE_PTR_RET(pIdentity);
-
- // Initialize the binding record.
- BindingRecord rec = { hrResult };
- BindingRecordMap::element_t newEntry(pIdentity, rec);
-
- // Because the read lock must be taken within a ForbidSusped region, use CheckAddInPhases.
- if (m_BindingRecordMap.CheckAddInPhases<ForbidSuspendThreadCrstHolder, CrstHolder>(
- newEntry, m_MapReadLock, m_MapWriteLock))
- {
- // Indicates that this identity object was cached.
- // Caller relinquishes object ownership.
- return S_OK;
- }
- else
- {
- // Pre-existing entry was found.
-
-#ifdef _DEBUG
- ForbidSuspendThreadCrstHolder lock(&m_MapReadLock);
- auto pExistingEntry = m_BindingRecordMap.LookupPtr(pIdentity);
- if (pExistingEntry != nullptr)
- {
- // It's possible for racing threads to try to cache their results;
- // just make sure that they got the same HRESULT.
- _ASSERTE(pExistingEntry->Value().hr == rec.hr);
- }
-#endif
-
- // Indicates that previous entry existed, and this identity object was not cached.
- // Caller retains object ownership.
- hr = S_FALSE;
- }
-
- return hr;
-}
-
-//=====================================================================================================================
-// Implements code:ICLRPrivBinder::BindAssemblyByName
-
-HRESULT CLRPrivBinderAppX::BindAssemblyByName(
- IAssemblyName * pAssemblyName,
- ICLRPrivAssembly ** ppAssembly)
-{
- STANDARD_BIND_CONTRACT;
- BinderHRESULT hr = S_OK;
- ReleaseHolder<ICLRPrivAssembly> pResult;
-
- VALIDATE_ARG_RET(pAssemblyName != nullptr && ppAssembly != nullptr);
-
- EX_TRY
- {
- hr = CLR_E_BIND_UNRECOGNIZED_IDENTITY_FORMAT;
-
- if (FAILED(hr))
- {
- _ASSERTE(m_pFusionBinder != nullptr);
- hr = m_pFusionBinder->BindFusionAssemblyByName(pAssemblyName, GetFusionBindingScope(), &pResult);
- }
-
- //
- // The fusion binder returns CLR_E_BIND_UNRECOGNIZED_IDENTITY_FORMAT only if it did not
- // recognize pAssemblyName as a FX assembly. Only then should other binders be consulted
- // (otherwise applications would be able to copy arbitrary FX assemblies into their AppX
- // package and use them directly).
- //
-
- if (hr == CLR_E_BIND_UNRECOGNIZED_IDENTITY_FORMAT)
- {
- if (FAILED(hr) && (m_pWinRTBinder != nullptr))
- {
- hr = m_pWinRTBinder->BindWinRTAssemblyByName(pAssemblyName, &pResult);
- }
-
- if (FAILED(hr))
- {
- hr = BindAppXAssemblyByName(pAssemblyName, ABF_Default, &pResult);
- }
-
- if (FAILED(hr) && (m_pParentBinder != nullptr))
- {
- hr = m_pParentBinder->BindAssemblyByName(pAssemblyName, &pResult);
- }
-
- _ASSERTE(FAILED(hr) || pResult != nullptr);
- }
- }
- EX_CATCH_HRESULT(hr);
-
- // Return if either the bind or the bind cache fails.
- IfFailRet(hr);
-
- // Success.
- *ppAssembly = pResult.Extract();
- return hr;
-}
-
-//=====================================================================================================================
-// Implements code:IBindContext::PreBind
-HRESULT CLRPrivBinderAppX::PreBind(
- IAssemblyName * pIAssemblyName,
- DWORD dwPreBindFlags,
- IBindResult ** ppIBindResult)
-{
- STANDARD_BIND_CONTRACT;
- BinderHRESULT hr = S_OK;
-
- VALIDATE_ARG_RET((dwPreBindFlags & ~(PRE_BIND_APPLY_POLICY)) == 0);
- VALIDATE_ARG_RET(pIAssemblyName != nullptr && ppIBindResult != nullptr);
-
- // Assert that we are only working with binder that supports Native Images context bits.
- _ASSERTE(m_fCanUseNativeImages);
-
- EX_TRY
- {
- hr = CLR_E_BIND_UNRECOGNIZED_IDENTITY_FORMAT;
-
- if (FAILED(hr))
- {
- hr = m_pFusionBinder->PreBindFusionAssemblyByName(pIAssemblyName, dwPreBindFlags, ppIBindResult);
- }
-
- if (FAILED(hr) && (m_pWinRTBinder != nullptr))
- {
- hr = m_pWinRTBinder->BindWinRTAssemblyByName(pIAssemblyName, ppIBindResult, TRUE);
- }
-
- if (FAILED(hr))
- {
- hr = PreBindAppXAssemblyByName(pIAssemblyName, ABF_BindIL, ppIBindResult);
- }
- }
- EX_CATCH_HRESULT(hr);
-
- if (FAILED(hr) && (m_pParentBinder != nullptr))
- {
- ReleaseHolder<IBindContext> pParentBindContext;
- hr = m_pParentBinder->QueryInterface(__uuidof(IBindContext), (LPVOID *)&pParentBindContext);
- if (SUCCEEDED(hr))
- {
- hr = pParentBindContext->PreBind(pIAssemblyName, dwPreBindFlags, ppIBindResult);
- }
- }
-
- return hr;
-}
-
-//=====================================================================================================================
-UINT_PTR CLRPrivBinderAppX::GetBinderID()
-{
- LIMITED_METHOD_CONTRACT;
- return reinterpret_cast<UINT_PTR>(this);
-}
-
-//=====================================================================================================================
-// Implements code:ICLRPrivBinder::GetBinderID
-HRESULT CLRPrivBinderAppX::GetBinderID(
- UINT_PTR *pBinderId)
-{
- LIMITED_METHOD_CONTRACT;
-
- *pBinderId = GetBinderID();
- return S_OK;
-}
-
-//=====================================================================================================================
-// Implements code:IBindContext::IsDefaultContext
-HRESULT CLRPrivBinderAppX::IsDefaultContext()
-{
- LIMITED_METHOD_CONTRACT;
- return S_OK;
-}
-
-//=====================================================================================================================
-// Implements code:ICLRPrivWinRtTypeBinder::FindAssemblyForWinRtTypeIfLoaded
-// Finds Assembly * for type in AppDomain * if it is loaded.
-// Returns NULL if assembly is not loaded or type is not found.
-//
-void *
-CLRPrivBinderAppX::FindAssemblyForWinRtTypeIfLoaded(
- void * pAppDomain,
- LPCUTF8 szNamespace,
- LPCUTF8 szClassName)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- FORBID_FAULT;
- MODE_ANY;
- }
- CONTRACTL_END
-
- void * pAssembly = nullptr;
- if (m_pWinRTBinder != nullptr)
- {
- pAssembly = (void *)m_pWinRTBinder->FindAssemblyForTypeIfLoaded(
- dac_cast<PTR_AppDomain>((AppDomain *)pAppDomain),
- szNamespace,
- szClassName);
- }
-
- if ((pAssembly == nullptr) && (m_pParentBinder != nullptr))
- {
- ReleaseHolder<ICLRPrivWinRtTypeBinder> pParentBinder =
- ToInterface_NoThrow<ICLRPrivWinRtTypeBinder>(m_pParentBinder.GetValue());
- // Parent binder should be another instance of code:CLRPrivBinderAppX class that implements the interface
- _ASSERTE(pParentBinder != nullptr);
-
- pAssembly = pParentBinder->FindAssemblyForWinRtTypeIfLoaded(
- pAppDomain,
- szNamespace,
- szClassName);
- }
-
- return pAssembly;
-}
-
-//=====================================================================================================================
-CLRPrivAssemblyAppX::CLRPrivAssemblyAppX(
- CLRPrivBinderUtil::AssemblyIdentity * pIdentity,
- CLRPrivBinderAppX *pBinder,
- ICLRPrivResource *pIResourceIL,
- IBindResult * pIBindResult)
- : m_pIdentity(pIdentity),
- m_pBinder(nullptr),
- m_pIResourceIL(nullptr),
- m_pIResourceNI(nullptr),
- m_pIBindResult(nullptr)
-{
- STANDARD_VM_CONTRACT;
-
- VALIDATE_PTR_THROW(pIdentity);
- VALIDATE_PTR_THROW(pBinder);
- VALIDATE_PTR_THROW(pIResourceIL);
- VALIDATE_PTR_THROW(pIBindResult);
-
- m_pBinder = clr::SafeAddRef(pBinder);
- m_pIResourceIL = clr::SafeAddRef(pIResourceIL);
- m_pIBindResult = clr::SafeAddRef(pIBindResult);
-}
-
-//=====================================================================================================================
-CLRPrivAssemblyAppX::~CLRPrivAssemblyAppX()
-{
- LIMITED_METHOD_CONTRACT;
- clr::SafeRelease(m_pIResourceNI);
-}
-
-//=====================================================================================================================
-LPCWSTR CLRPrivAssemblyAppX::GetSimpleName() const
-{
- LIMITED_METHOD_CONTRACT;
- return m_pIdentity->Name;
-}
-
-//=====================================================================================================================
-// Implements code:IUnknown::Release
-ULONG CLRPrivAssemblyAppX::Release()
-{
- LIMITED_METHOD_CONTRACT;
- STATIC_CONTRACT_CAN_TAKE_LOCK;
- _ASSERTE(m_cRef > 0);
-
- ULONG cRef;
-
- {
- // To achieve proper lifetime semantics, the name to assembly map elements' CLRPrivAssemblyAppX
- // instances are not ref counted. We cannot allow discovery of the object via m_NameToAssemblyMap
- // when the ref count is 0 (to prevent another thread to AddRef and Release it back to 0 in parallel).
- // All uses of the map are guarded by the map lock, so we have to decrease the ref count under that
- // lock (to avoid the chance that 2 threads are running Release to ref count 0 at once).
- // Host callouts are now forbidden.
- ForbidSuspendThreadCrstHolder lock(&m_pBinder->m_MapReadLock);
-
- cRef = InterlockedDecrement(&m_cRef);
- if (cRef == 0)
- {
- m_pBinder->m_NameToAssemblyMap.Remove(GetSimpleName());
- m_pBinder->m_BindingRecordMap.Remove(m_pIdentity);
- }
- }
-
- if (cRef == 0)
- {
- delete this;
- }
-
- return cRef;
-}
-
-//=====================================================================================================================
-// Implements code:ICLRPrivBinder::BindAssemblyByName
-HRESULT CLRPrivAssemblyAppX::BindAssemblyByName(
- IAssemblyName * pAssemblyName,
- ICLRPrivAssembly ** ppAssembly)
-{
- WRAPPER_NO_CONTRACT;
-
- return m_pBinder->BindAssemblyByName(
- pAssemblyName,
- ppAssembly);
-}
-
-//=====================================================================================================================
-// Implements code:ICLRPrivBinder::GetBinderID
-HRESULT CLRPrivAssemblyAppX::GetBinderID(
- UINT_PTR *pBinderId)
-{
- WRAPPER_NO_CONTRACT;
- return m_pBinder->GetBinderID(
- pBinderId);
-}
-
-//=====================================================================================================================
-// Implements code:ICLRPrivAssembly::IsShareable
-HRESULT CLRPrivAssemblyAppX::IsShareable(
- BOOL * pbIsShareable)
-{
- LIMITED_METHOD_CONTRACT;
-
- VALIDATE_ARG_RET(pbIsShareable != nullptr);
-
- *pbIsShareable = FALSE;
- return S_OK;
-}
-
-//=====================================================================================================================
-// Implements code:ICLRPrivAssembly::GetAvailableImageTypes
-HRESULT CLRPrivAssemblyAppX::GetAvailableImageTypes(
- LPDWORD pdwImageTypes)
-{
- LIMITED_METHOD_CONTRACT;
-
- VALIDATE_ARG_RET(pdwImageTypes != nullptr);
-
- *pdwImageTypes = 0;
-
- if (m_pIResourceIL != nullptr)
- *pdwImageTypes |= ASSEMBLY_IMAGE_TYPE_IL;
-
- if (m_pIResourceNI != nullptr)
- *pdwImageTypes |= ASSEMBLY_IMAGE_TYPE_NATIVE;
-
- return S_OK;
-}
-
-//=====================================================================================================================
-static ICLRPrivResource* GetResourceForBindResult(
- IBindResult * pIBindResult)
-{
- STANDARD_VM_CONTRACT;
- VALIDATE_ARG_THROW(pIBindResult != nullptr);
-
- WCHAR wzPath[_MAX_PATH];
- DWORD cchPath = NumItems(wzPath);
- ReleaseHolder<IAssemblyLocation> pIAssemLoc;
- IfFailThrow(pIBindResult->GetAssemblyLocation(&pIAssemLoc));
- IfFailThrow(pIAssemLoc->GetPath(wzPath, &cchPath));
- return ToInterface<ICLRPrivResource>(new CLRPrivResourcePathImpl(wzPath));
-}
-
-//=====================================================================================================================
-// Implements code:ICLRPrivAssembly::GetImageResource
-HRESULT CLRPrivAssemblyAppX::GetImageResource(
- DWORD dwImageType,
- DWORD * pdwImageType,
- ICLRPrivResource ** ppIResource)
-{
- STANDARD_BIND_CONTRACT;
- HRESULT hr = S_OK;
-
- VALIDATE_ARG_RET(ppIResource != nullptr && m_pIBindResult != nullptr);
-
- EX_TRY
- {
- DWORD _dwImageType;
- if (pdwImageType == nullptr)
- pdwImageType = &_dwImageType;
-
- if ((dwImageType & ASSEMBLY_IMAGE_TYPE_NATIVE) == ASSEMBLY_IMAGE_TYPE_NATIVE)
- {
- ReleaseHolder<IBindResult> pIBindResultNI;
- if (m_pIResourceNI == nullptr)
- {
- if (SUCCEEDED(hr = m_pIBindResult->GetNativeImage(&pIBindResultNI, nullptr)) && pIBindResultNI != nullptr)
- {
- ReleaseHolder<ICLRPrivResource> pResourceNI = GetResourceForBindResult(pIBindResultNI);
- if (InterlockedCompareExchangeT<ICLRPrivResource *>(&m_pIResourceNI, pResourceNI, nullptr) == nullptr)
- pResourceNI.SuppressRelease();
- }
- else
- {
- IfFailGo(CLR_E_BIND_IMAGE_UNAVAILABLE);
- }
- }
-
- *ppIResource = clr::SafeAddRef(m_pIResourceNI);
- *pdwImageType = ASSEMBLY_IMAGE_TYPE_NATIVE;
- }
- else if ((dwImageType & ASSEMBLY_IMAGE_TYPE_IL) == ASSEMBLY_IMAGE_TYPE_IL)
- {
- *ppIResource = clr::SafeAddRef(m_pIResourceIL);
- *pdwImageType = ASSEMBLY_IMAGE_TYPE_IL;
- }
- else
- {
- hr = CLR_E_BIND_IMAGE_UNAVAILABLE;
- }
-
- ErrExit:
- ;
- }
- EX_CATCH_HRESULT(hr);
-
- return hr;
-}
-
-
-//=====================================================================================================================
-// Implements code:ICLRPrivBinder::VerifyBind
-HRESULT CLRPrivBinderAppX::VerifyBind(
- IAssemblyName *pAssemblyName,
- ICLRPrivAssembly *pAssembly,
- ICLRPrivAssemblyInfo *pAssemblyInfo)
-{
- STANDARD_BIND_CONTRACT;
-
- HRESULT hr = S_OK;
-
- VALIDATE_ARG_RET(pAssemblyName!= nullptr && pAssemblyInfo != nullptr);
-
- UINT_PTR binderID;
- IfFailRet(pAssembly->GetBinderID(&binderID));
-
- if (binderID != GetBinderID())
- {
- return pAssembly->VerifyBind(pAssemblyName, pAssembly, pAssemblyInfo);
- }
-
- return CLRPrivBinderUtil::VerifyBind(pAssemblyName, pAssemblyInfo);
-}
-
-//=====================================================================================================================
-/*static*/
-LPCWSTR CLRPrivBinderAppX::NameToAssemblyMapTraits::GetKey(CLRPrivAssemblyAppX *pAssemblyAppX)
-{
- WRAPPER_NO_CONTRACT;
- _ASSERT(pAssemblyAppX != nullptr);
- return pAssemblyAppX->GetSimpleName();
-}
-
-//=====================================================================================================================
-HRESULT CLRPrivAssemblyAppX::GetIBindResult(
- IBindResult ** ppIBindResult)
-{
- STANDARD_VM_CONTRACT;
-
- VALIDATE_ARG_RET(ppIBindResult != nullptr);
- VALIDATE_CONDITION(m_pIBindResult != nullptr, return E_UNEXPECTED);
-
- *ppIBindResult = clr::SafeAddRef(m_pIBindResult);
-
- return S_OK;
-}
-
-#endif // !DACCESS_COMPILE