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 // FusionAssemblyName.cpp
8 // Implements the CAssemblyName class
10 // ============================================================
14 #include "strongname.h"
16 #include "fusionhelpers.hpp"
17 #include "fusionassemblyname.hpp"
22 #include "binderinterface.hpp"
23 #include "assemblyidentity.hpp"
24 #include "textualidentityparser.hpp"
26 #define DISPLAY_NAME_DELIMITER W(',')
27 #define DISPLAY_NAME_DELIMITER_STRING W(",")
28 #define VERSION_STRING_SEGMENTS 4
29 #define REMAINING_BUFFER_SIZE ((*pccDisplayName) - (pszBuf - szDisplayName))
31 // ---------------------------------------------------------------------------
33 // ---------------------------------------------------------------------------
36 HRESULT GetPublicKeyTokenFromPKBlob(LPBYTE pbPublicKeyToken, DWORD cbPublicKeyToken,
37 LPBYTE *ppbSN, LPDWORD pcbSN)
41 // Generate the hash of the public key.
42 if (!StrongNameTokenFromPublicKey(pbPublicKeyToken, cbPublicKeyToken, ppbSN, pcbSN))
44 hr = StrongNameErrorInfo();
51 // ---------------------------------------------------------------------------
52 // CPropertyArray ctor
53 // ---------------------------------------------------------------------------
54 CPropertyArray::CPropertyArray()
56 _dwSig = 0x504f5250; /* 'PORP' */
57 memset(&_rProp, 0, ASM_NAME_MAX_PARAMS * sizeof(FusionProperty));
60 // ---------------------------------------------------------------------------
61 // CPropertyArray dtor
62 // ---------------------------------------------------------------------------
63 CPropertyArray::~CPropertyArray()
65 for (DWORD i = 0; i < ASM_NAME_MAX_PARAMS; i++)
67 if (_rProp[i].cb > sizeof(DWORD))
69 if (_rProp[i].pv != NULL)
71 FUSION_DELETE_ARRAY((LPBYTE) _rProp[i].pv);
78 // ---------------------------------------------------------------------------
79 // CPropertyArray::Set
80 // ---------------------------------------------------------------------------
81 HRESULT CPropertyArray::Set(DWORD PropertyId,
82 LPCVOID pvProperty, DWORD cbProperty)
85 FusionProperty *pItem = NULL;
87 pItem = &(_rProp[PropertyId]);
89 if (!cbProperty && !pvProperty)
91 if (pItem->cb > sizeof(DWORD))
93 if (pItem->pv != NULL)
94 FUSION_DELETE_ARRAY((LPBYTE) pItem->pv);
98 else if (cbProperty > sizeof(DWORD))
100 LPBYTE ptr = NEW(BYTE[cbProperty]);
107 if (pItem->cb > sizeof(DWORD))
108 FUSION_DELETE_ARRAY((LPBYTE) pItem->pv);
110 memcpy(ptr, pvProperty, cbProperty);
115 if (pItem->cb > sizeof(DWORD))
116 FUSION_DELETE_ARRAY((LPBYTE) pItem->pv);
118 memcpy(&(pItem->pv), pvProperty, cbProperty);
121 if (PropertyId == ASM_NAME_ARCHITECTURE) {
122 PEKIND pe = * ((PEKIND *)pvProperty);
123 _ASSERTE(pe != peInvalid);
127 pItem->cb = cbProperty;
133 // ---------------------------------------------------------------------------
134 // CPropertyArray::Get
135 // ---------------------------------------------------------------------------
136 HRESULT CPropertyArray::Get(DWORD PropertyId,
137 LPVOID pvProperty, LPDWORD pcbProperty)
140 FusionProperty *pItem;
142 _ASSERTE(pcbProperty);
144 if (PropertyId >= ASM_NAME_MAX_PARAMS
145 || (!pvProperty && *pcbProperty))
147 _ASSERTE(!"Invalid Argument! Passed in NULL buffer with size non-zero!");
152 pItem = &(_rProp[PropertyId]);
154 if (pItem->cb > *pcbProperty)
155 hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
157 memcpy(pvProperty, (pItem->cb > sizeof(DWORD) ?
158 pItem->pv : (LPBYTE) &(pItem->pv)), pItem->cb);
160 *pcbProperty = pItem->cb;
166 // ---------------------------------------------------------------------------
167 // CPropertyArray::operator []
168 // Wraps DWORD optimization test.
169 // ---------------------------------------------------------------------------
170 FusionProperty CPropertyArray::operator [] (DWORD PropertyId)
174 prop.pv = _rProp[PropertyId].cb > sizeof(DWORD) ?
175 _rProp[PropertyId].pv : &(_rProp[PropertyId].pv);
177 prop.cb = _rProp[PropertyId].cb;
182 // ---------------------------------------------------------------------------
183 // CAssemblyName::AddRef
184 // ---------------------------------------------------------------------------
186 CAssemblyName::AddRef()
188 return InterlockedIncrement(&_cRef);
191 // ---------------------------------------------------------------------------
192 // CAssemblyName::Release
193 // ---------------------------------------------------------------------------
195 CAssemblyName::Release()
197 ULONG ulRef = InterlockedDecrement(&_cRef);
206 // ---------------------------------------------------------------------------
207 // CAssemblyName::QueryInterface
208 // ---------------------------------------------------------------------------
210 CAssemblyName::QueryInterface(REFIID riid, void** ppv)
214 BEGIN_ENTRYPOINT_NOTHROW;
222 if ( IsEqualIID(riid, IID_IUnknown)
223 || IsEqualIID(riid, IID_IAssemblyName)
226 *ppv = static_cast<IAssemblyName*> (this);
239 END_ENTRYPOINT_NOTHROW;
244 // ---------------------------------------------------------------------------
245 // CAssemblyName::SetProperty
246 // ---------------------------------------------------------------------------
248 CAssemblyName::SetProperty(DWORD PropertyId,
254 BEGIN_ENTRYPOINT_NOTHROW;
256 hr = SetPropertyInternal(PropertyId, pvProperty, cbProperty);
258 END_ENTRYPOINT_NOTHROW;
262 // ---------------------------------------------------------------------------
263 // CAssemblyName::GetProperty
264 // ---------------------------------------------------------------------------
266 CAssemblyName::GetProperty(DWORD PropertyId,
267 LPVOID pvProperty, LPDWORD pcbProperty)
271 BEGIN_ENTRYPOINT_NOTHROW;
273 // Retrieve the property.
276 case ASM_NAME_NULL_PUBLIC_KEY_TOKEN:
277 case ASM_NAME_NULL_PUBLIC_KEY:
279 hr = (_fPublicKeyToken && !_rProp[PropertyId].cb) ? S_OK : S_FALSE;
282 case ASM_NAME_NULL_CUSTOM:
284 hr = (_fCustom && !_rProp[PropertyId].cb) ? S_OK : S_FALSE;
289 hr = _rProp.Get(PropertyId, pvProperty, pcbProperty);
294 END_ENTRYPOINT_NOTHROW;
299 // ---------------------------------------------------------------------------
300 // CAssemblyName::Finalize
301 // ---------------------------------------------------------------------------
303 CAssemblyName::Finalize()
305 BEGIN_ENTRYPOINT_NOTHROW;
307 _fIsFinalized = TRUE;
308 END_ENTRYPOINT_NOTHROW;
312 // ---------------------------------------------------------------------------
313 // CAssemblyName::GetDisplayName
314 // ---------------------------------------------------------------------------
316 CAssemblyName::GetDisplayName( __out_ecount_opt(*pccDisplayName) LPOLESTR szDisplayName,
317 __inout LPDWORD pccDisplayName,
318 DWORD dwDisplayFlags)
322 BEGIN_ENTRYPOINT_NOTHROW;
324 if (!dwDisplayFlags) {
325 dwDisplayFlags = ASM_DISPLAYF_DEFAULT;
328 // Validate input buffer.
329 if(!pccDisplayName || (!szDisplayName && *pccDisplayName)) {
336 NewHolder<BINDER_SPACE::AssemblyIdentity> pAssemblyIdentity = new BINDER_SPACE::AssemblyIdentity();
338 StackSString textualIdentity;
341 prop = _rProp[ASM_NAME_NAME];
343 hr = FUSION_E_INVALID_NAME;
347 _ASSERTE(prop.cb >= sizeof(WCHAR));
349 pAssemblyIdentity->m_simpleName.Set((const WCHAR *) prop.pv,
350 (prop.cb - sizeof(WCHAR)) / sizeof(WCHAR));
351 pAssemblyIdentity->SetHave(BINDER_SPACE::AssemblyIdentity::IDENTITY_FLAG_SIMPLE_NAME);
355 if (dwDisplayFlags & ASM_DISPLAYF_VERSION) {
356 prop = _rProp[ASM_NAME_MAJOR_VERSION];
358 // Set version if we have it
360 DWORD dwVersionParts[4];
362 for(DWORD i = 0; i < 4; i++) {
363 prop = _rProp[ASM_NAME_MAJOR_VERSION + i];
365 // Normalize non-existing version parts to zero
366 if (prop.cb == sizeof(WORD)) {
367 dwVersionParts[i] = (DWORD) (* ((WORD *) prop.pv));
370 dwVersionParts[i] = 0;
374 pAssemblyIdentity->m_version.SetFeatureVersion(dwVersionParts[0], dwVersionParts[1]);
375 pAssemblyIdentity->m_version.SetServiceVersion(dwVersionParts[2], dwVersionParts[3]);
376 pAssemblyIdentity->SetHave(BINDER_SPACE::AssemblyIdentity::IDENTITY_FLAG_VERSION);
381 if (dwDisplayFlags & ASM_DISPLAYF_CULTURE) {
382 prop = _rProp[ASM_NAME_CULTURE];
385 _ASSERTE(prop.cb >= sizeof(WCHAR));
387 if (((const WCHAR *) prop.pv)[0] != 0x00) {
388 pAssemblyIdentity->m_cultureOrLanguage.
389 Set((const WCHAR *) prop.pv,
390 (prop.cb - sizeof(WCHAR)) / sizeof(WCHAR));
393 pAssemblyIdentity->SetHave(BINDER_SPACE::AssemblyIdentity::IDENTITY_FLAG_CULTURE);
397 // Display public key token
398 if ((dwDisplayFlags & ASM_DISPLAYF_PUBLIC_KEY_TOKEN) && _fPublicKeyToken) {
399 prop = _rProp[ASM_NAME_PUBLIC_KEY_TOKEN];
402 pAssemblyIdentity->m_publicKeyOrTokenBLOB.Set((const BYTE *) prop.pv, prop.cb);
403 pAssemblyIdentity->SetHave(BINDER_SPACE::AssemblyIdentity::IDENTITY_FLAG_PUBLIC_KEY_TOKEN);
407 SetHave(BINDER_SPACE::AssemblyIdentity::IDENTITY_FLAG_PUBLIC_KEY_TOKEN_NULL);
411 // Display processor architecture
412 if (dwDisplayFlags & ASM_DISPLAYF_PROCESSORARCHITECTURE) {
413 if (_rProp[ASM_NAME_ARCHITECTURE].cb != 0) {
414 DWORD PeKind = *((LPDWORD)_rProp[ASM_NAME_ARCHITECTURE].pv);
416 if (PeKind != peNone) {
417 pAssemblyIdentity->m_kProcessorArchitecture = (PEKIND) PeKind;
419 SetHave(BINDER_SPACE::AssemblyIdentity::IDENTITY_FLAG_PROCESSOR_ARCHITECTURE);
424 // Display retarget flag
425 if (dwDisplayFlags & ASM_DISPLAYF_RETARGET) {
426 prop = _rProp[ASM_NAME_RETARGET];
429 BOOL fRetarget = *((LPBOOL) prop.pv);
433 pAssemblyIdentity->SetHave(BINDER_SPACE::AssemblyIdentity::IDENTITY_FLAG_RETARGETABLE);
438 // Display content type
439 if (dwDisplayFlags & ASM_DISPLAYF_CONTENT_TYPE)
441 prop = _rProp[ASM_NAME_CONTENT_TYPE];
444 DWORD dwContentType = *((LPDWORD)prop.pv);
445 if (dwContentType != AssemblyContentType_Default)
447 pAssemblyIdentity->SetHave(BINDER_SPACE::AssemblyIdentity::IDENTITY_FLAG_CONTENT_TYPE);
448 pAssemblyIdentity->m_kContentType = (AssemblyContentType)dwContentType;
453 // Display custom flag
454 if ((dwDisplayFlags & ASM_DISPLAYF_CUSTOM) && _fCustom) {
455 prop = _rProp[ASM_NAME_CUSTOM];
458 pAssemblyIdentity->m_customBLOB.Set((const BYTE *) prop.pv, prop.cb);
459 pAssemblyIdentity->SetHave(BINDER_SPACE::AssemblyIdentity::IDENTITY_FLAG_CUSTOM);
462 pAssemblyIdentity->SetHave(BINDER_SPACE::AssemblyIdentity::IDENTITY_FLAG_CUSTOM_NULL);
466 // Create the textual identity
467 hr = BINDER_SPACE::TextualIdentityParser::ToString(pAssemblyIdentity,
468 pAssemblyIdentity->m_dwIdentityFlags,
474 // Determine required buffer size
475 DWORD dwGivenSize = *pccDisplayName;
476 DWORD dwRequiredSize = textualIdentity.GetCount() + 1;
478 *pccDisplayName = dwRequiredSize;
480 if (dwRequiredSize > dwGivenSize) {
481 hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
484 szDisplayName[0] = 0x00;
490 memcpy(szDisplayName, textualIdentity.GetUnicode(), dwRequiredSize * sizeof(WCHAR));
493 EX_CATCH_HRESULT(hr);
496 END_ENTRYPOINT_NOTHROW;
500 // ---------------------------------------------------------------------------
501 // CAssemblyName::GetName
502 // ---------------------------------------------------------------------------
504 CAssemblyName::GetName(
505 __inout LPDWORD lpcwBuffer,
506 __out_ecount_opt(*lpcwBuffer) LPOLESTR pwzBuffer)
509 BEGIN_ENTRYPOINT_NOTHROW;
511 DWORD cbBuffer = *lpcwBuffer * sizeof(TCHAR);
512 hr = GetProperty(ASM_NAME_NAME, pwzBuffer, &cbBuffer);
513 *lpcwBuffer = cbBuffer / sizeof(TCHAR);
514 END_ENTRYPOINT_NOTHROW;
519 // ---------------------------------------------------------------------------
520 // CAssemblyName::GetVersion
521 // ---------------------------------------------------------------------------
523 CAssemblyName::GetVersion(
524 /* [out] */ LPDWORD pdwVersionHi,
525 /* [out] */ LPDWORD pdwVersionLow)
528 BEGIN_ENTRYPOINT_NOTHROW;
530 // Get Assembly Version
531 hr = GetVersion( ASM_NAME_MAJOR_VERSION, pdwVersionHi, pdwVersionLow);
533 END_ENTRYPOINT_NOTHROW;
537 // ---------------------------------------------------------------------------
538 // CAssemblyName::IsEqual
539 // ---------------------------------------------------------------------------
541 CAssemblyName::IsEqual(LPASSEMBLYNAME pName, DWORD dwCmpFlags)
545 BEGIN_ENTRYPOINT_NOTHROW;
547 DWORD dwPartialCmpMask = 0;
548 BOOL fIsPartial = FALSE;
549 CAssemblyName *pCName = static_cast<CAssemblyName *>(pName);
551 const DWORD SIMPLE_VERSION_MASK = ASM_CMPF_VERSION;
553 FusionProperty propThis;
554 FusionProperty propPara;
561 // Get the ref partial comparison mask, if any.
562 fIsPartial = CAssemblyName::IsPartial(this, &dwPartialCmpMask);
564 if (dwCmpFlags == ASM_CMPF_DEFAULT) {
565 // Set all comparison flags.
566 dwCmpFlags = ASM_CMPF_IL_ALL | ASM_CMPF_ARCHITECTURE;
568 // don't compare architecture if ref does not have architecture.
569 if (!(dwPartialCmpMask & ASM_CMPF_ARCHITECTURE)) {
570 dwCmpFlags &= ~ASM_CMPF_ARCHITECTURE;
573 // Otherwise, if ref is simple (possibly partial)
574 // we mask off all version bits.
575 if (!CAssemblyName::IsStronglyNamed(this))
577 // we don't have a public key token, but we don't know
578 // it is because we are simply named assembly or we are
579 // just partial on public key token.
580 if (dwPartialCmpMask & ASM_CMPF_PUBLIC_KEY_TOKEN)
582 // now we know we are simply named assembly since we
583 // have a public key token, but it is NULL.
584 dwCmpFlags &= ~SIMPLE_VERSION_MASK;
586 // If neither of these two cases then public key token
587 // is not set in ref , but def may be simple or strong.
588 // The comparison mask is chosen based on def.
591 if (!CAssemblyName::IsStronglyNamed(pName))
592 dwCmpFlags &= ~SIMPLE_VERSION_MASK;
597 // Mask off flags (either passed in or generated
598 // by default flag with the comparison mask generated
600 dwCmpFlags &= dwPartialCmpMask;
603 // The individual name fields can now be compared..
607 if (dwCmpFlags & ASM_CMPF_NAME)
609 propThis = _rProp[ASM_NAME_NAME];
610 propPara = pCName->_rProp[ASM_NAME_NAME];
612 if (propThis.cb != propPara.cb)
618 if (propThis.cb && FusionCompareStringI((LPWSTR)propThis.pv, (LPWSTR)propPara.pv))
627 if (dwCmpFlags & ASM_CMPF_MAJOR_VERSION)
629 propThis = _rProp[ASM_NAME_MAJOR_VERSION];
630 propPara = pCName->_rProp[ASM_NAME_MAJOR_VERSION];
632 if (*((LPWORD) propThis.pv) != *((LPWORD)propPara.pv))
639 if (dwCmpFlags & ASM_CMPF_MINOR_VERSION)
641 propThis = _rProp[ASM_NAME_MINOR_VERSION];
642 propPara = pCName->_rProp[ASM_NAME_MINOR_VERSION];
644 if (*((LPWORD) propThis.pv) != *((LPWORD)propPara.pv))
651 if (dwCmpFlags & ASM_CMPF_REVISION_NUMBER)
653 propThis = _rProp[ASM_NAME_REVISION_NUMBER];
654 propPara = pCName->_rProp[ASM_NAME_REVISION_NUMBER];
656 if (*((LPWORD) propThis.pv) != *((LPWORD)propPara.pv))
663 if (dwCmpFlags & ASM_CMPF_BUILD_NUMBER)
665 propThis = _rProp[ASM_NAME_BUILD_NUMBER];
666 propPara = pCName->_rProp[ASM_NAME_BUILD_NUMBER];
668 if (*((LPWORD) propThis.pv) != *((LPWORD)propPara.pv))
675 // Compare public key token
677 if (dwCmpFlags & ASM_CMPF_PUBLIC_KEY_TOKEN)
679 // compare public key if both of them have public key set.
680 propThis = _rProp[ASM_NAME_PUBLIC_KEY];
681 propPara = pCName->_rProp[ASM_NAME_PUBLIC_KEY];
682 if (!propThis.cb || !propPara.cb) {
683 // otherwise, compare public key token
684 propThis = _rProp[ASM_NAME_PUBLIC_KEY_TOKEN];
685 propPara = pCName->_rProp[ASM_NAME_PUBLIC_KEY_TOKEN];
688 if (propThis.cb != propPara.cb) {
693 if (propThis.cb && memcmp(propThis.pv, propPara.pv, propThis.cb)) {
701 if (dwCmpFlags & ASM_CMPF_CULTURE)
703 propThis = _rProp[ASM_NAME_CULTURE];
704 propPara = pCName->_rProp[ASM_NAME_CULTURE];
706 if (propThis.cb != propPara.cb)
712 if (propThis.cb && FusionCompareStringI((LPWSTR)propThis.pv, (LPWSTR)propPara.pv))
719 // Compare Custom attribute.
721 if (dwCmpFlags & ASM_CMPF_CUSTOM)
723 propThis = _rProp[ASM_NAME_PUBLIC_KEY_TOKEN];
724 propPara = pCName->_rProp[ASM_NAME_PUBLIC_KEY_TOKEN];
726 if (propThis.cb != propPara.cb) {
731 if (propThis.cb && memcmp(propThis.pv, propPara.pv, propThis.cb)) {
737 // Compare Retarget flag
738 if (dwCmpFlags & ASM_CMPF_RETARGET)
740 propThis = _rProp[ASM_NAME_RETARGET];
741 propPara = pCName->_rProp[ASM_NAME_RETARGET];
743 if (*((LPDWORD) propThis.pv) != *((LPDWORD)propPara.pv))
750 // compare config mask
751 if (dwCmpFlags & ASM_CMPF_CONFIG_MASK)
753 propThis = _rProp[ASM_NAME_CONFIG_MASK];
754 propPara = pCName->_rProp[ASM_NAME_CONFIG_MASK];
756 if (*((LPDWORD) propThis.pv) != *((LPDWORD)propPara.pv))
764 // compare architecture
765 if (dwCmpFlags & ASM_CMPF_ARCHITECTURE)
767 propThis = _rProp[ASM_NAME_ARCHITECTURE];
768 propPara = pCName->_rProp[ASM_NAME_ARCHITECTURE];
770 if (propThis.cb != propPara.cb) {
776 if (*((LPDWORD) propThis.pv) != *((LPDWORD)propPara.pv)) {
783 // Compare content type
784 if (dwCmpFlags & ASM_CMPF_CONTENT_TYPE)
786 propThis = _rProp[ASM_NAME_CONTENT_TYPE];
787 propPara = pCName->_rProp[ASM_NAME_CONTENT_TYPE];
789 if (*((LPDWORD)propThis.pv) != *((LPDWORD)propPara.pv))
797 if (dwCmpFlags & ASM_CMPF_MVID)
799 propThis = _rProp[ASM_NAME_MVID];
800 propPara = pCName->_rProp[ASM_NAME_MVID];
802 if (propThis.cb != propPara.cb) {
807 if (propThis.cb && memcmp(propThis.pv, propPara.pv, propThis.cb)) {
814 if (dwCmpFlags & ASM_CMPF_SIGNATURE)
816 propThis = _rProp[ASM_NAME_SIGNATURE_BLOB];
817 propPara = pCName->_rProp[ASM_NAME_SIGNATURE_BLOB];
819 if (propThis.cb != propPara.cb) {
824 if (propThis.cb && memcmp(propThis.pv, propPara.pv, propThis.cb)) {
832 END_ENTRYPOINT_NOTHROW;
836 // ---------------------------------------------------------------------------
837 // CAssemblyName::Reserved
838 // ---------------------------------------------------------------------------
840 CAssemblyName::Reserved(
841 /* in */ REFIID refIID,
842 /* in */ IUnknown *pUnkBindSink,
843 /* in */ IUnknown *pUnkAppCtx,
844 /* in */ LPCOLESTR szCodebaseIn,
845 /* in */ LONGLONG llFlags,
846 /* in */ LPVOID pvReserved,
847 /* in */ DWORD cbReserved,
848 /* out */ VOID **ppv)
853 // ---------------------------------------------------------------------------
854 // CAssemblyName::Clone
855 // ---------------------------------------------------------------------------
856 HRESULT CAssemblyName::Clone(IAssemblyName **ppName)
860 BEGIN_ENTRYPOINT_NOTHROW;
862 CAssemblyName *pClone = NULL;
871 pClone = NEW(CAssemblyName);
877 hr = CopyProperties(this, pClone, NULL, 0);
888 END_ENTRYPOINT_NOTHROW;
893 // ---------------------------------------------------------------------------
894 // CAssemblyName::SetPropertyInternal
895 // ---------------------------------------------------------------------------
896 HRESULT CAssemblyName::SetPropertyInternal(DWORD PropertyId,
904 // Fail if finalized.
907 _ASSERTE(!"SetProperty on a IAssemblyName while the name is finalized!");
912 if (PropertyId >= ASM_NAME_MAX_PARAMS
913 || (!pvProperty && cbProperty))
915 _ASSERTE(!"Invalid Argument! Passed in NULL buffer with size non-zero!");
920 // <REVISIT_TODO> - make this a switch statement.</REVISIT_TODO>
921 if (PropertyId == ASM_NAME_MAJOR_VERSION ||
922 PropertyId == ASM_NAME_MINOR_VERSION ||
923 PropertyId == ASM_NAME_BUILD_NUMBER ||
924 PropertyId == ASM_NAME_REVISION_NUMBER)
926 if (cbProperty > sizeof(WORD)) {
932 // Check if public key is being set and if so,
933 // set the public key token if not already set.
934 if (PropertyId == ASM_NAME_PUBLIC_KEY)
936 // If setting true public key, generate hash.
937 if (pvProperty && cbProperty)
939 // Generate the public key token from the pk.
940 if (FAILED(hr = GetPublicKeyTokenFromPKBlob((LPBYTE) pvProperty, cbProperty, &pbSN, &cbSN)))
943 // Set the public key token property.
944 if (FAILED(hr = SetPropertyInternal(ASM_NAME_PUBLIC_KEY_TOKEN, pbSN, cbSN)))
947 // Otherwise expect call to reset property.
948 else if (!cbProperty)
950 if (FAILED(hr = SetPropertyInternal(ASM_NAME_PUBLIC_KEY_TOKEN, pvProperty, cbProperty)))
955 // Setting NULL public key clears values in public key,
956 // public key token and sets public key token flag.
957 else if (PropertyId == ASM_NAME_NULL_PUBLIC_KEY)
961 hr = SetPropertyInternal(ASM_NAME_NULL_PUBLIC_KEY_TOKEN, pvProperty, cbProperty);
964 // Setting or clearing public key token.
965 else if (PropertyId == ASM_NAME_PUBLIC_KEY_TOKEN)
967 // Defensive: invalid sized public key tokens should be avoided.
968 if (cbProperty > PUBLIC_KEY_TOKEN_LEN)
970 hr = SetPropertyInternal(ASM_NAME_NULL_PUBLIC_KEY_TOKEN, NULL, 0);
975 if (pvProperty && cbProperty)
976 _fPublicKeyToken = TRUE;
977 else if (!cbProperty)
978 _fPublicKeyToken = FALSE;
980 // Setting NULL public key token clears public key token and
981 // sets public key token flag.
982 else if (PropertyId == ASM_NAME_NULL_PUBLIC_KEY_TOKEN)
984 _fPublicKeyToken = TRUE;
987 PropertyId = ASM_NAME_PUBLIC_KEY_TOKEN;
989 else if (PropertyId == ASM_NAME_CUSTOM)
991 if (pvProperty && cbProperty)
993 else if (!cbProperty)
996 else if (PropertyId == ASM_NAME_NULL_CUSTOM)
1001 PropertyId = ASM_NAME_CUSTOM;
1004 // Setting "neutral" as the culture is the same as "" culture (meaning
1005 // culture-invariant).
1006 else if (PropertyId == ASM_NAME_CULTURE) {
1007 if (pvProperty && !FusionCompareStringI((LPWSTR)pvProperty, W("neutral"))) {
1008 pvProperty = (void *)W("");
1009 cbProperty = sizeof(W(""));
1013 // Set property on array.
1014 hr = _rProp.Set(PropertyId, pvProperty, cbProperty);
1017 if (SUCCEEDED(hr)) {
1022 pwzOld = InterlockedExchangeT(&_pwzTextualIdentity, NULL);
1023 SAFEDELETEARRAY(pwzOld);
1024 pwzOld = InterlockedExchangeT(&_pwzTextualIdentityILFull, NULL);
1025 SAFEDELETEARRAY(pwzOld);
1028 // Free memory allocated by crypto wrapper.
1030 StrongNameFreeBuffer(pbSN);
1038 // ---------------------------------------------------------------------------
1039 // CheckFieldsForFriendAssembly
1040 // ---------------------------------------------------------------------------
1042 CheckFieldsForFriendAssembly(
1043 LPASSEMBLYNAME pAssemblyName)
1048 // Let's look at the information they gave us in the friends declaration.
1049 // If they put in a Processor Architecture, Culture, or Version, then we'll return an error.
1051 if (FAILED(hr = pAssemblyName->GetProperty(ASM_NAME_MAJOR_VERSION, NULL, &dwSize)) ||
1052 FAILED(hr = pAssemblyName->GetProperty(ASM_NAME_MINOR_VERSION, NULL, &dwSize)) ||
1053 FAILED(hr = pAssemblyName->GetProperty(ASM_NAME_BUILD_NUMBER, NULL, &dwSize)) ||
1054 FAILED(hr = pAssemblyName->GetProperty(ASM_NAME_REVISION_NUMBER, NULL, &dwSize)) ||
1055 FAILED(hr = pAssemblyName->GetProperty(ASM_NAME_CULTURE, NULL, &dwSize)) ||
1056 FAILED(hr = pAssemblyName->GetProperty(ASM_NAME_ARCHITECTURE, NULL, &dwSize)))
1058 // If any of these calls failed due to an insufficient buffer, then that means
1059 // the assembly name contained them
1060 if (hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER))
1061 hr = META_E_CA_BAD_FRIENDS_ARGS;
1063 if (FAILED(hr = pAssemblyName->GetProperty(ASM_NAME_PUBLIC_KEY_TOKEN, NULL, &dwSize))) {
1066 // Public Key token should not be passed to InternalsVisibleTo
1067 // attribute. This translates to the ASM_NAME_PUBLIC_KEY_TOKEN
1068 // property being set, while the full public key is not.
1071 if (hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) {
1075 if (FAILED(hr = pAssemblyName->GetProperty(ASM_NAME_PUBLIC_KEY, NULL, &dwSize))) {
1076 if (hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER))
1079 hr = META_E_CA_BAD_FRIENDS_ARGS;
1092 // ---------------------------------------------------------------------------
1093 // CreateAssemblyNameObject
1094 // ---------------------------------------------------------------------------
1096 // This is not external for CoreCLR
1098 CreateAssemblyNameObject(
1099 LPASSEMBLYNAME *ppAssemblyName,
1100 LPCOLESTR szAssemblyName,
1107 BEGIN_ENTRYPOINT_NOTHROW;
1109 CAssemblyName *pName = NULL;
1111 if (!ppAssemblyName)
1117 pName = NEW(CAssemblyName);
1124 if (dwFlags & CANOF_PARSE_DISPLAY_NAME)
1126 hr = pName->Init(NULL, NULL);
1131 hr = pName->Parse((LPWSTR)szAssemblyName);
1135 hr = pName->Init(szAssemblyName, NULL);
1139 if (SUCCEEDED(hr) && ((dwFlags & CANOF_VERIFY_FRIEND_ASSEMBLYNAME)))
1141 hr = CheckFieldsForFriendAssembly(pName);
1151 *ppAssemblyName = pName;
1154 END_ENTRYPOINT_NOTHROW;
1158 // ---------------------------------------------------------------------------
1159 // CreateAssemblyNameObjectFromMetaData
1160 // ---------------------------------------------------------------------------
1162 CreateAssemblyNameObjectFromMetaData(
1163 LPASSEMBLYNAME *ppAssemblyName,
1164 LPCOLESTR szAssemblyName,
1165 ASSEMBLYMETADATA *pamd,
1170 CAssemblyName *pName = NULL;
1172 pName = NEW(CAssemblyName);
1179 hr = pName->Init(szAssemblyName, pamd);
1187 *ppAssemblyName = pName;
1193 // ---------------------------------------------------------------------------
1194 // CAssemblyName constructor
1195 // ---------------------------------------------------------------------------
1196 CAssemblyName::CAssemblyName()
1198 _dwSig = 0x454d414e; /* 'EMAN' */
1199 _fIsFinalized = FALSE;
1200 _fPublicKeyToken = FALSE;
1203 _pwzPathModifier = NULL;
1204 _pwzTextualIdentity = NULL;
1205 _pwzTextualIdentityILFull = NULL;
1208 // ---------------------------------------------------------------------------
1209 // CAssemblyName destructor
1210 // ---------------------------------------------------------------------------
1211 CAssemblyName::~CAssemblyName()
1213 SAFEDELETEARRAY(_pwzPathModifier);
1214 SAFEDELETEARRAY(_pwzTextualIdentity);
1215 SAFEDELETEARRAY(_pwzTextualIdentityILFull);
1218 // ---------------------------------------------------------------------------
1219 // CAssemblyName::IsStronglyNamed
1220 // ---------------------------------------------------------------------------
1221 BOOL CAssemblyName::IsStronglyNamed(IAssemblyName *pName)
1223 CAssemblyName *pCName = static_cast<CAssemblyName *> (pName);
1226 return (pCName->_rProp[ASM_NAME_PUBLIC_KEY_TOKEN].cb != 0);
1229 // ---------------------------------------------------------------------------
1230 // CAssemblyName::IsPartial
1231 // ---------------------------------------------------------------------------
1232 BOOL CAssemblyName::IsPartial(IAssemblyName *pIName,
1235 DWORD dwCmpMask = 0;
1236 BOOL fPartial = FALSE;
1238 static const ASM_NAME rNameFlags[] ={ASM_NAME_NAME,
1240 ASM_NAME_PUBLIC_KEY_TOKEN,
1241 ASM_NAME_MAJOR_VERSION,
1242 ASM_NAME_MINOR_VERSION,
1243 ASM_NAME_BUILD_NUMBER,
1244 ASM_NAME_REVISION_NUMBER,
1248 static const ASM_CMP_FLAGS rCmpFlags[] = {ASM_CMPF_NAME,
1250 ASM_CMPF_PUBLIC_KEY_TOKEN,
1251 ASM_CMPF_MAJOR_VERSION,
1252 ASM_CMPF_MINOR_VERSION,
1253 ASM_CMPF_BUILD_NUMBER,
1254 ASM_CMPF_REVISION_NUMBER,
1258 CAssemblyName *pName = static_cast<CAssemblyName*> (pIName); // dynamic_cast
1261 DWORD iNumOfComparison = sizeof(rNameFlags) / sizeof(rNameFlags[0]);
1263 for (DWORD i = 0; i < iNumOfComparison; i++)
1265 if (pName->_rProp[rNameFlags[i]].cb
1266 || (rNameFlags[i] == ASM_NAME_PUBLIC_KEY_TOKEN
1267 && pName->_fPublicKeyToken)
1268 || (rNameFlags[i] == ASM_NAME_CUSTOM
1269 && pName->_fCustom))
1271 dwCmpMask |= rCmpFlags[i];
1278 if(pName->_rProp[ASM_NAME_ARCHITECTURE].cb) {
1279 dwCmpMask |= ASM_CMPF_ARCHITECTURE;
1282 if (pName->_rProp[ASM_NAME_RETARGET].cb) {
1283 dwCmpMask |= ASM_CMPF_RETARGET;
1286 if (pName->_rProp[ASM_NAME_CONTENT_TYPE].cb != 0)
1288 dwCmpMask |= ASM_CMPF_CONTENT_TYPE;
1291 if (pName->_rProp[ASM_NAME_CONFIG_MASK].cb) {
1292 dwCmpMask |= ASM_CMPF_CONFIG_MASK;
1295 if (pName->_rProp[ASM_NAME_MVID].cb) {
1296 dwCmpMask |= ASM_CMPF_MVID;
1299 if (pName->_rProp[ASM_NAME_SIGNATURE_BLOB].cb) {
1300 dwCmpMask |= ASM_CMPF_SIGNATURE;
1304 *pdwCmpMask = dwCmpMask;
1309 // ---------------------------------------------------------------------------
1310 // CAssemblyName::Init
1311 // ---------------------------------------------------------------------------
1313 CAssemblyName::Init(LPCTSTR pszAssemblyName, ASSEMBLYMETADATA *pamd)
1318 if (pszAssemblyName)
1320 hr = SetProperty(ASM_NAME_NAME, (LPTSTR) pszAssemblyName,
1321 (lstrlenW(pszAssemblyName)+1) * sizeof(TCHAR));
1328 if (FAILED(hr = SetProperty(ASM_NAME_MAJOR_VERSION,
1329 &pamd->usMajorVersion, sizeof(WORD)))
1332 || FAILED(hr = SetProperty(ASM_NAME_MINOR_VERSION,
1333 &pamd->usMinorVersion, sizeof(WORD)))
1336 || FAILED(hr = SetProperty(ASM_NAME_REVISION_NUMBER,
1337 &pamd->usRevisionNumber, sizeof(WORD)))
1340 || FAILED(hr = SetProperty(ASM_NAME_BUILD_NUMBER,
1341 &pamd->usBuildNumber, sizeof(WORD)))
1344 || FAILED(hr = SetProperty(ASM_NAME_CULTURE,
1345 pamd->szLocale, pamd->cbLocale * sizeof(WCHAR)))
1356 // ---------------------------------------------------------------------------
1357 // CAssemblyName::Parse
1358 // ---------------------------------------------------------------------------
1359 HRESULT CAssemblyName::Parse(__in_z LPCWSTR szDisplayName)
1363 if (!(szDisplayName && *szDisplayName))
1370 BINDER_SPACE::AssemblyIdentity assemblyIdentity;
1371 SString displayName(szDisplayName);
1373 // Parse the textual identity
1374 hr = BINDER_SPACE::TextualIdentityParser::Parse(displayName, &assemblyIdentity);
1380 hr = SetProperty(ASM_NAME_NAME,
1381 (LPVOID) assemblyIdentity.m_simpleName.GetUnicode(),
1382 (assemblyIdentity.m_simpleName.GetCount() + 1) * sizeof(WCHAR));
1388 if (assemblyIdentity.Have(BINDER_SPACE::AssemblyIdentity::IDENTITY_FLAG_VERSION)) {
1389 WORD wVersionPart = 0;
1391 wVersionPart = (WORD) assemblyIdentity.m_version.GetMajor();
1392 hr = SetProperty(ASM_NAME_MAJOR_VERSION, &wVersionPart, sizeof(WORD));
1397 wVersionPart = (WORD) assemblyIdentity.m_version.GetMinor();
1398 hr = SetProperty(ASM_NAME_MINOR_VERSION, &wVersionPart, sizeof(WORD));
1403 wVersionPart = (WORD) assemblyIdentity.m_version.GetBuild();
1404 hr = SetProperty(ASM_NAME_BUILD_NUMBER, &wVersionPart, sizeof(WORD));
1409 wVersionPart = (WORD) assemblyIdentity.m_version.GetRevision();
1410 hr = SetProperty(ASM_NAME_REVISION_NUMBER, &wVersionPart, sizeof(WORD));
1417 if (assemblyIdentity.Have(BINDER_SPACE::AssemblyIdentity::IDENTITY_FLAG_CULTURE)) {
1418 hr = SetProperty(ASM_NAME_CULTURE,
1419 (LPVOID) assemblyIdentity.m_cultureOrLanguage.GetUnicode(),
1420 (assemblyIdentity.m_cultureOrLanguage.GetCount()+1) * sizeof(WCHAR));
1426 // Set public key (token) or NULL flag.
1427 if (assemblyIdentity.Have(BINDER_SPACE::AssemblyIdentity::IDENTITY_FLAG_PUBLIC_KEY)) {
1428 SBuffer &publicKeyBuffer = assemblyIdentity.m_publicKeyOrTokenBLOB;
1429 const void *pBytes = publicKeyBuffer;
1431 // This also computes and sets the public key token.
1432 hr = SetProperty(ASM_NAME_PUBLIC_KEY, (void *) pBytes, publicKeyBuffer.GetSize());
1437 else if (assemblyIdentity.Have(BINDER_SPACE::AssemblyIdentity::IDENTITY_FLAG_PUBLIC_KEY_TOKEN)) {
1438 SBuffer &publicKeyTokenBuffer = assemblyIdentity.m_publicKeyOrTokenBLOB;
1439 const void *pBytes = publicKeyTokenBuffer;
1441 hr = SetProperty(ASM_NAME_PUBLIC_KEY_TOKEN,
1443 publicKeyTokenBuffer.GetSize());
1448 else if (assemblyIdentity.
1449 Have(BINDER_SPACE::AssemblyIdentity::IDENTITY_FLAG_PUBLIC_KEY_TOKEN_NULL)) {
1450 hr = SetProperty(ASM_NAME_NULL_PUBLIC_KEY_TOKEN, NULL, 0);
1456 // Set architecture.
1457 if (assemblyIdentity.Have(BINDER_SPACE::AssemblyIdentity::IDENTITY_FLAG_PROCESSOR_ARCHITECTURE)) {
1458 PEKIND peKind = assemblyIdentity.m_kProcessorArchitecture;
1460 hr = SetProperty(ASM_NAME_ARCHITECTURE, (LPVOID) &peKind, sizeof(PEKIND));
1466 // Set retargetable flag.
1467 if (assemblyIdentity.Have(BINDER_SPACE::AssemblyIdentity::IDENTITY_FLAG_RETARGETABLE)) {
1468 BOOL fRetarget = TRUE;
1470 if (FAILED(hr = SetProperty(ASM_NAME_RETARGET, &fRetarget, sizeof(BOOL)))) {
1475 // Set content type.
1476 if (assemblyIdentity.Have(BINDER_SPACE::AssemblyIdentity::IDENTITY_FLAG_CONTENT_TYPE)) {
1477 DWORD dwContentType = assemblyIdentity.m_kContentType;
1479 hr = SetProperty(ASM_NAME_CONTENT_TYPE, &dwContentType, sizeof(dwContentType));
1480 IfFailGoto(hr, exit);
1483 // Set custom or NULL flag.
1484 if (assemblyIdentity.Have(BINDER_SPACE::AssemblyIdentity::IDENTITY_FLAG_CUSTOM)) {
1485 SBuffer &customBuffer = assemblyIdentity.m_customBLOB;
1486 const void *pBytes = customBuffer;
1488 hr = SetProperty(ASM_NAME_CUSTOM, (void *) pBytes, customBuffer.GetSize());
1493 else if (assemblyIdentity.Have(BINDER_SPACE::AssemblyIdentity::IDENTITY_FLAG_CUSTOM_NULL)) {
1494 hr = SetProperty(ASM_NAME_NULL_CUSTOM, NULL, 0);
1500 EX_CATCH_HRESULT(hr);
1506 // ---------------------------------------------------------------------------
1507 // CAssemblyName::GetVersion
1508 // ---------------------------------------------------------------------------
1510 CAssemblyName::GetVersion(
1511 /* [in] */ DWORD dwMajorVersionEnumValue,
1512 /* [out] */ LPDWORD pdwVersionHi,
1513 /* [out] */ LPDWORD pdwVersionLow)
1516 DWORD cb = sizeof(WORD);
1517 WORD wVerMajor = 0, wVerMinor = 0, wRevNo = 0, wBldNo = 0;
1519 if(!pdwVersionHi || !pdwVersionLow) {
1524 *pdwVersionHi = *pdwVersionLow = 0;
1526 if(FAILED( (hr = GetProperty(dwMajorVersionEnumValue, &wVerMajor, &(cb = sizeof(WORD))))))
1529 hr = FUSION_E_INVALID_NAME;
1533 if(FAILED( (hr = GetProperty(dwMajorVersionEnumValue+1, &wVerMinor, &(cb = sizeof(WORD))))))
1537 hr = FUSION_E_INVALID_NAME;
1541 if(FAILED( (hr = GetProperty(dwMajorVersionEnumValue+2, &wBldNo, &(cb = sizeof(WORD))))))
1544 hr = FUSION_E_INVALID_NAME;
1548 if(FAILED( (hr = GetProperty(dwMajorVersionEnumValue+3, &wRevNo, &(cb = sizeof(WORD))))))
1552 hr = FUSION_E_INVALID_NAME;
1556 *pdwVersionHi = MAKELONG(wVerMinor, wVerMajor);
1557 *pdwVersionLow = MAKELONG(wRevNo, wBldNo);
1563 // ---------------------------------------------------------------------------
1564 // CAssemblyName::CopyProperties
1565 // ---------------------------------------------------------------------------
1567 CAssemblyName::CopyProperties(CAssemblyName *pSource,
1568 CAssemblyName *pTarget,
1569 const DWORD properties[],
1574 FusionProperty prop;
1576 _ASSERTE(pSource && pTarget);
1579 for( i = 0; i < ASM_NAME_MAX_PARAMS; i ++) {
1580 prop = pSource->_rProp[i];
1583 if (FAILED(hr = pTarget->SetProperty(i, prop.pv, prop.cb))) {
1590 for (i = 0; i<dwSize; i++) {
1591 _ASSERTE(properties[i] < ASM_NAME_MAX_PARAMS);
1592 prop = pSource->_rProp[properties[i]];
1594 if (FAILED(hr = pTarget->SetProperty(properties[i], prop.pv, prop.cb))) {
1601 pTarget->_fPublicKeyToken = pSource->_fPublicKeyToken;
1602 pTarget->_fCustom = pSource->_fCustom;
1604 if (pSource->_pwzPathModifier) {
1605 pTarget->_pwzPathModifier = WSTRDupDynamic(pSource->_pwzPathModifier);
1606 if(!pTarget->_pwzPathModifier) {
1616 namespace LegacyFusion
1618 HRESULT SetStringProperty(IAssemblyName *pIAssemblyName,
1622 CAssemblyName *pAssemblyName = static_cast<CAssemblyName *>(pIAssemblyName);
1623 const WCHAR *pValue = value.GetUnicode();
1624 DWORD dwCBValue = (value.GetCount() + 1) * sizeof(WCHAR);
1626 return pAssemblyName->SetPropertyInternal(dwPropertyId,
1627 const_cast<WCHAR *>(pValue),
1631 HRESULT SetBufferProperty(IAssemblyName *pIAssemblyName,
1635 CAssemblyName *pAssemblyName = static_cast<CAssemblyName *>(pIAssemblyName);
1636 const BYTE *pValue = value; // special operator
1637 DWORD dwCBValue = value.GetSize() * sizeof(BYTE);
1639 return pAssemblyName->SetPropertyInternal(dwPropertyId,
1640 const_cast<BYTE *>(pValue),
1644 HRESULT SetWordProperty(IAssemblyName *pIAssemblyName,
1648 CAssemblyName *pAssemblyName = static_cast<CAssemblyName *>(pIAssemblyName);
1649 WORD wValue = static_cast<WORD>(dwValue);
1650 DWORD wCBValue = sizeof(WORD);
1652 // This file-internal function is and must be only used to set version fields
1653 PREFIX_ASSUME((dwPropertyId == ASM_NAME_MAJOR_VERSION) ||
1654 (dwPropertyId == ASM_NAME_MINOR_VERSION) ||
1655 (dwPropertyId == ASM_NAME_BUILD_NUMBER) ||
1656 (dwPropertyId == ASM_NAME_REVISION_NUMBER));
1658 return pAssemblyName->SetPropertyInternal(dwPropertyId, &wValue, wCBValue);
1661 HRESULT SetDwordProperty(IAssemblyName *pIAssemblyName,
1665 CAssemblyName *pAssemblyName = static_cast<CAssemblyName *>(pIAssemblyName);
1666 DWORD dwCBValue = sizeof(DWORD);
1668 return pAssemblyName->SetPropertyInternal(dwPropertyId, &dwValue, dwCBValue);
1677 inline bool IsNullProperty(DWORD dwProperty)
1679 LIMITED_METHOD_CONTRACT;
1680 return dwProperty == ASM_NAME_NULL_PUBLIC_KEY_TOKEN ||
1681 dwProperty == ASM_NAME_NULL_PUBLIC_KEY ||
1682 dwProperty == ASM_NAME_NULL_CUSTOM;
1685 HRESULT ConvertToUtf8(PCWSTR wzStr, __deref_out UTF8** pszStr)
1689 _ASSERTE(wzStr != nullptr && pszStr != nullptr);
1690 if (wzStr == nullptr || pszStr == nullptr)
1692 return E_INVALIDARG;
1695 DWORD cbSize = WszWideCharToMultiByte(CP_UTF8, 0, wzStr, -1, NULL, 0, NULL, NULL);
1698 return SUCCEEDED(hr = HRESULT_FROM_GetLastError()) ? E_UNEXPECTED : hr;
1701 NewArrayHolder<UTF8> szStr = new (nothrow) UTF8[cbSize];
1704 cbSize = WszWideCharToMultiByte(CP_UTF8, 0, wzStr, -1, static_cast<LPSTR>(szStr), cbSize, NULL, NULL);
1707 return SUCCEEDED(hr = HRESULT_FROM_GetLastError()) ? E_UNEXPECTED : hr;
1710 *pszStr = szStr.Extract();
1715 // Non-allocating helper.
1716 HRESULT GetProperty(IAssemblyName * pName, DWORD dwProperty, PVOID pBuf, DWORD *pcbBuf)
1718 LIMITED_METHOD_CONTRACT;
1721 _ASSERTE(pName != nullptr && pcbBuf != nullptr);
1722 if (pName == nullptr || pcbBuf == nullptr)
1724 return E_INVALIDARG;
1727 hr = pName->GetProperty(dwProperty, pBuf, pcbBuf);
1730 // Zero-length non-null property means there is no value.
1731 if (hr == S_OK && *pcbBuf == 0 && !priv::IsNullProperty(dwProperty))
1739 // Allocating helper.
1740 HRESULT GetProperty(IAssemblyName * pName, DWORD dwProperty, PBYTE * ppBuf, DWORD *pcbBuf)
1742 LIMITED_METHOD_CONTRACT;
1745 _ASSERTE(ppBuf != nullptr && (*ppBuf == nullptr || pcbBuf != nullptr));
1746 if (ppBuf == nullptr || (*ppBuf != nullptr && pcbBuf == nullptr))
1748 return E_INVALIDARG;
1752 if (pcbBuf == nullptr)
1755 hr = GetProperty(pName, dwProperty, *ppBuf, pcbBuf);
1757 // No provided buffer constitutes a request for one to be allocated.
1758 if (*ppBuf == nullptr)
1760 // If it's a null property, allocate a single-byte array to provide consistency.
1761 if (hr == S_OK && priv::IsNullProperty(dwProperty))
1763 *ppBuf = new (nothrow) BYTE[1];
1766 // Great, get the value.
1767 else if (hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER))
1769 NewArrayHolder<BYTE> pBuf = new (nothrow) BYTE[*pcbBuf];
1771 hr = pName->GetProperty(dwProperty, pBuf, pcbBuf);
1773 *ppBuf = pBuf.Extract();
1781 HRESULT GetProperty(IAssemblyName * pName, DWORD dwProperty, SString & ssVal)
1783 LIMITED_METHOD_CONTRACT;
1786 _ASSERTE(pName != nullptr);
1787 if (pName == nullptr)
1789 return E_INVALIDARG;
1793 hr = GetProperty(pName, dwProperty, static_cast<PBYTE>(nullptr), &cbSize);
1795 if (hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER))
1799 PWSTR wzNameBuf = ssVal.OpenUnicodeBuffer(cbSize / sizeof(WCHAR) - 1);
1800 hr = GetProperty(pName, dwProperty, reinterpret_cast<PBYTE>(wzNameBuf), &cbSize);
1801 ssVal.CloseBuffer();
1805 EX_CATCH_HRESULT(hr);
1812 HRESULT GetProperty(IAssemblyName * pName, DWORD dwProperty, __deref_out WCHAR ** pwzVal)
1814 LIMITED_METHOD_CONTRACT;
1817 _ASSERTE(pName != nullptr && pwzVal != nullptr);
1818 if (pName == nullptr || pwzVal == nullptr)
1820 return E_INVALIDARG;
1824 hr = pName->GetProperty(dwProperty, NULL, &cbSize);
1826 if (hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER))
1828 NewArrayHolder<WCHAR> wzVal = reinterpret_cast<PWSTR>(new (nothrow) BYTE[cbSize]);
1830 hr = pName->GetProperty(dwProperty, reinterpret_cast<PBYTE>(static_cast<PWSTR>(wzVal)), &cbSize);
1832 *pwzVal = wzVal.Extract();
1838 HRESULT GetProperty(IAssemblyName * pName, DWORD dwProperty, __deref_out UTF8 **pwzOut)
1840 LIMITED_METHOD_CONTRACT;
1843 if (pwzOut == nullptr)
1844 return E_INVALIDARG;
1846 SmallStackSString ssStr;
1847 hr = GetProperty(pName, dwProperty, ssStr);
1849 hr = priv::ConvertToUtf8(ssStr, pwzOut);