// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // ============================================================ // // BaseAssemblySpec.cpp // // Implements the BaseAssemblySpec class // // ============================================================ #include "common.h" #include "thekey.h" #include "strongnameinternal.h" #include "strongnameholders.h" VOID BaseAssemblySpec::CloneFieldsToStackingAllocator( StackingAllocator* alloc) { CONTRACTL { INSTANCE_CHECK; THROWS; GC_TRIGGERS; MODE_ANY; INJECT_FAULT(ThrowOutOfMemory();); } CONTRACTL_END #if _DEBUG DWORD hash = Hash(); #endif if ((~m_ownedFlags & NAME_OWNED) && m_pAssemblyName) { S_UINT32 len = S_UINT32((DWORD) strlen(m_pAssemblyName)) + S_UINT32(1); if(len.IsOverflow()) COMPlusThrowHR(COR_E_OVERFLOW); LPSTR temp = (LPSTR)alloc->Alloc(len); strcpy_s(temp, len.Value(), m_pAssemblyName); m_pAssemblyName = temp; } if ((~m_ownedFlags & PUBLIC_KEY_OR_TOKEN_OWNED) && m_pbPublicKeyOrToken && m_cbPublicKeyOrToken > 0) { BYTE *temp = (BYTE *)alloc->Alloc(S_UINT32(m_cbPublicKeyOrToken)) ; memcpy(temp, m_pbPublicKeyOrToken, m_cbPublicKeyOrToken); m_pbPublicKeyOrToken = temp; } if ((~m_ownedFlags & LOCALE_OWNED) && m_context.szLocale) { S_UINT32 len = S_UINT32((DWORD) strlen(m_context.szLocale)) + S_UINT32(1); if(len.IsOverflow()) COMPlusThrowHR(COR_E_OVERFLOW); LPSTR temp = (char *)alloc->Alloc(len) ; strcpy_s(temp, len.Value(), m_context.szLocale); m_context.szLocale = temp; } if ((~m_ownedFlags & CODEBASE_OWNED) && m_wszCodeBase) { S_UINT32 len = S_UINT32((DWORD) wcslen(m_wszCodeBase)) + S_UINT32(1); if(len.IsOverflow()) COMPlusThrowHR(COR_E_OVERFLOW); LPWSTR temp = (LPWSTR)alloc->Alloc(len*S_UINT32(sizeof(WCHAR))); wcscpy_s(temp, len.Value(), m_wszCodeBase); m_wszCodeBase = temp; } _ASSERTE(hash == Hash()); } BOOL BaseAssemblySpec::IsCoreLib() { CONTRACTL { THROWS; INSTANCE_CHECK; GC_TRIGGERS; MODE_ANY; INJECT_FAULT(COMPlusThrowOM();); } CONTRACTL_END; if (m_pAssemblyName == NULL) { LPCWSTR file = GetCodeBase(); if (file) { StackSString path(file); PEAssembly::UrlToPath(path); return SystemDomain::System()->IsBaseLibrary(path); } return FALSE; } _ASSERTE(strlen(g_psBaseLibraryName) == CoreLibNameLen); // More of bug 213471 size_t iNameLen = strlen(m_pAssemblyName); return ( (iNameLen >= CoreLibNameLen) && ( (!stricmpUTF8(m_pAssemblyName, g_psBaseLibrary)) || ( (!SString::_strnicmp(m_pAssemblyName, g_psBaseLibraryName, CoreLibNameLen)) && ( (iNameLen == CoreLibNameLen) || (m_pAssemblyName[CoreLibNameLen] == ',') ) ) ) ); } BOOL BaseAssemblySpec::IsAssemblySpecForCoreLib() { CONTRACTL { NOTHROW; INSTANCE_CHECK; GC_NOTRIGGER; MODE_ANY; PRECONDITION(strlen(g_psBaseLibraryName) == CoreLibNameLen); } CONTRACTL_END; BOOL fIsAssemblySpecForCoreLib = FALSE; if (m_pAssemblyName) { size_t iNameLen = strlen(m_pAssemblyName); fIsAssemblySpecForCoreLib = ( (iNameLen >= CoreLibNameLen) && ( (!_stricmp(m_pAssemblyName, g_psBaseLibrary)) || ( (!_strnicmp(m_pAssemblyName, g_psBaseLibraryName, CoreLibNameLen)) && ( (iNameLen == CoreLibNameLen) || (m_pAssemblyName[CoreLibNameLen] == ',') ) ) ) ); } return fIsAssemblySpecForCoreLib; } #define CORELIB_PUBLICKEY g_rbTheSilverlightPlatformKey // A satellite assembly for CoreLib is named "System.Private.CoreLib.resources" or // System.Private.CoreLib.debug.resources.dll and uses the same public key as CoreLib. // It does not necessarily have the same version, and the Culture will // always be set to something like "jp-JP". BOOL BaseAssemblySpec::IsCoreLibSatellite() const { CONTRACTL { THROWS; INSTANCE_CHECK; GC_TRIGGERS; MODE_ANY; INJECT_FAULT(COMPlusThrowOM();); } CONTRACTL_END; if (m_pAssemblyName == NULL) { LPCWSTR file = GetCodeBase(); if (file) { StackSString path(file); PEAssembly::UrlToPath(path); return SystemDomain::System()->IsBaseLibrarySatellite(path); } return FALSE; } _ASSERTE(strlen(g_psBaseLibrarySatelliteAssemblyName) == CoreLibSatelliteNameLen); // More of bug 213471 size_t iNameLen = strlen(m_pAssemblyName); // we allow name to be of the form System.Private.CoreLib.resources.dll only BOOL r = ( (m_cbPublicKeyOrToken == sizeof(CORELIB_PUBLICKEY)) && (iNameLen >= CoreLibSatelliteNameLen) && (!SString::_strnicmp(m_pAssemblyName, g_psBaseLibrarySatelliteAssemblyName, CoreLibSatelliteNameLen)) && ( (iNameLen == CoreLibSatelliteNameLen) || (m_pAssemblyName[CoreLibSatelliteNameLen] == ',') ) ); r = r && ( memcmp(m_pbPublicKeyOrToken,CORELIB_PUBLICKEY,sizeof(CORELIB_PUBLICKEY)) == 0); return r; } VOID BaseAssemblySpec::ConvertPublicKeyToToken() { CONTRACTL { INSTANCE_CHECK; THROWS; GC_NOTRIGGER; MODE_ANY; PRECONDITION(HasPublicKey()); } CONTRACTL_END; StrongNameBufferHolder pbPublicKeyToken; DWORD cbPublicKeyToken; IfFailThrow(StrongNameTokenFromPublicKey(m_pbPublicKeyOrToken, m_cbPublicKeyOrToken, &pbPublicKeyToken, &cbPublicKeyToken)); BYTE *temp = new BYTE [cbPublicKeyToken]; memcpy(temp, pbPublicKeyToken, cbPublicKeyToken); if (m_ownedFlags & PUBLIC_KEY_OR_TOKEN_OWNED) delete [] m_pbPublicKeyOrToken; else m_ownedFlags |= PUBLIC_KEY_OR_TOKEN_OWNED; m_pbPublicKeyOrToken = temp; m_cbPublicKeyOrToken = cbPublicKeyToken; m_dwFlags &= ~afPublicKey; } // Similar to BaseAssemblySpec::CompareEx, but allows the ref to be partially specified // Returns TRUE if ref matches def, FALSE otherwise. // // static BOOL BaseAssemblySpec::CompareRefToDef(const BaseAssemblySpec *pRef, const BaseAssemblySpec *pDef) { WRAPPER_NO_CONTRACT; if(pRef->m_wszCodeBase || pDef->m_wszCodeBase) { if(!pRef->m_wszCodeBase || !pDef->m_wszCodeBase) return FALSE; return wcscmp(pRef->m_wszCodeBase,(pDef->m_wszCodeBase)) == 0; } // Compare fields // // name is non-optional // if (pRef->m_pAssemblyName != pDef->m_pAssemblyName && (pRef->m_pAssemblyName == NULL || pDef->m_pAssemblyName == NULL || CompareStrings(pRef->m_pAssemblyName, pDef->m_pAssemblyName))) { return FALSE; } // // public key [token] is non-optional // if (pRef->m_cbPublicKeyOrToken != pDef->m_cbPublicKeyOrToken || memcmp(pRef->m_pbPublicKeyOrToken, pDef->m_pbPublicKeyOrToken, pRef->m_cbPublicKeyOrToken)) { return FALSE; } // // flags are non-optional, except processor architecture, content type, and debuggable attribute bits // DWORD dwFlagsMask = ~(afPA_FullMask | afContentType_Mask | afDebuggableAttributeMask); if ((pRef->m_dwFlags & dwFlagsMask) != (pDef->m_dwFlags & dwFlagsMask)) return FALSE; // To match Fusion behavior, we ignore processor architecture (GetAssemblyNameRefFromMDImport // does not look at architecture part of the flags, and having processor architecture in // InternalsVisibleTo attribute causess META_E_CA_BAD_FRIENDS_ARGS exception). // Content type is optional in pRef. if (!IsAfContentType_Default(pRef->m_dwFlags) && (pRef->m_dwFlags & afContentType_Mask) != (pDef->m_dwFlags & afContentType_Mask)) return FALSE; // // version info is optional in the ref // if (pRef->m_context.usMajorVersion != (USHORT) -1) { if (pRef->m_context.usMajorVersion != pDef->m_context.usMajorVersion) return FALSE; if (pRef->m_context.usMinorVersion != (USHORT) -1) { if (pRef->m_context.usMinorVersion != pDef->m_context.usMinorVersion) return FALSE; if (pRef->m_context.usBuildNumber != (USHORT) -1) { if (pRef->m_context.usBuildNumber != pDef->m_context.usBuildNumber) return FALSE; if (pRef->m_context.usRevisionNumber != (USHORT) -1) { if (pRef->m_context.usRevisionNumber != pDef->m_context.usRevisionNumber) return FALSE; } } } } // // locale info is optional in the ref // if ((pRef->m_context.szLocale != NULL) && (pRef->m_context.szLocale != pDef->m_context.szLocale) && strcmp(pRef->m_context.szLocale, pDef->m_context.szLocale)) { return FALSE; } return TRUE; } // static BOOL BaseAssemblySpec::RefMatchesDef(const BaseAssemblySpec* pRef, const BaseAssemblySpec* pDef) { CONTRACTL { THROWS; GC_NOTRIGGER; MODE_ANY; PRECONDITION(pRef->GetName()!=NULL && pDef->GetName()!=NULL); } CONTRACTL_END; if (pRef->IsStrongNamed()) { if (!pDef->IsStrongNamed()) return FALSE; if(pRef->HasPublicKey()) { // cannot use pRef->CompareEx(pDef) here because it does a full comparison // and the ref may be partial. return CompareRefToDef(pRef, pDef); } else { BaseAssemblySpec defCopy; defCopy.CopyFrom(pDef); defCopy.ConvertPublicKeyToToken(); return CompareRefToDef(pRef, &defCopy); } } else { return (CompareStrings(pRef->GetName(), pDef->GetName())==0); } } VOID BaseAssemblySpec::SetName(SString const & ssName) { CONTRACTL { INSTANCE_CHECK; GC_NOTRIGGER; THROWS; } CONTRACTL_END; if (m_ownedFlags & NAME_OWNED) { delete [] m_pAssemblyName; m_ownedFlags &= ~NAME_OWNED; } m_pAssemblyName = NULL; IfFailThrow(FString::ConvertUnicode_Utf8(ssName.GetUnicode(), & ((LPSTR &) m_pAssemblyName))); m_ownedFlags |= NAME_OWNED; }