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 // ============================================================
6 // BaseAssemblySpec.inl
11 // Implements the BaseAssemblySpec class
13 // ============================================================
15 #ifndef __BASE_ASSEMBLY_SPEC_INL__
16 #define __BASE_ASSEMBLY_SPEC_INL__
18 BOOL AreSameBinderInstance(ICLRPrivBinder *pBinderA, ICLRPrivBinder *pBinderB);
20 inline int BaseAssemblySpec::CompareStrings(LPCUTF8 string1, LPCUTF8 string2)
27 return s1.CompareCaseInsensitive(s2);
31 inline BaseAssemblySpec::BaseAssemblySpec()
33 LIMITED_METHOD_CONTRACT;
34 ZeroMemory(this, sizeof(*this));
35 m_context.usMajorVersion = (USHORT) -1;
36 m_context.usMinorVersion = (USHORT) -1;
37 m_context.usBuildNumber = (USHORT) -1;
38 m_context.usRevisionNumber = (USHORT) -1;
41 inline BaseAssemblySpec::~BaseAssemblySpec()
44 if (m_ownedFlags & NAME_OWNED)
45 delete [] m_pAssemblyName;
46 if (m_ownedFlags & PUBLIC_KEY_OR_TOKEN_OWNED)
47 delete [] m_pbPublicKeyOrToken;
48 if (m_wszCodeBase && (m_ownedFlags & CODE_BASE_OWNED))
49 delete [] m_wszCodeBase;
50 if (m_ownedFlags & LOCALE_OWNED)
51 delete [] m_context.szLocale;
52 if (m_szWinRtTypeClassName && (m_ownedFlags & WINRT_TYPE_NAME_OWNED))
53 delete [] m_szWinRtTypeClassName;
54 if (m_szWinRtTypeNamespace && (m_ownedFlags & WINRT_TYPE_NAME_OWNED))
55 delete [] m_szWinRtTypeNamespace;
58 inline HRESULT BaseAssemblySpec::Init(LPCSTR pAssemblyName,
59 const AssemblyMetaDataInternal* pContext,
60 const BYTE * pbPublicKeyOrToken, DWORD cbPublicKeyOrToken,
63 LIMITED_METHOD_CONTRACT;
67 m_pAssemblyName = pAssemblyName;
68 m_pbPublicKeyOrToken = const_cast<BYTE *>(pbPublicKeyOrToken);
69 m_cbPublicKeyOrToken = cbPublicKeyOrToken;
73 m_context = *pContext;
78 inline HRESULT BaseAssemblySpec::Init(LPCSTR pAssemblyDisplayName)
81 m_pAssemblyName = pAssemblyDisplayName;
82 // We eagerly parse the name to allow FusionBind::Hash to avoid throwing.
86 inline VOID BaseAssemblySpec::CloneFields(int ownedFlags)
93 INJECT_FAULT(ThrowOutOfMemory(););
101 if ((~m_ownedFlags & NAME_OWNED) && (ownedFlags & NAME_OWNED) &&
103 size_t len = strlen(m_pAssemblyName) + 1;
104 LPSTR temp = new char [len];
105 strcpy_s(temp, len, m_pAssemblyName);
106 m_pAssemblyName = temp;
107 m_ownedFlags |= NAME_OWNED;
110 if ((~m_ownedFlags & PUBLIC_KEY_OR_TOKEN_OWNED) &&
111 (ownedFlags & PUBLIC_KEY_OR_TOKEN_OWNED) && m_pbPublicKeyOrToken) {
112 BYTE *temp = new BYTE [m_cbPublicKeyOrToken];
113 memcpy(temp, m_pbPublicKeyOrToken, m_cbPublicKeyOrToken);
114 m_pbPublicKeyOrToken = temp;
115 m_ownedFlags |= PUBLIC_KEY_OR_TOKEN_OWNED;
118 if ((~m_ownedFlags & LOCALE_OWNED) && (ownedFlags & LOCALE_OWNED) &&
119 m_context.szLocale) {
120 size_t len = strlen(m_context.szLocale) + 1;
121 LPSTR temp = new char [len];
122 strcpy_s(temp, len, m_context.szLocale);
123 m_context.szLocale = temp;
124 m_ownedFlags |= LOCALE_OWNED;
127 if ((~m_ownedFlags & CODEBASE_OWNED) && (ownedFlags & CODEBASE_OWNED) &&
129 size_t len = wcslen(m_wszCodeBase) + 1;
130 LPWSTR temp = new WCHAR [len];
131 wcscpy_s(temp, len, m_wszCodeBase);
132 m_wszCodeBase = temp;
133 m_ownedFlags |= CODEBASE_OWNED;
136 if ((~m_ownedFlags & WINRT_TYPE_NAME_OWNED) && (ownedFlags & WINRT_TYPE_NAME_OWNED)) {
138 NewArrayHolder<CHAR> nameTemp, namespaceTemp;
140 if (m_szWinRtTypeClassName) {
142 size_t nameLen = strlen(m_szWinRtTypeClassName) + 1;
143 nameTemp = new CHAR [nameLen];
144 strcpy_s(nameTemp, nameLen, m_szWinRtTypeClassName);
147 if (m_szWinRtTypeNamespace){
149 size_t namespaceLen = strlen(m_szWinRtTypeNamespace) + 1;
150 namespaceTemp = new CHAR [namespaceLen];
151 strcpy_s(namespaceTemp, namespaceLen, m_szWinRtTypeNamespace);
154 m_szWinRtTypeClassName = nameTemp.Extract();
155 m_szWinRtTypeNamespace = namespaceTemp.Extract();
156 if (m_szWinRtTypeClassName != NULL || m_szWinRtTypeNamespace != NULL)
158 m_ownedFlags |= WINRT_TYPE_NAME_OWNED;
162 _ASSERTE(hash == Hash());
165 inline VOID BaseAssemblySpec::CloneFieldsToLoaderHeap(int flags, LoaderHeap *pHeap, AllocMemTracker *pamTracker)
173 INJECT_FAULT(ThrowOutOfMemory(););
181 if ((~m_ownedFlags & NAME_OWNED) && (flags &NAME_OWNED) &&
183 size_t len = strlen(m_pAssemblyName) + 1;
184 LPSTR temp = (LPSTR)pamTracker->Track( pHeap->AllocMem(S_SIZE_T (len)) );
185 strcpy_s(temp, len, m_pAssemblyName);
186 m_pAssemblyName = temp;
189 if ((~m_ownedFlags & PUBLIC_KEY_OR_TOKEN_OWNED) && (flags &PUBLIC_KEY_OR_TOKEN_OWNED) &&
190 m_pbPublicKeyOrToken && m_cbPublicKeyOrToken > 0) {
191 BYTE *temp = (BYTE *)pamTracker->Track( pHeap->AllocMem(S_SIZE_T (m_cbPublicKeyOrToken)) );
192 memcpy(temp, m_pbPublicKeyOrToken, m_cbPublicKeyOrToken);
193 m_pbPublicKeyOrToken = temp;
196 if ((~m_ownedFlags & LOCALE_OWNED) && (flags &LOCALE_OWNED) &&
197 m_context.szLocale) {
198 size_t len = strlen(m_context.szLocale) + 1;
199 LPSTR temp = (char *)pamTracker->Track( pHeap->AllocMem(S_SIZE_T (len)) );
200 strcpy_s(temp, len, m_context.szLocale);
201 m_context.szLocale = temp;
204 if ((~m_ownedFlags & CODEBASE_OWNED) && (flags &CODEBASE_OWNED) &&
206 size_t len = wcslen(m_wszCodeBase) + 1;
207 LPWSTR temp = (LPWSTR)pamTracker->Track( pHeap->AllocMem(S_SIZE_T(len*sizeof(WCHAR))) );
208 wcscpy_s(temp, len, m_wszCodeBase);
209 m_wszCodeBase = temp;
212 if ((~m_ownedFlags & WINRT_TYPE_NAME_OWNED) && (flags & WINRT_TYPE_NAME_OWNED)) {
213 if (m_szWinRtTypeNamespace)
215 size_t len = strlen(m_szWinRtTypeNamespace) + 1;
216 LPSTR temp = (LPSTR)pamTracker->Track( pHeap->AllocMem(S_SIZE_T(len*sizeof(CHAR))) );
217 strcpy_s(temp, len, m_szWinRtTypeNamespace);
218 m_szWinRtTypeNamespace = temp;
221 if (m_szWinRtTypeClassName)
223 size_t len = strlen(m_szWinRtTypeClassName) + 1;
224 LPSTR temp = (LPSTR)pamTracker->Track( pHeap->AllocMem(S_SIZE_T(len*sizeof(CHAR))) );
225 strcpy_s(temp, len, m_szWinRtTypeClassName);
226 m_szWinRtTypeClassName = temp;
230 _ASSERTE(hash == Hash());
235 inline void BaseAssemblySpec::CopyFrom(const BaseAssemblySpec *pSpec)
242 INJECT_FAULT(ThrowOutOfMemory(););
246 m_pAssemblyName = pSpec->m_pAssemblyName;
248 m_pbPublicKeyOrToken = pSpec->m_pbPublicKeyOrToken;
249 m_cbPublicKeyOrToken = pSpec->m_cbPublicKeyOrToken;
250 m_dwFlags = pSpec->m_dwFlags;
253 m_wszCodeBase=pSpec->m_wszCodeBase;
254 m_szWinRtTypeNamespace = pSpec->m_szWinRtTypeNamespace;
255 m_szWinRtTypeClassName = pSpec->m_szWinRtTypeClassName;
257 m_context = pSpec->m_context;
259 m_pHostBinder = pSpec->m_pHostBinder;
261 if ((pSpec->m_ownedFlags & BAD_NAME_OWNED) != 0)
263 m_ownedFlags |= BAD_NAME_OWNED;
267 m_pBindingContext = pSpec->m_pBindingContext;
272 inline DWORD BaseAssemblySpec::Hash()
282 return HashString(m_wszCodeBase);
288 hash ^= HashStringA(m_pAssemblyName);
289 hash = _rotl(hash, 4);
291 hash ^= HashBytes(m_pbPublicKeyOrToken, m_cbPublicKeyOrToken);
292 hash = _rotl(hash, 4);
295 hash = _rotl(hash, 4);
298 hash ^= m_context.usMajorVersion;
299 hash = _rotl(hash, 8);
301 if (m_context.usMajorVersion != (USHORT) -1) {
302 hash ^= m_context.usMinorVersion;
303 hash = _rotl(hash, 8);
305 if (m_context.usMinorVersion != (USHORT) -1) {
306 hash ^= m_context.usBuildNumber;
307 hash = _rotl(hash, 8);
309 if (m_context.usBuildNumber != (USHORT) -1) {
310 hash ^= m_context.usRevisionNumber;
311 hash = _rotl(hash, 8);
316 if (m_context.szLocale)
317 hash ^= HashStringA(m_context.szLocale);
318 hash = _rotl(hash, 4);
320 if (m_szWinRtTypeNamespace)
322 hash ^= HashStringA(m_szWinRtTypeNamespace);
323 hash = _rotl(hash, 4);
326 if (m_szWinRtTypeClassName)
328 hash ^= HashStringA(m_szWinRtTypeClassName);
329 hash = _rotl(hash, 4);
337 inline BOOL BaseAssemblySpec::CompareEx(BaseAssemblySpec *pSpec, DWORD dwCompareFlags)
342 if(m_wszCodeBase || pSpec->m_wszCodeBase)
344 if(!m_wszCodeBase || !pSpec->m_wszCodeBase)
346 return wcscmp(m_wszCodeBase,(pSpec->m_wszCodeBase))==0;
351 if (m_pAssemblyName != pSpec->m_pAssemblyName
352 && (m_pAssemblyName == NULL || pSpec->m_pAssemblyName == NULL
353 || strcmp(m_pAssemblyName, pSpec->m_pAssemblyName)))
356 if (m_cbPublicKeyOrToken != pSpec->m_cbPublicKeyOrToken
357 || memcmp(m_pbPublicKeyOrToken, pSpec->m_pbPublicKeyOrToken, m_cbPublicKeyOrToken))
361 if (m_dwFlags != pSpec->m_dwFlags)
364 if (m_context.usMajorVersion != pSpec->m_context.usMajorVersion)
367 if (m_context.usMajorVersion != (USHORT) -1) {
368 if (m_context.usMinorVersion != pSpec->m_context.usMinorVersion)
371 if (m_context.usMinorVersion != (USHORT) -1) {
372 if (m_context.usBuildNumber != pSpec->m_context.usBuildNumber)
375 if (m_context.usBuildNumber != (USHORT) -1) {
376 if (m_context.usRevisionNumber != pSpec->m_context.usRevisionNumber)
382 if (m_context.szLocale != pSpec->m_context.szLocale
383 && (m_context.szLocale == NULL || pSpec->m_context.szLocale == NULL
384 || strcmp(m_context.szLocale, pSpec->m_context.szLocale)))
388 // If the assemblySpec contains the binding context, then check if they match.
389 if (!(pSpec->IsAssemblySpecForMscorlib() && IsAssemblySpecForMscorlib()))
391 if (!AreSameBinderInstance(pSpec->m_pBindingContext, m_pBindingContext))
402 inline HRESULT BaseAssemblySpec::Init(mdToken kAssemblyToken,
403 IMDInternalImport *pImport)
414 if (TypeFromToken(kAssemblyToken) == mdtAssembly) {
416 IfFailRet(pImport->GetAssemblyProps(kAssemblyToken,
417 (const void **) &m_pbPublicKeyOrToken,
418 &m_cbPublicKeyOrToken,
424 if (m_cbPublicKeyOrToken != 0)
425 m_dwFlags |= afPublicKey;
428 IfFailRet(pImport->GetAssemblyRefProps(kAssemblyToken,
429 (const void**) &m_pbPublicKeyOrToken,
430 &m_cbPublicKeyOrToken,
437 // When m_cbPublicKeyOrToken is 0, a NULL in m_pbPublicKeyOrToken indicates that public key or token
438 // is not specified, while a non-NULL in m_pbPublicKeyOrToken indicates an empty public key (i.e.,
439 // a non-strongnamed assembly). However, the MetaData API puts a random value in m_pbPublicKeyOrToken
440 // when m_cbPublicKeyOrToken is 0. Since AssemblyDef or AssemblyRef can't using partial name, we
441 // always ensure that m_pbPublicKeyOrToken is not NULL.
442 if (m_cbPublicKeyOrToken == 0)
443 m_pbPublicKeyOrToken = (PBYTE)1;
448 inline HRESULT BaseAssemblySpec::Init(mdToken tkAssemblyRef,
449 IMetaDataAssemblyImport *pImport)
459 // Retrieve size of assembly name
460 ASSEMBLYMETADATA sContext;
461 LPWSTR wszAssemblyName=NULL;
462 ZeroMemory(&sContext, sizeof(ASSEMBLYMETADATA));
464 if(TypeFromToken(tkAssemblyRef) == mdtAssembly)
467 IfFailRet(pImport->GetAssemblyProps(tkAssemblyRef, // [IN] The Assembly for which to get the properties.
468 NULL, // [OUT] Pointer to the public key or token.
469 NULL, // [OUT] Count of bytes in the public key or token.
470 NULL, // [OUT] Hash Algorithm
471 NULL, // [OUT] Buffer to fill with name.
472 NULL, // [IN] Size of buffer in wide chars.
473 &cchName, // [OUT] Actual # of wide chars in name.
474 &sContext, // [OUT] Assembly MetaData.
475 NULL)); // [OUT] Flags.
477 // Get the assembly name other naming properties
478 wszAssemblyName = (LPWSTR)_alloca(cchName * sizeof(WCHAR));
479 IfFailRet(pImport->GetAssemblyProps(tkAssemblyRef,
480 (const void **)&m_pbPublicKeyOrToken,
481 &m_cbPublicKeyOrToken,
489 else if(TypeFromToken(tkAssemblyRef) == mdtAssemblyRef)
492 IfFailRet(pImport->GetAssemblyRefProps(tkAssemblyRef, // [IN] The AssemblyRef for which to get the properties.
493 NULL, // [OUT] Pointer to the public key or token.
494 NULL, // [OUT] Count of bytes in the public key or token.
495 NULL, // [OUT] Buffer to fill with name.
496 NULL, // [IN] Size of buffer in wide chars.
497 &cchName, // [OUT] Actual # of wide chars in name.
498 &sContext, // [OUT] Assembly MetaData.
499 NULL, // [OUT] Hash blob.
500 NULL, // [OUT] Count of bytes in the hash blob.
501 NULL)); // [OUT] Flags.
503 // Get the assembly name other naming properties
504 wszAssemblyName = (LPWSTR)_alloca(cchName * sizeof(WCHAR));
505 IfFailRet(pImport->GetAssemblyRefProps(tkAssemblyRef,
506 (const void **)&m_pbPublicKeyOrToken,
507 &m_cbPublicKeyOrToken,
518 _ASSERTE(false && "unexpected token");
520 MAKE_UTF8PTR_FROMWIDE_NOTHROW(szAssemblyName,wszAssemblyName);
521 IfNullRet(szAssemblyName);
522 size_t len=strlen(szAssemblyName)+1;
523 NewArrayHolder<char> assemblyName(new(nothrow) char[len]);
524 IfNullRet(assemblyName);
525 strcpy_s(assemblyName,len,szAssemblyName);
527 m_pAssemblyName=assemblyName.Extract();
528 m_ownedFlags |= CODEBASE_OWNED;
529 SetContext(&sContext);
533 inline void BaseAssemblySpec::SetCodeBase(LPCWSTR szCodeBase)
543 if(m_wszCodeBase && (m_ownedFlags & CODEBASE_OWNED))
544 delete m_wszCodeBase;
545 m_ownedFlags &= ~CODEBASE_OWNED;
546 m_wszCodeBase=szCodeBase;
549 inline LPCWSTR BaseAssemblySpec::GetCodeBase()
551 LIMITED_METHOD_CONTRACT;
552 return m_wszCodeBase;
555 inline void BaseAssemblySpec::SetName(LPCSTR szName)
565 if (m_pAssemblyName && (m_ownedFlags & NAME_OWNED))
566 delete [] m_pAssemblyName;
567 m_ownedFlags &= ~NAME_OWNED;
568 m_pAssemblyName = szName;
571 inline void BaseAssemblySpec::SetCulture(LPCSTR szCulture)
573 LIMITED_METHOD_CONTRACT;
574 if (m_context.szLocale && (m_ownedFlags & LOCALE_OWNED))
575 delete [] m_context.szLocale;
576 m_ownedFlags &= ~LOCALE_OWNED;
577 if (strcmp(szCulture,"neutral")==0)
578 m_context.szLocale="";
580 m_context.szLocale=szCulture;
583 inline bool BaseAssemblySpec::IsNeutralCulture()
585 return strcmp(m_context.szLocale,"")==0;
588 inline void BaseAssemblySpec::SetContext(ASSEMBLYMETADATA* assemblyData)
590 LIMITED_METHOD_CONTRACT;
591 m_context.usMajorVersion=assemblyData->usMajorVersion;
592 m_context.usMinorVersion=assemblyData->usMinorVersion;
593 m_context.usBuildNumber=assemblyData->usBuildNumber;
594 m_context.usRevisionNumber=assemblyData->usRevisionNumber;
595 m_context.rProcessor=assemblyData->rProcessor;
596 m_context.ulProcessor=assemblyData->ulProcessor;
597 m_context.rOS=assemblyData->rOS;
598 m_context.ulOS=assemblyData->ulOS;
599 m_context.szLocale="";
602 inline BOOL BaseAssemblySpec::IsStrongNamed() const
604 LIMITED_METHOD_CONTRACT;
605 return m_cbPublicKeyOrToken;
608 inline BOOL BaseAssemblySpec::HasPublicKey() const
610 LIMITED_METHOD_CONTRACT;
611 return IsAfPublicKey(m_dwFlags) && m_cbPublicKeyOrToken != 0;
614 inline BOOL BaseAssemblySpec::HasPublicKeyToken() const
616 LIMITED_METHOD_CONTRACT;
617 return IsAfPublicKeyToken(m_dwFlags) && m_cbPublicKeyOrToken != 0;
620 inline LPCSTR BaseAssemblySpec::GetName() const
622 LIMITED_METHOD_CONTRACT;
623 return m_pAssemblyName;
628 inline BOOL BaseAssemblySpec::VerifyBindingString(LPCWSTR pwStr)
631 if (wcschr(pwStr, '\\') ||
632 wcschr(pwStr, '/') ||
640 #endif // __BASE_ASSEMBLY_SPEC_INL__