diff options
Diffstat (limited to 'src/binder/assembly.cpp')
-rw-r--r-- | src/binder/assembly.cpp | 434 |
1 files changed, 434 insertions, 0 deletions
diff --git a/src/binder/assembly.cpp b/src/binder/assembly.cpp new file mode 100644 index 0000000000..8fcc7cf54f --- /dev/null +++ b/src/binder/assembly.cpp @@ -0,0 +1,434 @@ +// 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. +// ============================================================ +// +// Assembly.cpp +// + + +// +// Implements the Assembly class +// +// ============================================================ +#include "common.h" +#include "clrprivbinderutil.h" +#include "assembly.hpp" +#include "utils.hpp" + +namespace BINDER_SPACE +{ + namespace + { + BOOL IsPlatformArchicture(PEKIND kArchitecture) + { + return ((kArchitecture != peMSIL) && (kArchitecture != peNone)); + } + + HRESULT GetAssemblyRefTokens(IMDInternalImport *pMDImport, + mdAssembly **ppAssemblyRefTokens, + DWORD *pdwCAssemblyRefTokens) + { + HRESULT hr = S_OK; + + _ASSERTE(pMDImport != NULL); + _ASSERTE(ppAssemblyRefTokens != NULL); + _ASSERTE(pdwCAssemblyRefTokens != NULL); + + mdAssembly *pAssemblyRefTokens = NULL; + COUNT_T assemblyRefCount; + + HENUMInternalHolder hEnumAssemblyRef(pMDImport); + IF_FAIL_GO(hEnumAssemblyRef.EnumInitNoThrow(mdtAssemblyRef, mdTokenNil)); + + assemblyRefCount = hEnumAssemblyRef.EnumGetCount(); + + pAssemblyRefTokens = new (nothrow) mdAssemblyRef[assemblyRefCount]; + if (pAssemblyRefTokens == NULL) + { + IF_FAIL_GO(E_OUTOFMEMORY); + } + ZeroMemory(pAssemblyRefTokens, assemblyRefCount * sizeof(mdAssemblyRef)); + + for (COUNT_T i = 0; i < assemblyRefCount; i++) + { + bool ret = hEnumAssemblyRef.EnumNext(&(pAssemblyRefTokens[i])); + _ASSERTE(ret); + } + + *ppAssemblyRefTokens = pAssemblyRefTokens; + pAssemblyRefTokens = NULL; + + *pdwCAssemblyRefTokens= assemblyRefCount; + hr = S_OK; + +Exit: + SAFE_DELETE_ARRAY(pAssemblyRefTokens); + + return hr; + } + }; + + STDMETHODIMP Assembly::QueryInterface(REFIID riid, + void **ppv) + { + HRESULT hr = S_OK; + + if (ppv == NULL) + { + hr = E_POINTER; + } + else + { + if (IsEqualIID(riid, IID_IUnknown)) + { + AddRef(); + *ppv = static_cast<IUnknown *>(this); + } + else + { + *ppv = NULL; + hr = E_NOINTERFACE; + } + } + + return hr; + } + + STDMETHODIMP_(ULONG) Assembly::AddRef() + { + return InterlockedIncrement(&m_cRef); + } + + STDMETHODIMP_(ULONG) Assembly::Release() + { + ULONG ulRef = InterlockedDecrement(&m_cRef); + + if (ulRef == 0) + { + delete this; + } + + return ulRef; + } + + Assembly::Assembly() + { + m_cRef = 1; + m_pPEImage = NULL; + m_pNativePEImage = NULL; + m_pAssemblyName = NULL; + m_pMDImport = NULL; + m_pAssemblyRefTokens = NULL; + m_dwCAssemblyRefTokens = static_cast<DWORD>(-1); + m_dwAssemblyFlags = FLAG_NONE; + m_pBinder = NULL; + } + + Assembly::~Assembly() + { + BINDER_LOG_ASSEMBLY_NAME(L"destructing assembly", m_pAssemblyName); + + if (m_pPEImage != NULL) + { + BinderReleasePEImage(m_pPEImage); + m_pPEImage = NULL; + } + +#ifdef FEATURE_PREJIT + if (m_pNativePEImage != NULL) + { + BinderReleasePEImage(m_pNativePEImage); + m_pNativePEImage = NULL; + } +#endif + + SAFE_RELEASE(m_pAssemblyName); + SAFE_RELEASE(m_pMDImport); + SAFE_DELETE_ARRAY(m_pAssemblyRefTokens); + } + + HRESULT Assembly::Init( + IMDInternalImport *pIMetaDataAssemblyImport, + PEKIND PeKind, + PEImage *pPEImage, + PEImage *pNativePEImage, + SString &assemblyPath, + BOOL fInspectionOnly, + BOOL fIsInGAC) + { + HRESULT hr = S_OK; + BINDER_LOG_ENTER(L"Assembly::Init"); + + ReleaseHolder<AssemblyName> pAssemblyName; + SAFE_NEW(pAssemblyName, AssemblyName); + + // Get assembly name def from meta data import and store it for later refs access + IF_FAIL_GO(pAssemblyName->Init(pIMetaDataAssemblyImport, PeKind)); + SetMDImport(pIMetaDataAssemblyImport); + if (!fIsInGAC) + { + GetPath().Set(assemblyPath); + } + + BINDER_LOG_ASSEMBLY_NAME(L"AssemblyNameDef", pAssemblyName); + BINDER_LOG_STRING(L"System Architecture", + AssemblyName::ArchitectureToString(GetSystemArchitecture())); + + // Safe architecture for validation + PEKIND kAssemblyArchitecture; + kAssemblyArchitecture = pAssemblyName->GetArchitecture(); + SetInspectionOnly(fInspectionOnly); + SetIsInGAC(fIsInGAC); + SetPEImage(pPEImage); + SetNativePEImage(pNativePEImage); + pAssemblyName->SetIsDefinition(TRUE); + + // Now take ownership of assembly names + SetAssemblyName(pAssemblyName.Extract(), FALSE /* fAddRef */); + + // Finally validate architecture + if (!fInspectionOnly && !IsValidArchitecture(kAssemblyArchitecture)) + { + // Assembly image can't be executed on this platform + IF_FAIL_GO(HRESULT_FROM_WIN32(ERROR_BAD_FORMAT)); + } + + Exit: + BINDER_LOG_LEAVE_HR(L"Assembly::Init", hr); + return hr; + } + + HRESULT Assembly::GetMVID(GUID *pMVID) + { + // Zero init the GUID incase we fail + ZeroMemory(pMVID, sizeof(GUID)); + + return m_pMDImport->GetScopeProps(NULL, pMVID); + } + + HRESULT Assembly::GetNextAssemblyNameRef(DWORD nIndex, + AssemblyName **ppAssemblyName) + { + HRESULT hr = S_OK; + BINDER_LOG_ENTER(L"Assembly::GetNextAssemblyNameRef"); + + if (ppAssemblyName == NULL) + { + IF_FAIL_GO(E_INVALIDARG); + } + else if (GetNbAssemblyRefTokens() == static_cast<DWORD>(-1)) + { + mdAssembly *pAssemblyRefTokens = NULL; + DWORD dwCAssemblyRefTokens = 0; + + IF_FAIL_GO(BINDER_SPACE::GetAssemblyRefTokens(GetMDImport(), + &pAssemblyRefTokens, + &dwCAssemblyRefTokens)); + + if (InterlockedCompareExchangeT(&m_pAssemblyRefTokens, + pAssemblyRefTokens, + NULL)) + { + SAFE_DELETE_ARRAY(pAssemblyRefTokens); + } + SetNbAsssemblyRefTokens(dwCAssemblyRefTokens); + } + + _ASSERTE(GetNbAssemblyRefTokens() != static_cast<DWORD>(-1)); + + // Verify input index + if (nIndex >= GetNbAssemblyRefTokens()) + { + IF_FAIL_GO(HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS)); + } + else + { + ReleaseHolder<AssemblyName> pAssemblyName; + + SAFE_NEW(pAssemblyName, AssemblyName); + IF_FAIL_GO(pAssemblyName->Init(GetMDImport(), + peNone, + GetAssemblyRefTokens()[nIndex], + FALSE /* fIsDefinition */)); + + *ppAssemblyName = pAssemblyName.Extract(); + } + + Exit: + BINDER_LOG_LEAVE_HR(L"Assembly::GetNextAssemblyNameRef", hr); + return hr; + } + + /* static */ + PEKIND Assembly::GetSystemArchitecture() + { +#if defined(_TARGET_X86_) + return peI386; +#elif defined(_TARGET_AMD64_) + return peAMD64; +#elif defined(_TARGET_ARM_) + return peARM; +#elif defined(_TARGET_ARM64_) + return peARM64; +#else + PORTABILITY_ASSERT("Assembly::GetSystemArchitecture"); +#endif + } + + /* static */ + BOOL Assembly::IsValidArchitecture(PEKIND kArchitecture) + { + if (!IsPlatformArchicture(kArchitecture)) + return TRUE; + + return (kArchitecture == GetSystemArchitecture()); + } + + // -------------------------------------------------------------------- + // ICLRPrivAssembly methods + // -------------------------------------------------------------------- + LPCWSTR Assembly::GetSimpleName() + { + AssemblyName *pAsmName = GetAssemblyName(); + return (pAsmName == nullptr ? nullptr : pAsmName->GetSimpleName()); + } + + HRESULT Assembly::BindAssemblyByName(IAssemblyName * pIAssemblyName, ICLRPrivAssembly ** ppAssembly) + { + return (m_pBinder == NULL) ? E_FAIL : m_pBinder->BindAssemblyByName(pIAssemblyName, ppAssembly); + } + + HRESULT Assembly::FindAssemblyBySpec( + LPVOID pvAppDomain, + LPVOID pvAssemblySpec, + HRESULT * pResult, + ICLRPrivAssembly ** ppAssembly) + { + return (m_pBinder == NULL) ? E_FAIL : m_pBinder->FindAssemblyBySpec(pvAppDomain, pvAssemblySpec, pResult, ppAssembly); + } + + HRESULT Assembly::VerifyBind ( + IAssemblyName * pIAssemblyName, + ICLRPrivAssembly *pAssembly, + ICLRPrivAssemblyInfo *pAssemblyInfo) + { + return (m_pBinder == NULL) ? E_FAIL : m_pBinder->VerifyBind(pIAssemblyName, pAssembly, pAssemblyInfo); + } + + HRESULT Assembly::GetBinderID(UINT_PTR *pBinderId) + { + return (m_pBinder == NULL) ? E_FAIL : m_pBinder->GetBinderID(pBinderId); + } + + HRESULT Assembly::GetBinderFlags(DWORD *pBinderFlags) + { + return (m_pBinder == NULL) ? E_FAIL : m_pBinder->GetBinderFlags(pBinderFlags); + } + + HRESULT Assembly::IsShareable( + BOOL * pbIsShareable) + { + if(pbIsShareable == nullptr) + return E_INVALIDARG; + + *pbIsShareable = GetIsSharable(); + return S_OK; + } + + HRESULT Assembly::GetAvailableImageTypes( + LPDWORD pdwImageTypes) + { + HRESULT hr = E_FAIL; + + if(pdwImageTypes == nullptr) + return E_INVALIDARG; + + *pdwImageTypes = ASSEMBLY_IMAGE_TYPE_ASSEMBLY; + + return S_OK; + } + + HRESULT Assembly::GetImageResource( + DWORD dwImageType, + DWORD * pdwImageType, + ICLRPrivResource ** ppIResource) + { + HRESULT hr = S_OK; + if(ppIResource == nullptr) + return E_INVALIDARG; + + if ((dwImageType & ASSEMBLY_IMAGE_TYPE_ASSEMBLY) == ASSEMBLY_IMAGE_TYPE_ASSEMBLY) + { + *ppIResource = clr::SafeAddRef(&m_clrPrivRes); + if (pdwImageType != nullptr) + *pdwImageType = ASSEMBLY_IMAGE_TYPE_ASSEMBLY; + } + else + { + hr = CLR_E_BIND_IMAGE_UNAVAILABLE; + } + + return hr; + } + + // get parent pointer from nested type + #define GetPThis() ((BINDER_SPACE::Assembly*)(((PBYTE)this) - offsetof(BINDER_SPACE::Assembly, m_clrPrivRes))) + + HRESULT Assembly::CLRPrivResourceAssembly::QueryInterface(REFIID riid, void ** ppv) + { + HRESULT hr = S_OK; + VALIDATE_ARG_RET(ppv != NULL); + + if (IsEqualIID(riid, IID_IUnknown)) + { + AddRef(); + *ppv = this; + } + else if (IsEqualIID(riid, __uuidof(ICLRPrivResource))) + { + AddRef(); + // upcasting is safe + *ppv = static_cast<ICLRPrivResource *>(this); + } + else if (IsEqualIID(riid, __uuidof(ICLRPrivResourceAssembly))) + { + AddRef(); + *ppv = static_cast<ICLRPrivResourceAssembly *>(this); + } + else + { + *ppv = NULL; + hr = E_NOINTERFACE; + } + + return hr; + } + + ULONG Assembly::CLRPrivResourceAssembly::AddRef() + { + return GetPThis()->AddRef(); + } + + ULONG Assembly::CLRPrivResourceAssembly::Release() + { + return GetPThis()->Release(); + } + + HRESULT Assembly::CLRPrivResourceAssembly::GetResourceType(IID *pIID) + { + VALIDATE_ARG_RET(pIID != nullptr); + *pIID = __uuidof(ICLRPrivResourceAssembly); + return S_OK; + } + + HRESULT Assembly::CLRPrivResourceAssembly::GetAssembly(LPVOID *ppAssembly) + { + VALIDATE_ARG_RET(ppAssembly != nullptr); + AddRef(); + *ppAssembly = GetPThis(); + return S_OK; + } + +} + |