Fix trigger for tier 1 call counting delay (#17477)
[platform/upstream/coreclr.git] / src / binder / assemblyname.cpp
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 // ============================================================
5 //
6 // AssemblyName.cpp
7 //
8
9
10 //
11 // Implements the AssemblyName class
12 //
13 // ============================================================
14
15 #define DISABLE_BINDER_DEBUG_LOGGING
16
17 #include "assemblyname.hpp"
18 #include "assembly.hpp"
19 #include "utils.hpp"
20 #include "variables.hpp"
21
22 #include "fusionassemblyname.hpp"
23
24 #include "textualidentityparser.hpp"
25
26 #include "corpriv.h"
27
28 #include "ex.h"
29
30 namespace BINDER_SPACE
31 {
32     AssemblyName::AssemblyName()
33     {
34         m_cRef = 1;
35         m_dwNameFlags = NAME_FLAG_NONE;
36         // Default values present in every assembly name
37         SetHave(AssemblyIdentity::IDENTITY_FLAG_CULTURE |
38                 AssemblyIdentity::IDENTITY_FLAG_PUBLIC_KEY_TOKEN_NULL);
39     }
40
41     AssemblyName::~AssemblyName()
42     {
43         //  Nothing to do here
44     }
45
46     HRESULT AssemblyName::Init(IMDInternalImport       *pIMetaDataAssemblyImport,
47                                PEKIND                   PeKind,
48                                mdAssemblyRef            mdar /* = 0 */,
49                                BOOL                     fIsDefinition /* = TRUE */)
50     {
51         HRESULT hr = S_OK;
52         mdAssembly mda = 0;
53         AssemblyMetaDataInternal amd = {0};
54         CONST VOID *pvPublicKeyToken = NULL;
55         DWORD dwPublicKeyToken = 0;
56         LPCSTR pAssemblyName = NULL;
57         DWORD dwRefOrDefFlags = 0;
58         DWORD dwHashAlgId = 0;
59
60         BINDER_LOG_ENTER(L"AssemblyName::Init(IMetaDataAssemblyImport)");
61
62         if (fIsDefinition)
63         {
64             // Get the assembly token
65             IF_FAIL_GO(pIMetaDataAssemblyImport->GetAssemblyFromScope(&mda));
66         }
67
68         BINDER_LOG(L"Have mda scope!");
69
70         // Get name and metadata
71         if (fIsDefinition)
72         {
73             IF_FAIL_GO(pIMetaDataAssemblyImport->GetAssemblyProps(             
74                             mda,            // [IN] The Assembly for which to get the properties.
75                             &pvPublicKeyToken,  // [OUT] Pointer to the PublicKeyToken blob.
76                             &dwPublicKeyToken,  // [OUT] Count of bytes in the PublicKeyToken Blob.
77                             &dwHashAlgId,   // [OUT] Hash Algorithm.
78                             &pAssemblyName, // [OUT] Name.
79                             &amd,           // [OUT] Assembly MetaData.
80                             &dwRefOrDefFlags // [OUT] Flags.
81                             ));
82         }
83         else
84         {
85             IF_FAIL_GO(pIMetaDataAssemblyImport->GetAssemblyRefProps(             
86                             mdar,            // [IN] The Assembly for which to get the properties.
87                             &pvPublicKeyToken,  // [OUT] Pointer to the PublicKeyToken blob.
88                             &dwPublicKeyToken,  // [OUT] Count of bytes in the PublicKeyToken Blob.
89                             &pAssemblyName, // [OUT] Name.
90                             &amd,           // [OUT] Assembly MetaData.
91                             NULL, // [OUT] Hash blob.
92                             NULL, // [OUT] Count of bytes in hash blob.
93                             &dwRefOrDefFlags // [OUT] Flags.
94                             ));
95         }
96
97         BINDER_LOG(L"Have props!");
98
99         {
100             StackSString culture;
101             culture.SetUTF8(amd.szLocale);
102             culture.Normalize();
103
104             SString::CIterator itr = culture.Begin();
105             if (culture.Find(itr, L';'))
106             {
107                 culture = SString(culture, culture.Begin(), itr-1);
108             }
109
110             SetCulture(culture);
111         }
112
113         {
114             StackSString assemblyName;
115             assemblyName.SetUTF8(pAssemblyName);
116             assemblyName.Normalize();
117
118             COUNT_T assemblyNameLength = assemblyName.GetCount();
119             if (assemblyNameLength == 0 || assemblyNameLength >= MAX_PATH_FNAME)
120             {
121                 IF_FAIL_GO(FUSION_E_INVALID_NAME);
122             }
123
124             SetSimpleName(assemblyName);
125         }
126
127         // See if the assembly[def] is retargetable (ie, for a generic assembly).
128         if (IsAfRetargetable(dwRefOrDefFlags))
129         {
130             SetIsRetargetable(TRUE);
131         }
132         
133         // Set ContentType
134         if (IsAfContentType_Default(dwRefOrDefFlags))
135         {
136             SetContentType(AssemblyContentType_Default);
137         }
138         else if (IsAfContentType_WindowsRuntime(dwRefOrDefFlags))
139         {
140             SetContentType(AssemblyContentType_WindowsRuntime);
141         }
142         else
143         {
144             IF_FAIL_GO(FUSION_E_INVALID_NAME);
145         }
146         
147         // Set the assembly version
148         {
149             AssemblyVersion *pAssemblyVersion = GetVersion();
150
151             pAssemblyVersion->SetFeatureVersion(amd.usMajorVersion, amd.usMinorVersion);
152             pAssemblyVersion->SetServiceVersion(amd.usBuildNumber, amd.usRevisionNumber);
153             SetHave(AssemblyIdentity::IDENTITY_FLAG_VERSION);
154         }
155
156         // Set public key and/or public key token (if we have it)
157         if (pvPublicKeyToken && dwPublicKeyToken)
158         {
159             SBuffer publicKeyOrTokenBLOB((const BYTE *) pvPublicKeyToken, dwPublicKeyToken);
160
161             if (IsAfPublicKey(dwRefOrDefFlags))
162             {
163                 SBuffer publicKeyTokenBLOB;
164
165                 IF_FAIL_GO(GetTokenFromPublicKey(publicKeyOrTokenBLOB, publicKeyTokenBLOB));
166                 GetPublicKeyTokenBLOB().Set(publicKeyTokenBLOB);
167             }
168             else
169             {
170                 GetPublicKeyTokenBLOB().Set(publicKeyOrTokenBLOB);
171             }
172             
173             SetHave(AssemblyIdentity::IDENTITY_FLAG_PUBLIC_KEY_TOKEN);
174         }
175
176         SetArchitecture(PeKind);
177
178     Exit:
179         BINDER_LOG_LEAVE_HR(L"AssemblyName::Init(IMetaDataAssemblyImport)", hr);
180         return hr;
181     }
182
183     HRESULT AssemblyName::Init(SString &assemblyDisplayName)
184     {
185         HRESULT hr = S_OK;
186         BINDER_LOG_ENTER(L"AssemblyName::Init(assemblyDisplayName)");
187
188         BINDER_LOG_STRING(L"assemblyDisplayName", assemblyDisplayName);
189
190         IF_FAIL_GO(TextualIdentityParser::Parse(assemblyDisplayName, this));
191         
192     Exit:
193         BINDER_LOG_LEAVE_HR(L"AssemblyName::Init(assemblyDisplayName)", hr);
194         return hr;
195     }
196
197     HRESULT AssemblyName::Init(IAssemblyName *pIAssemblyName)
198     {
199         HRESULT hr = S_OK;
200         
201         _ASSERTE(pIAssemblyName != NULL);
202         
203         EX_TRY
204         {
205             {
206                 // Set the simpleName
207                 StackSString simpleName;
208                 hr = fusion::util::GetSimpleName(pIAssemblyName, simpleName);
209                 IF_FAIL_GO(hr);
210                 SetSimpleName(simpleName);
211                 SetHave(BINDER_SPACE::AssemblyIdentity::IDENTITY_FLAG_SIMPLE_NAME);
212             }
213
214             // Display version
215             DWORD dwVersionParts[4] = {0,0,0,0};
216             DWORD cbVersionSize = sizeof(dwVersionParts[0]);
217             hr = fusion::util::GetProperty(pIAssemblyName, ASM_NAME_MAJOR_VERSION, static_cast<PVOID>(&dwVersionParts[0]), &cbVersionSize);
218             IF_FAIL_GO(hr);
219             if ((hr == S_OK) && (cbVersionSize != 0))
220             {
221                 // Property is present - loop to get the individual version details
222                 for(DWORD i = 0; i < 4; i++) 
223                 {
224                     cbVersionSize = sizeof(dwVersionParts[i]);
225                     hr = fusion::util::GetProperty(pIAssemblyName, ASM_NAME_MAJOR_VERSION+i, static_cast<PVOID>(&dwVersionParts[i]), &cbVersionSize);
226                     IF_FAIL_GO(hr);
227                 }
228
229                 m_version.SetFeatureVersion(dwVersionParts[0], dwVersionParts[1]);
230                 m_version.SetServiceVersion(dwVersionParts[2], dwVersionParts[3]);
231                 SetHave(BINDER_SPACE::AssemblyIdentity::IDENTITY_FLAG_VERSION);
232             }
233
234             {
235                 // Display culture
236                 StackSString culture;
237                 hr = fusion::util::GetProperty(pIAssemblyName, ASM_NAME_CULTURE, culture);
238                 IF_FAIL_GO(hr);
239                 if (hr == S_OK)
240                 {
241                     SetCulture(culture);
242                     SetHave(BINDER_SPACE::AssemblyIdentity::IDENTITY_FLAG_CULTURE);
243                 }
244             }
245
246             {
247                 // Display public key token
248                 NewArrayHolder<BYTE> pPublicKeyToken;
249                 DWORD cbPublicKeyToken = 0;
250                 hr = fusion::util::GetProperty(pIAssemblyName, ASM_NAME_PUBLIC_KEY_TOKEN, static_cast<PBYTE*>(&pPublicKeyToken), &cbPublicKeyToken);
251                 IF_FAIL_GO(hr);
252                 if ((hr == S_OK) && (cbPublicKeyToken != 0))
253                 {
254                     m_publicKeyOrTokenBLOB.Set(pPublicKeyToken, cbPublicKeyToken);
255                     SetHave(BINDER_SPACE::AssemblyIdentity::IDENTITY_FLAG_PUBLIC_KEY_TOKEN);
256                 }
257                 else
258                 {
259                     SetHave(BINDER_SPACE::AssemblyIdentity::IDENTITY_FLAG_PUBLIC_KEY_TOKEN_NULL);
260                 }
261             }
262
263             // Display processor architecture
264             DWORD peKind = 0;
265             DWORD cbPeKind = sizeof(peKind);
266             hr = fusion::util::GetProperty(pIAssemblyName, ASM_NAME_ARCHITECTURE, static_cast<PVOID>(&peKind), &cbPeKind);
267             IF_FAIL_GO(hr);
268             if ((hr == S_OK) && (cbPeKind != 0))
269             {
270                 PEKIND PeKind = (PEKIND)peKind;
271                 if (PeKind != peNone) 
272                 {
273                     SetArchitecture(PeKind);
274                     SetHave(BINDER_SPACE::AssemblyIdentity::IDENTITY_FLAG_PROCESSOR_ARCHITECTURE);
275                 }
276             }
277
278             // Display retarget flag
279             BOOL fRetarget = FALSE;
280             DWORD cbRetarget = sizeof(fRetarget);
281             hr = fusion::util::GetProperty(pIAssemblyName, ASM_NAME_RETARGET, static_cast<PVOID>(&fRetarget), &cbRetarget);
282             IF_FAIL_GO(hr);
283             if ((hr == S_OK) && (cbRetarget != 0))
284             {
285                 if (fRetarget)
286                 {
287                     SetIsRetargetable(fRetarget);
288                     SetHave(BINDER_SPACE::AssemblyIdentity::IDENTITY_FLAG_RETARGETABLE);
289                 }
290             }
291
292             // Display content type
293             DWORD dwContentType = AssemblyContentType_Default;
294             DWORD cbContentType = sizeof(dwContentType);
295             hr = fusion::util::GetProperty(pIAssemblyName, ASM_NAME_CONTENT_TYPE, static_cast<PVOID>(&dwContentType), &cbContentType);
296             IF_FAIL_GO(hr);
297             if ((hr == S_OK) && (cbContentType != 0))
298             {
299                 if (dwContentType != AssemblyContentType_Default)
300                 {
301                     SetHave(BINDER_SPACE::AssemblyIdentity::IDENTITY_FLAG_CONTENT_TYPE);
302                     SetContentType((AssemblyContentType)dwContentType);
303                 }
304             }
305
306             {
307                 // Display custom flag. Dont set it if it is not present since that will end up adding the "Custom=null" attribute
308                 // in the displayname of the assembly that maybe generated using this AssemblyName instance. This could create conflict when
309                 // the displayname is generated from the assembly directly as that will not have a "Custom" field set.
310                 NewArrayHolder<BYTE> pCustomBLOB;
311                 DWORD cbCustomBLOB = 0;
312                 hr = fusion::util::GetProperty(pIAssemblyName, ASM_NAME_CUSTOM, static_cast<PBYTE*>(&pCustomBLOB), &cbCustomBLOB);
313                 IF_FAIL_GO(hr);
314                 if ((hr == S_OK) && (cbCustomBLOB != 0))
315                 {
316                     m_customBLOB.Set(pCustomBLOB, cbCustomBLOB);
317                     SetHave(BINDER_SPACE::AssemblyIdentity::IDENTITY_FLAG_CUSTOM);
318                 }
319             }
320         }
321         EX_CATCH_HRESULT(hr);
322 Exit:        
323         return hr;
324     }
325     
326     HRESULT AssemblyName::CreateFusionName(IAssemblyName **ppIAssemblyName)
327     {
328         HRESULT hr = S_OK;
329         ReleaseHolder<IAssemblyName> pIAssemblyName;
330
331         IF_FAIL_GO(CreateAssemblyNameObject(&pIAssemblyName, NULL, 0, NULL));
332
333         IF_FAIL_GO(LegacyFusion::SetStringProperty(pIAssemblyName, ASM_NAME_NAME, GetSimpleName()));
334
335         if (Have(AssemblyIdentity::IDENTITY_FLAG_VERSION))
336         {
337             AssemblyVersion *pAssemblyVersion = GetVersion();
338
339             IF_FAIL_GO(LegacyFusion::SetWordProperty(pIAssemblyName,
340                                        ASM_NAME_MAJOR_VERSION,
341                                        pAssemblyVersion->GetMajor()));
342             IF_FAIL_GO(LegacyFusion::SetWordProperty(pIAssemblyName,
343                                        ASM_NAME_MINOR_VERSION,
344                                        pAssemblyVersion->GetMinor()));
345             IF_FAIL_GO(LegacyFusion::SetWordProperty(pIAssemblyName,
346                                        ASM_NAME_BUILD_NUMBER,
347                                        pAssemblyVersion->GetBuild()));
348             IF_FAIL_GO(LegacyFusion::SetWordProperty(pIAssemblyName,
349                                        ASM_NAME_REVISION_NUMBER,
350                                        pAssemblyVersion->GetRevision()));
351         }
352
353         if (Have(AssemblyIdentity::IDENTITY_FLAG_CULTURE))
354         {
355             IF_FAIL_GO(LegacyFusion::SetStringProperty(pIAssemblyName, ASM_NAME_CULTURE, GetCulture()));
356         }
357
358         if (Have(AssemblyIdentity::IDENTITY_FLAG_PUBLIC_KEY))
359         {
360             // GetPublicKeyTokenBLOB contains either PK or PKT.
361             IF_FAIL_GO(LegacyFusion::SetBufferProperty(pIAssemblyName,
362                                          ASM_NAME_PUBLIC_KEY,
363                                          GetPublicKeyTokenBLOB()));
364         }
365         else if (Have(AssemblyIdentity::IDENTITY_FLAG_PUBLIC_KEY_TOKEN))
366         {
367             // GetPublicKeyTokenBLOB contains either PK or PKT.
368             IF_FAIL_GO(LegacyFusion::SetBufferProperty(pIAssemblyName,
369                                          ASM_NAME_PUBLIC_KEY_TOKEN,
370                                          GetPublicKeyTokenBLOB()));
371         }
372
373         if (Have(AssemblyIdentity::IDENTITY_FLAG_PROCESSOR_ARCHITECTURE))
374         {
375             IF_FAIL_GO(LegacyFusion::SetDwordProperty(pIAssemblyName,
376                                         ASM_NAME_ARCHITECTURE,
377                                         static_cast<DWORD>(GetArchitecture())));
378         }
379
380         if (Have(AssemblyIdentity::IDENTITY_FLAG_CONTENT_TYPE))
381         {
382             IF_FAIL_GO(LegacyFusion::SetDwordProperty(pIAssemblyName,
383                                         ASM_NAME_CONTENT_TYPE,
384                                         GetContentType()));
385         }
386         
387         *ppIAssemblyName = pIAssemblyName.Extract();
388
389     Exit:
390         return hr;
391     }
392
393     ULONG AssemblyName::AddRef()
394     {
395         return InterlockedIncrement(&m_cRef);
396     }
397
398     ULONG AssemblyName::Release()
399     {
400         ULONG ulRef = InterlockedDecrement(&m_cRef);
401         if (ulRef == 0) 
402         {
403             delete this;
404         }
405         return ulRef;
406     }
407
408     SString &AssemblyName::GetDeNormalizedCulture()
409     {
410         SString &culture = GetCulture();
411
412         if (EqualsCaseInsensitive(culture, g_BinderVariables->cultureNeutral))
413         {
414             culture = g_BinderVariables->emptyString;
415         }
416
417         return culture;
418     }
419
420     BOOL AssemblyName::IsStronglyNamed()
421     {
422         return Have(AssemblyIdentity::IDENTITY_FLAG_PUBLIC_KEY_TOKEN);
423     }
424     
425     BOOL AssemblyName::IsMscorlib()
426     {
427         // TODO: Is this simple comparison enough?
428         return EqualsCaseInsensitive(GetSimpleName(), g_BinderVariables->mscorlib);
429     }
430
431     HRESULT AssemblyName::SetArchitecture(SString &architecture)
432     {
433         HRESULT hr = S_OK;
434
435         if (architecture.IsEmpty())
436         {
437             SetArchitecture(peNone);
438         }
439         else if (EqualsCaseInsensitive(architecture, g_BinderVariables->architectureMSIL))
440         {
441             SetArchitecture(peMSIL);
442         }
443         else if (EqualsCaseInsensitive(architecture, g_BinderVariables->architectureX86))
444         {
445             SetArchitecture(peI386);
446         }
447         else if (EqualsCaseInsensitive(architecture, g_BinderVariables->architectureAMD64))
448         {
449             SetArchitecture(peAMD64);
450         }
451         else if (EqualsCaseInsensitive(architecture, g_BinderVariables->architectureARM))
452         {
453             SetArchitecture(peARM);
454         }
455         else if (EqualsCaseInsensitive(architecture, g_BinderVariables->architectureARM64))
456         {
457             SetArchitecture(peARM64);
458         }
459         else
460         {
461             hr = FUSION_E_MANIFEST_PARSE_ERROR;
462         }
463
464         return hr;
465     }
466
467     ULONG AssemblyName::Hash(DWORD dwIncludeFlags)
468     {
469         DWORD dwHash = 0;
470         DWORD dwUseIdentityFlags = m_dwIdentityFlags;
471
472         // Prune unwanted name parts
473         if ((dwIncludeFlags & INCLUDE_VERSION) == 0)
474         {
475             dwUseIdentityFlags &= ~AssemblyIdentity::IDENTITY_FLAG_VERSION;
476         }
477         if ((dwIncludeFlags & INCLUDE_ARCHITECTURE) == 0)
478         {
479             dwUseIdentityFlags &= ~AssemblyIdentity::IDENTITY_FLAG_PROCESSOR_ARCHITECTURE;
480         }
481         if ((dwIncludeFlags & INCLUDE_RETARGETABLE) == 0)
482         {
483             dwUseIdentityFlags &= ~AssemblyIdentity::IDENTITY_FLAG_RETARGETABLE;
484         }
485         if ((dwIncludeFlags & INCLUDE_CONTENT_TYPE) == 0)
486         {
487             dwUseIdentityFlags &= ~AssemblyIdentity::IDENTITY_FLAG_CONTENT_TYPE;
488         }
489
490         dwHash ^= static_cast<DWORD>(HashCaseInsensitive(GetSimpleName()));
491         dwHash = _rotl(dwHash, 4);
492
493         if (AssemblyIdentity::Have(dwUseIdentityFlags,
494                                    AssemblyIdentity::IDENTITY_FLAG_PUBLIC_KEY) ||
495             AssemblyIdentity::Have(dwUseIdentityFlags,
496                                    AssemblyIdentity::IDENTITY_FLAG_PUBLIC_KEY_TOKEN))
497         {
498             const BYTE *pbPublicKeyOrToken = GetPublicKeyTokenBLOB();
499             DWORD dwcbPublicKeyOrToken = GetPublicKeyTokenBLOB().GetSize();
500
501             _ASSERTE(pbPublicKeyOrToken != NULL);
502
503             dwHash ^= HashBytes(pbPublicKeyOrToken, dwcbPublicKeyOrToken);
504             dwHash = _rotl(dwHash, 4);
505         }
506
507         if (AssemblyIdentity::Have(dwUseIdentityFlags, AssemblyIdentity::IDENTITY_FLAG_VERSION))
508         {
509             AssemblyVersion *pAssemblyVersion = GetVersion();
510
511             dwHash ^= pAssemblyVersion->GetMajor();
512             dwHash = _rotl(dwHash, 8);
513             dwHash ^= pAssemblyVersion->GetMinor();
514             dwHash = _rotl(dwHash, 8);
515             dwHash ^= pAssemblyVersion->GetBuild();
516             dwHash = _rotl(dwHash, 8);
517             dwHash ^= pAssemblyVersion->GetRevision();
518             dwHash = _rotl(dwHash, 8);
519         }
520
521         if (AssemblyIdentity::Have(dwUseIdentityFlags, AssemblyIdentity::IDENTITY_FLAG_CULTURE))
522         {
523             dwHash ^= static_cast<DWORD>(HashCaseInsensitive(GetNormalizedCulture()));
524             dwHash = _rotl(dwHash, 4);
525         }
526
527         if (AssemblyIdentity::Have(dwUseIdentityFlags,
528                                    AssemblyIdentity::IDENTITY_FLAG_RETARGETABLE))
529         {
530             dwHash ^= 1;
531             dwHash = _rotl(dwHash, 4);
532         }
533
534         if (AssemblyIdentity::Have(dwUseIdentityFlags,
535                                    AssemblyIdentity::IDENTITY_FLAG_PROCESSOR_ARCHITECTURE))
536         {
537             dwHash ^= static_cast<DWORD>(GetArchitecture());
538             dwHash = _rotl(dwHash, 4);
539         }
540
541         if (AssemblyIdentity::Have(dwUseIdentityFlags,
542                                    AssemblyIdentity::IDENTITY_FLAG_CONTENT_TYPE))
543         {
544             dwHash ^= static_cast<DWORD>(GetContentType());
545             dwHash = _rotl(dwHash, 4);
546         }
547
548         return static_cast<ULONG>(dwHash);
549     }
550
551     BOOL AssemblyName::Equals(AssemblyName *pAssemblyName,
552                               DWORD         dwIncludeFlags)
553     {
554         BOOL fEquals = FALSE;
555
556         if (GetContentType() == AssemblyContentType_WindowsRuntime)
557         {   // Assembly is meaningless for WinRT, all assemblies form one joint type namespace
558             return (GetContentType() == pAssemblyName->GetContentType());
559         }
560         
561         if (EqualsCaseInsensitive(GetSimpleName(), pAssemblyName->GetSimpleName()) &&
562             (GetContentType() == pAssemblyName->GetContentType()))
563         {
564             fEquals = TRUE;
565
566             if ((dwIncludeFlags & EXCLUDE_CULTURE) == 0)
567             {
568                 fEquals = EqualsCaseInsensitive(GetNormalizedCulture(), pAssemblyName->GetNormalizedCulture());
569             }
570
571             if (fEquals && (dwIncludeFlags & INCLUDE_PUBLIC_KEY_TOKEN) != 0)
572             {
573                 fEquals = (GetPublicKeyTokenBLOB().Equals(pAssemblyName->GetPublicKeyTokenBLOB()));
574             }
575             
576             if (fEquals && ((dwIncludeFlags & INCLUDE_ARCHITECTURE) != 0))
577             {
578                 fEquals = (GetArchitecture() == pAssemblyName->GetArchitecture());
579             }
580
581             if (fEquals && ((dwIncludeFlags & INCLUDE_VERSION) != 0))
582             {
583                 fEquals = GetVersion()->Equals(pAssemblyName->GetVersion());
584             }
585
586             if (fEquals && ((dwIncludeFlags & INCLUDE_RETARGETABLE) != 0))
587             {
588                 fEquals = (GetIsRetargetable() == pAssemblyName->GetIsRetargetable());
589             }
590         }
591
592         return fEquals;
593     }
594
595     BOOL AssemblyName::RefEqualsDef(AssemblyName *pAssemblyNameDef,
596                                     BOOL          fInspectionOnly)
597     {
598         BOOL fEquals = FALSE;
599         
600         if (GetContentType() == AssemblyContentType_WindowsRuntime)
601         {   // Assembly is meaningless for WinRT, all assemblies form one joint type namespace
602             return (GetContentType() == pAssemblyNameDef->GetContentType());
603         }
604         
605         if (EqualsCaseInsensitive(GetSimpleName(), pAssemblyNameDef->GetSimpleName()) &&
606             EqualsCaseInsensitive(GetNormalizedCulture(),
607                                   pAssemblyNameDef->GetNormalizedCulture()) &&
608             GetPublicKeyTokenBLOB().Equals(pAssemblyNameDef->GetPublicKeyTokenBLOB()) && 
609             (GetContentType() == pAssemblyNameDef->GetContentType()))
610         {
611             PEKIND kRefArchitecture = GetArchitecture();
612             PEKIND kDefArchitecture = pAssemblyNameDef->GetArchitecture();
613
614             if (kRefArchitecture == peNone)
615             {
616                 fEquals = (fInspectionOnly || 
617                            (kDefArchitecture == peNone) ||
618                            (kDefArchitecture == peMSIL) ||
619                            (kDefArchitecture == Assembly::GetSystemArchitecture()));
620             }
621             else
622             {
623                 fEquals = (kRefArchitecture == kDefArchitecture);
624             }
625         }
626
627         return fEquals;
628     }
629
630     HRESULT AssemblyName::Clone(AssemblyName **ppAssemblyName)
631     {
632         HRESULT hr = S_OK;
633         AssemblyName *pClonedAssemblyName = NULL;
634
635         SAFE_NEW(pClonedAssemblyName, AssemblyName);
636         CloneInto(pClonedAssemblyName);
637         pClonedAssemblyName->m_dwNameFlags = m_dwNameFlags;
638
639         *ppAssemblyName = pClonedAssemblyName;
640
641     Exit:
642         return hr;
643     }
644
645     void AssemblyName::GetDisplayName(PathString &displayName,
646                                       DWORD       dwIncludeFlags)
647     {
648         DWORD dwUseIdentityFlags = m_dwIdentityFlags;
649
650         // Prune unwanted name parts
651         if ((dwIncludeFlags & INCLUDE_VERSION) == 0)
652         {
653             dwUseIdentityFlags &= ~AssemblyIdentity::IDENTITY_FLAG_VERSION;
654         }
655         if ((dwIncludeFlags & INCLUDE_ARCHITECTURE) == 0)
656         {
657             dwUseIdentityFlags &= ~AssemblyIdentity::IDENTITY_FLAG_PROCESSOR_ARCHITECTURE;
658         }
659         if ((dwIncludeFlags & INCLUDE_RETARGETABLE) == 0)
660         {
661             dwUseIdentityFlags &= ~AssemblyIdentity::IDENTITY_FLAG_RETARGETABLE;
662         }
663         if ((dwIncludeFlags & INCLUDE_CONTENT_TYPE) == 0)
664         {
665             dwUseIdentityFlags &= ~AssemblyIdentity::IDENTITY_FLAG_CONTENT_TYPE;
666         }
667
668         TextualIdentityParser::ToString(this, dwUseIdentityFlags, displayName);
669     }
670
671     SString &AssemblyName::ArchitectureToString(PEKIND kArchitecture)
672     {
673             switch (kArchitecture)
674             {
675             case peNone:
676                 return g_BinderVariables->emptyString;
677             case peMSIL:
678                 return g_BinderVariables->architectureMSIL;
679             case peI386:
680                 return g_BinderVariables->architectureX86;
681             case peAMD64:
682                 return g_BinderVariables->architectureAMD64;
683             case peARM:
684                 return g_BinderVariables->architectureARM;
685             case peARM64:
686                 return g_BinderVariables->architectureARM64;
687             default:
688                 _ASSERTE(0);
689                 return g_BinderVariables->emptyString;
690             }
691     }
692
693     SString &AssemblyName::GetNormalizedCulture()
694     {
695         SString &culture = GetCulture();
696
697         if (culture.IsEmpty())
698         {
699             culture = g_BinderVariables->cultureNeutral;
700         }
701
702         return culture;
703     }
704 };  // namespace BINDER_SPACE