1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 // ============================================================
11 // Implements the Assembly class
13 // ============================================================
15 #include "clrprivbinderutil.h"
16 #include "assembly.hpp"
19 namespace BINDER_SPACE
23 BOOL IsPlatformArchicture(PEKIND kArchitecture)
25 return ((kArchitecture != peMSIL) && (kArchitecture != peNone));
28 HRESULT GetAssemblyRefTokens(IMDInternalImport *pMDImport,
29 mdAssembly **ppAssemblyRefTokens,
30 DWORD *pdwCAssemblyRefTokens)
34 _ASSERTE(pMDImport != NULL);
35 _ASSERTE(ppAssemblyRefTokens != NULL);
36 _ASSERTE(pdwCAssemblyRefTokens != NULL);
38 mdAssembly *pAssemblyRefTokens = NULL;
39 COUNT_T assemblyRefCount;
41 HENUMInternalHolder hEnumAssemblyRef(pMDImport);
42 IF_FAIL_GO(hEnumAssemblyRef.EnumInitNoThrow(mdtAssemblyRef, mdTokenNil));
44 assemblyRefCount = hEnumAssemblyRef.EnumGetCount();
46 pAssemblyRefTokens = new (nothrow) mdAssemblyRef[assemblyRefCount];
47 if (pAssemblyRefTokens == NULL)
49 IF_FAIL_GO(E_OUTOFMEMORY);
51 ZeroMemory(pAssemblyRefTokens, assemblyRefCount * sizeof(mdAssemblyRef));
53 for (COUNT_T i = 0; i < assemblyRefCount; i++)
55 bool ret = hEnumAssemblyRef.EnumNext(&(pAssemblyRefTokens[i]));
59 *ppAssemblyRefTokens = pAssemblyRefTokens;
60 pAssemblyRefTokens = NULL;
62 *pdwCAssemblyRefTokens= assemblyRefCount;
66 SAFE_DELETE_ARRAY(pAssemblyRefTokens);
72 STDMETHODIMP Assembly::QueryInterface(REFIID riid,
83 if (IsEqualIID(riid, IID_IUnknown))
86 *ppv = static_cast<IUnknown *>(this);
98 STDMETHODIMP_(ULONG) Assembly::AddRef()
100 return InterlockedIncrement(&m_cRef);
103 STDMETHODIMP_(ULONG) Assembly::Release()
105 ULONG ulRef = InterlockedDecrement(&m_cRef);
119 m_pNativePEImage = NULL;
120 m_pAssemblyName = NULL;
122 m_pAssemblyRefTokens = NULL;
123 m_dwCAssemblyRefTokens = static_cast<DWORD>(-1);
124 m_dwAssemblyFlags = FLAG_NONE;
128 Assembly::~Assembly()
130 BINDER_LOG_ASSEMBLY_NAME(L"destructing assembly", m_pAssemblyName);
132 if (m_pPEImage != NULL)
134 BinderReleasePEImage(m_pPEImage);
138 #ifdef FEATURE_PREJIT
139 if (m_pNativePEImage != NULL)
141 BinderReleasePEImage(m_pNativePEImage);
142 m_pNativePEImage = NULL;
146 SAFE_RELEASE(m_pAssemblyName);
147 SAFE_RELEASE(m_pMDImport);
148 SAFE_DELETE_ARRAY(m_pAssemblyRefTokens);
151 HRESULT Assembly::Init(
152 IMDInternalImport *pIMetaDataAssemblyImport,
155 PEImage *pNativePEImage,
156 SString &assemblyPath,
157 BOOL fInspectionOnly,
161 BINDER_LOG_ENTER(L"Assembly::Init");
163 ReleaseHolder<AssemblyName> pAssemblyName;
164 SAFE_NEW(pAssemblyName, AssemblyName);
166 // Get assembly name def from meta data import and store it for later refs access
167 IF_FAIL_GO(pAssemblyName->Init(pIMetaDataAssemblyImport, PeKind));
168 SetMDImport(pIMetaDataAssemblyImport);
171 GetPath().Set(assemblyPath);
174 BINDER_LOG_ASSEMBLY_NAME(L"AssemblyNameDef", pAssemblyName);
175 BINDER_LOG_STRING(L"System Architecture",
176 AssemblyName::ArchitectureToString(GetSystemArchitecture()));
178 // Safe architecture for validation
179 PEKIND kAssemblyArchitecture;
180 kAssemblyArchitecture = pAssemblyName->GetArchitecture();
181 SetInspectionOnly(fInspectionOnly);
182 SetIsInGAC(fIsInGAC);
183 SetPEImage(pPEImage);
184 SetNativePEImage(pNativePEImage);
185 pAssemblyName->SetIsDefinition(TRUE);
187 // Now take ownership of assembly names
188 SetAssemblyName(pAssemblyName.Extract(), FALSE /* fAddRef */);
190 // Finally validate architecture
191 if (!fInspectionOnly && !IsValidArchitecture(kAssemblyArchitecture))
193 // Assembly image can't be executed on this platform
194 IF_FAIL_GO(HRESULT_FROM_WIN32(ERROR_BAD_FORMAT));
198 BINDER_LOG_LEAVE_HR(L"Assembly::Init", hr);
202 HRESULT Assembly::GetMVID(GUID *pMVID)
204 // Zero init the GUID incase we fail
205 ZeroMemory(pMVID, sizeof(GUID));
207 return m_pMDImport->GetScopeProps(NULL, pMVID);
210 HRESULT Assembly::GetNextAssemblyNameRef(DWORD nIndex,
211 AssemblyName **ppAssemblyName)
214 BINDER_LOG_ENTER(L"Assembly::GetNextAssemblyNameRef");
216 if (ppAssemblyName == NULL)
218 IF_FAIL_GO(E_INVALIDARG);
220 else if (GetNbAssemblyRefTokens() == static_cast<DWORD>(-1))
222 mdAssembly *pAssemblyRefTokens = NULL;
223 DWORD dwCAssemblyRefTokens = 0;
225 IF_FAIL_GO(BINDER_SPACE::GetAssemblyRefTokens(GetMDImport(),
227 &dwCAssemblyRefTokens));
229 if (InterlockedCompareExchangeT(&m_pAssemblyRefTokens,
233 SAFE_DELETE_ARRAY(pAssemblyRefTokens);
235 SetNbAsssemblyRefTokens(dwCAssemblyRefTokens);
238 _ASSERTE(GetNbAssemblyRefTokens() != static_cast<DWORD>(-1));
240 // Verify input index
241 if (nIndex >= GetNbAssemblyRefTokens())
243 IF_FAIL_GO(HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS));
247 ReleaseHolder<AssemblyName> pAssemblyName;
249 SAFE_NEW(pAssemblyName, AssemblyName);
250 IF_FAIL_GO(pAssemblyName->Init(GetMDImport(),
252 GetAssemblyRefTokens()[nIndex],
253 FALSE /* fIsDefinition */));
255 *ppAssemblyName = pAssemblyName.Extract();
259 BINDER_LOG_LEAVE_HR(L"Assembly::GetNextAssemblyNameRef", hr);
264 PEKIND Assembly::GetSystemArchitecture()
266 #if defined(_TARGET_X86_)
268 #elif defined(_TARGET_AMD64_)
270 #elif defined(_TARGET_ARM_)
272 #elif defined(_TARGET_ARM64_)
275 PORTABILITY_ASSERT("Assembly::GetSystemArchitecture");
280 BOOL Assembly::IsValidArchitecture(PEKIND kArchitecture)
282 if (!IsPlatformArchicture(kArchitecture))
285 return (kArchitecture == GetSystemArchitecture());
288 // --------------------------------------------------------------------
289 // ICLRPrivAssembly methods
290 // --------------------------------------------------------------------
291 LPCWSTR Assembly::GetSimpleName()
293 AssemblyName *pAsmName = GetAssemblyName();
294 return (pAsmName == nullptr ? nullptr : pAsmName->GetSimpleName());
297 HRESULT Assembly::BindAssemblyByName(IAssemblyName * pIAssemblyName, ICLRPrivAssembly ** ppAssembly)
299 return (m_pBinder == NULL) ? E_FAIL : m_pBinder->BindAssemblyByName(pIAssemblyName, ppAssembly);
302 HRESULT Assembly::FindAssemblyBySpec(
304 LPVOID pvAssemblySpec,
306 ICLRPrivAssembly ** ppAssembly)
308 return (m_pBinder == NULL) ? E_FAIL : m_pBinder->FindAssemblyBySpec(pvAppDomain, pvAssemblySpec, pResult, ppAssembly);
311 HRESULT Assembly::VerifyBind (
312 IAssemblyName * pIAssemblyName,
313 ICLRPrivAssembly *pAssembly,
314 ICLRPrivAssemblyInfo *pAssemblyInfo)
316 return (m_pBinder == NULL) ? E_FAIL : m_pBinder->VerifyBind(pIAssemblyName, pAssembly, pAssemblyInfo);
319 HRESULT Assembly::GetBinderID(UINT_PTR *pBinderId)
321 return (m_pBinder == NULL) ? E_FAIL : m_pBinder->GetBinderID(pBinderId);
324 HRESULT Assembly::GetBinderFlags(DWORD *pBinderFlags)
326 return (m_pBinder == NULL) ? E_FAIL : m_pBinder->GetBinderFlags(pBinderFlags);
329 HRESULT Assembly::IsShareable(
330 BOOL * pbIsShareable)
332 if(pbIsShareable == nullptr)
335 *pbIsShareable = GetIsSharable();
339 HRESULT Assembly::GetAvailableImageTypes(
340 LPDWORD pdwImageTypes)
344 if(pdwImageTypes == nullptr)
347 *pdwImageTypes = ASSEMBLY_IMAGE_TYPE_ASSEMBLY;
352 HRESULT Assembly::GetImageResource(
354 DWORD * pdwImageType,
355 ICLRPrivResource ** ppIResource)
358 if(ppIResource == nullptr)
361 if ((dwImageType & ASSEMBLY_IMAGE_TYPE_ASSEMBLY) == ASSEMBLY_IMAGE_TYPE_ASSEMBLY)
363 *ppIResource = clr::SafeAddRef(&m_clrPrivRes);
364 if (pdwImageType != nullptr)
365 *pdwImageType = ASSEMBLY_IMAGE_TYPE_ASSEMBLY;
369 hr = CLR_E_BIND_IMAGE_UNAVAILABLE;
375 // get parent pointer from nested type
376 #define GetPThis() ((BINDER_SPACE::Assembly*)(((PBYTE)this) - offsetof(BINDER_SPACE::Assembly, m_clrPrivRes)))
378 HRESULT Assembly::CLRPrivResourceAssembly::QueryInterface(REFIID riid, void ** ppv)
381 VALIDATE_ARG_RET(ppv != NULL);
383 if (IsEqualIID(riid, IID_IUnknown))
388 else if (IsEqualIID(riid, __uuidof(ICLRPrivResource)))
392 *ppv = static_cast<ICLRPrivResource *>(this);
394 else if (IsEqualIID(riid, __uuidof(ICLRPrivResourceAssembly)))
397 *ppv = static_cast<ICLRPrivResourceAssembly *>(this);
408 ULONG Assembly::CLRPrivResourceAssembly::AddRef()
410 return GetPThis()->AddRef();
413 ULONG Assembly::CLRPrivResourceAssembly::Release()
415 return GetPThis()->Release();
418 HRESULT Assembly::CLRPrivResourceAssembly::GetResourceType(IID *pIID)
420 VALIDATE_ARG_RET(pIID != nullptr);
421 *pIID = __uuidof(ICLRPrivResourceAssembly);
425 HRESULT Assembly::CLRPrivResourceAssembly::GetAssembly(LPVOID *ppAssembly)
427 VALIDATE_ARG_RET(ppAssembly != nullptr);
429 *ppAssembly = GetPThis();