Replaced the few places that need to parse assembly names in the VM with callbacks to CoreLib
using System.Configuration.Assemblies;
using System.Globalization;
-using System.IO;
using System.Runtime.CompilerServices;
-using System.Runtime.Serialization;
+using System.Runtime.InteropServices;
namespace System.Reflection
{
}
}
- public sealed partial class AssemblyName : ICloneable, IDeserializationCallback, ISerializable
+ public sealed partial class AssemblyName
{
internal unsafe AssemblyName(NativeAssemblyNameParts* pParts)
: this()
}
return ProcessorArchitecture.None;
}
+
+ private static unsafe void ParseAsAssemblySpec(char* pAssemblyName, void* pAssemblySpec)
+ {
+ AssemblyNameParser.AssemblyNameParts parts = AssemblyNameParser.Parse(MemoryMarshal.CreateReadOnlySpanFromNullTerminated(pAssemblyName));
+
+ fixed (char* pName = parts._name)
+ fixed (char* pCultureName = parts._cultureName)
+ fixed (byte* pPublicKeyOrToken = parts._publicKeyOrToken)
+ {
+ NativeAssemblyNameParts nameParts = default;
+
+ nameParts._flags = parts._flags;
+ nameParts._pName = pName;
+ nameParts._pCultureName = pCultureName;
+
+ nameParts._pPublicKeyOrToken = pPublicKeyOrToken;
+ nameParts._cbPublicKeyOrToken = (parts._publicKeyOrToken != null) ? parts._publicKeyOrToken.Length : 0;
+
+ nameParts.SetVersion(parts._version, defaultValue: ushort.MaxValue);
+
+ InitializeAssemblySpec(&nameParts, pAssemblySpec);
+ }
+ }
+
+ [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyName_InitializeAssemblySpec")]
+ private static unsafe partial void InitializeAssemblySpec(NativeAssemblyNameParts* pAssemblyNameParts, void* pAssemblySpec);
}
}
applicationcontext.cpp
assembly.cpp
assemblybindercommon.cpp
- assemblyidentitycache.cpp
assemblyname.cpp
bindertracing.cpp
defaultassemblybinder.cpp
failurecache.cpp
- stringlexer.cpp
textualidentityparser.cpp
utils.cpp
)
inc/assemblyentry.hpp
inc/assemblyhashtraits.hpp
inc/assemblyidentity.hpp
- inc/assemblyidentitycache.hpp
inc/assemblyname.hpp
inc/assemblyname.inl
inc/assemblyversion.hpp
inc/failurecachehashtraits.hpp
inc/loadcontext.hpp
inc/loadcontext.inl
- inc/stringlexer.hpp
- inc/stringlexer.inl
inc/textualidentityparser.hpp
inc/utils.hpp
)
#include "stringarraylist.h"
#include "loadcontext.hpp"
#include "failurecache.hpp"
-#include "assemblyidentitycache.hpp"
#include "utils.hpp"
#include "ex.h"
#include "clr/fs/path.h"
return hr;
}
- HRESULT ApplicationContext::GetAssemblyIdentity(LPCSTR szTextualIdentity,
- AssemblyIdentityUTF8 **ppAssemblyIdentity)
- {
- HRESULT hr = S_OK;
-
- _ASSERTE(szTextualIdentity != NULL);
- _ASSERTE(ppAssemblyIdentity != NULL);
-
- CRITSEC_Holder contextLock(GetCriticalSectionCookie());
-
- AssemblyIdentityUTF8 *pAssemblyIdentity = m_assemblyIdentityCache.Lookup(szTextualIdentity);
- if (pAssemblyIdentity == NULL)
- {
- NewHolder<AssemblyIdentityUTF8> pNewAssemblyIdentity;
- SString sTextualIdentity;
-
- SAFE_NEW(pNewAssemblyIdentity, AssemblyIdentityUTF8);
- sTextualIdentity.SetUTF8(szTextualIdentity);
-
- IF_FAIL_GO(TextualIdentityParser::Parse(sTextualIdentity, pNewAssemblyIdentity));
- IF_FAIL_GO(m_assemblyIdentityCache.Add(szTextualIdentity, pNewAssemblyIdentity));
-
- pNewAssemblyIdentity->PopulateUTF8Fields();
-
- pAssemblyIdentity = pNewAssemblyIdentity.Extract();
- }
-
- *ppAssemblyIdentity = pAssemblyIdentity;
-
- Exit:
- return hr;
- }
-
bool ApplicationContext::IsTpaListProvided()
{
return m_pTrustedPlatformAssemblyMap != nullptr;
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// ============================================================
-//
-// AssemblyIdentityCache.cpp
-//
-
-
-//
-// Implements the AssemblyIdentityCache class
-//
-// ============================================================
-
-#include "assemblyidentitycache.hpp"
-
-namespace BINDER_SPACE
-{
- AssemblyIdentityCache::AssemblyIdentityCache() : SHash<AssemblyIdentityHashTraits>::SHash()
- {
- // Nothing to do here
- }
-
- AssemblyIdentityCache::~AssemblyIdentityCache()
- {
- // Delete entries and contents array
- for (Hash::Iterator i = Hash::Begin(), end = Hash::End(); i != end; i++)
- {
- const AssemblyIdentityCacheEntry *pAssemblyIdentityCacheEntry = *i;
- delete pAssemblyIdentityCacheEntry;
- }
- RemoveAll();
- }
-
- HRESULT AssemblyIdentityCache::Add(LPCSTR szTextualIdentity,
- AssemblyIdentityUTF8 *pAssemblyIdentity)
- {
- HRESULT hr = S_OK;
-
- NewHolder<AssemblyIdentityCacheEntry> pAssemblyIdentityCacheEntry;
- SAFE_NEW(pAssemblyIdentityCacheEntry, AssemblyIdentityCacheEntry);
-
- pAssemblyIdentityCacheEntry->SetTextualIdentity(szTextualIdentity);
- pAssemblyIdentityCacheEntry->SetAssemblyIdentity(pAssemblyIdentity);
-
- Hash::Add(pAssemblyIdentityCacheEntry);
- pAssemblyIdentityCacheEntry.SuppressRelease();
-
- Exit:
- return hr;
- }
-
- AssemblyIdentityUTF8 *AssemblyIdentityCache::Lookup(LPCSTR szTextualIdentity)
- {
- AssemblyIdentityUTF8 *pAssemblyIdentity = NULL;
- AssemblyIdentityCacheEntry *pAssemblyIdentityCacheEntry = Hash::Lookup(szTextualIdentity);
-
- if (pAssemblyIdentityCacheEntry != NULL)
- {
- pAssemblyIdentity = pAssemblyIdentityCacheEntry->GetAssemblyIdentity();
- }
-
- return pAssemblyIdentity;
- }
-};
#include "bindertypes.hpp"
#include "failurecache.hpp"
-#include "assemblyidentitycache.hpp"
#include "stringarraylist.h"
namespace BINDER_SPACE
/* in */ SString &sAppPaths,
/* in */ BOOL fAcquireLock);
- HRESULT GetAssemblyIdentity(/* in */ LPCSTR szTextualIdentity,
- /* in */ AssemblyIdentityUTF8 **ppAssemblyIdentity);
-
// Getters/Setter
inline ExecutionContext *GetExecutionContext();
inline FailureCache *GetFailureCache();
FailureCache *m_pFailureCache;
CRITSEC_COOKIE m_contextCS;
- AssemblyIdentityCache m_assemblyIdentityCache;
-
StringArrayList m_platformResourceRoots;
StringArrayList m_appPaths;
namespace BINDER_SPACE
{
- class AssemblyIdentityUTF8;
-
class AssemblyBinderCommon
{
public:
AssemblyContentType m_kContentType;
DWORD m_dwIdentityFlags;
};
-
- class AssemblyIdentityUTF8 final : public AssemblyIdentity
- {
- public:
- AssemblyIdentityUTF8()
- {
- m_szSimpleNameUTF8 = NULL;
- m_szCultureOrLanguageUTF8 = NULL;
- }
-
- void PopulateUTF8Fields()
- {
- m_szSimpleNameUTF8 = m_simpleName.GetUTF8(sSimpleNameBuffer);
-
- if (Have(IDENTITY_FLAG_CULTURE) && !m_cultureOrLanguage.IsEmpty())
- {
- m_szCultureOrLanguageUTF8 = m_cultureOrLanguage.GetUTF8(sCultureBuffer);
- }
- }
-
- inline LPCSTR GetSimpleNameUTF8()
- {
- return m_szSimpleNameUTF8;
- }
-
- inline LPCSTR GetCultureOrLanguageUTF8()
- {
- return m_szCultureOrLanguageUTF8;
- }
-
- inline const BYTE *GetPublicKeyOrTokenArray()
- {
- const BYTE *pPublicKeyOrToken = m_publicKeyOrTokenBLOB;
-
- return pPublicKeyOrToken;
- }
-
- protected:
- StackScratchBuffer sSimpleNameBuffer;
- StackScratchBuffer sCultureBuffer;
- LPCSTR m_szSimpleNameUTF8;
- LPCSTR m_szCultureOrLanguageUTF8;
- };
};
#endif
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// ============================================================
-//
-// AssemblyIdentityCache.hpp
-//
-
-
-//
-// Defines the AssemblyIdentityCache class and its helpers
-//
-// ============================================================
-
-#ifndef __BINDER__ASSEMBLY_IDENTITY_CACHE_HPP__
-#define __BINDER__ASSEMBLY_IDENTITY_CACHE_HPP__
-
-#include "bindertypes.hpp"
-#include "assemblyidentity.hpp"
-#include "sstring.h"
-#include "shash.h"
-
-namespace BINDER_SPACE
-{
- class AssemblyIdentityCacheEntry
- {
- public:
- inline AssemblyIdentityCacheEntry()
- {
- m_szTextualIdentity = NULL;
- m_pAssemblyIdentity = NULL;
- }
- inline ~AssemblyIdentityCacheEntry()
- {
- SAFE_DELETE_ARRAY(m_szTextualIdentity);
- SAFE_DELETE(m_pAssemblyIdentity);
- }
-
- // Getters/Setters
- inline LPCSTR GetTextualIdentity()
- {
- return m_szTextualIdentity;
- }
- inline void SetTextualIdentity(LPCSTR szTextualIdentity)
- {
- size_t len = strlen(szTextualIdentity) + 1;
-
- m_szTextualIdentity = new char[len];
- strcpy_s((LPSTR) m_szTextualIdentity, len, szTextualIdentity);
- }
- inline AssemblyIdentityUTF8 *GetAssemblyIdentity()
- {
- return m_pAssemblyIdentity;
- }
- inline void SetAssemblyIdentity(AssemblyIdentityUTF8 *pAssemblyIdentity)
- {
- m_pAssemblyIdentity = pAssemblyIdentity;
- }
-
- protected:
- LPCSTR m_szTextualIdentity;
- AssemblyIdentityUTF8 *m_pAssemblyIdentity;
- };
-
- class AssemblyIdentityHashTraits : public DefaultSHashTraits<AssemblyIdentityCacheEntry *>
- {
- public:
- typedef LPCSTR key_t;
-
- static key_t GetKey(element_t pAssemblyIdentityCacheEntry)
- {
- return pAssemblyIdentityCacheEntry->GetTextualIdentity();
- }
- static BOOL Equals(key_t textualIdentity1, key_t textualIdentity2)
- {
- if ((textualIdentity1 == NULL) && (textualIdentity2 == NULL))
- return TRUE;
- if ((textualIdentity1 == NULL) || (textualIdentity2 == NULL))
- return FALSE;
-
- return (strcmp(textualIdentity1, textualIdentity2) == 0);
- }
- static count_t Hash(key_t textualIdentity)
- {
- if (textualIdentity == NULL)
- return 0;
- else
- return HashStringA(textualIdentity);
- }
- static element_t Null()
- {
- return NULL;
- }
- static bool IsNull(const element_t &assemblyIdentityCacheEntry)
- {
- return (assemblyIdentityCacheEntry == NULL);
- }
-
- };
-
- class AssemblyIdentityCache : protected SHash<AssemblyIdentityHashTraits>
- {
- private:
- typedef SHash<AssemblyIdentityHashTraits> Hash;
- public:
- AssemblyIdentityCache();
- ~AssemblyIdentityCache();
-
- HRESULT Add(/* in */ LPCSTR szTextualIdentity,
- /* in */ AssemblyIdentityUTF8 *pAssemblyIdentity);
- AssemblyIdentityUTF8 *Lookup(/* in */ LPCSTR szTextualIdentity);
- };
-};
-
-#endif
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// ============================================================
-//
-// StringLexer.hpp
-//
-
-
-//
-// Defines the StringLexer class
-//
-// ============================================================
-
-#ifndef __BINDER__STRING_LEXER_HPP__
-#define __BINDER__STRING_LEXER_HPP__
-
-#include "bindertypes.hpp"
-
-#define GO_IF_NOT_EXPECTED(expr, kRequiredLexemeType) \
- if ((expr) != kRequiredLexemeType) \
- { \
- fIsValid = FALSE; \
- goto Exit; \
- }
-
-#define GO_IF_END_OR_NOT_EXPECTED(expr, kRequiredLexemeType) \
- { \
- LEXEME_TYPE kGotLexemeType = (expr); \
- if (kGotLexemeType == LEXEME_TYPE_END_OF_STREAM) \
- { \
- goto Exit; \
- } \
- else \
- { \
- GO_IF_NOT_EXPECTED(kGotLexemeType, kRequiredLexemeType); \
- } \
- }
-
-namespace BINDER_SPACE
-{
- class StringLexer
- {
- public:
- typedef enum
- {
- LEXEME_TYPE_INVALID,
- LEXEME_TYPE_EQUALS,
- LEXEME_TYPE_COMMA,
- LEXEME_TYPE_COLON,
- LEXEME_TYPE_SEMICOLON,
- LEXEME_TYPE_STRING,
- LEXEME_TYPE_END_OF_STREAM
- } LEXEME_TYPE;
-
- inline StringLexer();
- inline ~StringLexer();
-
- inline void Init(SString &inputString);
-
- static inline BOOL IsWhitespace(WCHAR wcChar);
- static inline BOOL IsEOS(WCHAR wcChar);
- static inline BOOL IsQuoteCharacter(WCHAR wcChar);
-
- BOOL IsSeparatorChar(WCHAR wcChar);
- LEXEME_TYPE GetLexemeType(WCHAR wcChar);
-
- protected:
- static const WCHAR INVALID_CHARACTER = -1;
-
- LEXEME_TYPE GetNextLexeme(SString ¤tString);
-
- inline WCHAR PopCharacter(BOOL *pfIsEscaped);
- inline void PushCharacter(WCHAR wcCurrentChar,
- BOOL fIsEscaped);
-
- inline WCHAR GetRawCharacter();
- inline WCHAR GetNextCharacter(BOOL *pfIsEscaped);
-
- LEXEME_TYPE ParseString(SString ¤tString);
-
- void TrimTrailingWhiteSpaces(SString ¤tString);
-
- SString::Iterator m_cursor;
- SString::Iterator m_end;
-
- WCHAR m_wcCurrentChar;
- BOOL m_fCurrentCharIsEscaped;
- };
-
-#include "stringlexer.inl"
-};
-
-#endif
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// ============================================================
-//
-// StringLexer.inl
-//
-
-
-//
-// Implements the inlined methods of StringLexer class
-//
-// ============================================================
-
-#ifndef __BINDER__STRING_LEXER_INL__
-#define __BINDER__STRING_LEXER_INL__
-
-StringLexer::StringLexer()
-{
- m_wcCurrentChar = INVALID_CHARACTER;
- m_fCurrentCharIsEscaped = FALSE;
-}
-
-StringLexer::~StringLexer()
-{
- // Nothing to do here
-}
-
-void StringLexer::Init(SString &inputString)
-{
- m_cursor = inputString.Begin();
- m_end = inputString.End();
-}
-
-BOOL StringLexer::IsWhitespace(WCHAR wcChar)
-{
- return ((wcChar == L'\n') || (wcChar == L'\r') || (wcChar == L' ') || (wcChar == L'\t'));
-}
-
-BOOL StringLexer::IsEOS(WCHAR wcChar)
-{
- return (wcChar == 0);
-}
-
-BOOL StringLexer::IsQuoteCharacter(WCHAR wcChar)
-{
- return ((wcChar == L'\'') || (wcChar == L'"'));
-}
-
-WCHAR StringLexer::PopCharacter(BOOL *pfIsEscaped)
-{
- WCHAR wcCurrentChar = m_wcCurrentChar;
- if (wcCurrentChar != INVALID_CHARACTER)
- {
- m_wcCurrentChar = INVALID_CHARACTER;
- *pfIsEscaped = m_fCurrentCharIsEscaped;
- m_cursor++;
- }
- else
- {
- wcCurrentChar = GetNextCharacter(pfIsEscaped);
- }
-
- return wcCurrentChar;
-}
-
-void StringLexer::PushCharacter(WCHAR wcCurrentChar,
- BOOL fIsEscaped)
-{
- _ASSERTE(m_wcCurrentChar == INVALID_CHARACTER);
-
- m_wcCurrentChar = wcCurrentChar;
- m_fCurrentCharIsEscaped = fIsEscaped;
- m_cursor--;
-}
-
-WCHAR StringLexer::GetRawCharacter()
-{
- WCHAR wcCurrentChar = 0;
-
- if (m_cursor < m_end)
- {
- wcCurrentChar = m_cursor[0];
- m_cursor++;
-
- // do not allow \0 anywhere in the string.
- if (wcCurrentChar == 0)
- {
- wcCurrentChar = INVALID_CHARACTER;
- }
- }
- else
- {
- // EOS
- wcCurrentChar = 0;
- }
-
- return wcCurrentChar;
-}
-
-WCHAR StringLexer::GetNextCharacter(BOOL *pfIsEscaped)
-{
- *pfIsEscaped = FALSE;
-
- WCHAR wcCurrentChar = GetRawCharacter();
- if (wcCurrentChar == L'\\')
- {
- WCHAR wcTempChar = GetRawCharacter();
-
- // Handle standard escapes
- switch (wcTempChar)
- {
- case L'"':
- case L'\'':
- case L',':
- case L'\\':
- case L'=':
- case L't':
- case L'n':
- case L'r':
- break;
- default:
- return INVALID_CHARACTER;
- }
-
- *pfIsEscaped = TRUE;
- wcCurrentChar = wcTempChar;
- }
-
- return wcCurrentChar;
-}
-
-#endif
#define __BINDER__TEXTUAL_IDENTITY_PARSER_HPP__
#include "bindertypes.hpp"
-#include "stringlexer.hpp"
namespace BINDER_SPACE
{
class AssemblyVersion;
class AssemblyIdentity;
- class TextualIdentityParser : public StringLexer
+ class TextualIdentityParser
{
public:
- TextualIdentityParser(AssemblyIdentity *pAssemblyIdentity);
- ~TextualIdentityParser();
-
- static HRESULT Parse(/* in */ SString &textualIdentity,
- /* out */ AssemblyIdentity *pAssemblyIdentity);
-
static HRESULT ToString(/* in */ AssemblyIdentity *pAssemblyIdentity,
/* in */ DWORD dwIdentityFlags,
/* out */ SString &textualIdentity);
- static BOOL ParseVersion(/* in */ SString &versionString,
- /* out */ AssemblyVersion *pAssemblyVersion);
-
- static BOOL HexToBlob(/* in */ SString &publicKeyOrToken,
- /* in */ BOOL fValidateHex,
- /* in */ BOOL fIsToken,
- /* out */ SBuffer &publicKeyOrTokenBLOB);
-
static void BlobToHex(/* in */ SBuffer &publicKeyOrTokenBLOB,
/* out */ SString &publicKeyOrToken);
- BOOL ParseString(/* in */ SString &textualString,
- /* out */ SString &contentString);
-
protected:
- BOOL Parse(/* in */ SString &textualIdentity);
-
- BOOL PopulateAssemblyIdentity(/* in */ SString &attributeString,
- /* in */ SString &valueString);
-
static void EscapeString(/* in */ SString &input,
/* out*/ SString &result);
-
- AssemblyIdentity *m_pAssemblyIdentity;
- DWORD m_dwAttributesSeen;
};
};
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// ============================================================
-//
-// StringLexer.cpp
-//
-
-
-//
-// Implements the StringLexer class
-//
-// ============================================================
-
-#include "stringlexer.hpp"
-#include "utils.hpp"
-
-#include "ex.h"
-
-namespace BINDER_SPACE
-{
- StringLexer::LEXEME_TYPE
- StringLexer::GetNextLexeme(SString ¤tString)
- {
- BOOL fIsEscaped = FALSE;
- WCHAR wcCurrentChar = INVALID_CHARACTER;
-
- // Remove any white spaces
- do
- {
- wcCurrentChar = PopCharacter(&fIsEscaped);
- }
- while (IsWhitespace(wcCurrentChar));
-
- // Determine lexeme type
- if (!fIsEscaped)
- {
- LEXEME_TYPE kLexemeType = GetLexemeType(wcCurrentChar);
- if (kLexemeType != LEXEME_TYPE_STRING)
- {
- return kLexemeType;
- }
- }
-
- // First character of string lexeme; push it back
- PushCharacter(wcCurrentChar, fIsEscaped);
- return ParseString(currentString);
- }
-
- StringLexer::LEXEME_TYPE
- StringLexer::ParseString(SString ¤tString)
- {
- BOOL fIsFirstCharacter = TRUE;
- WCHAR wcCurrentChar = INVALID_CHARACTER;
- WCHAR wcOpeningQuote = INVALID_CHARACTER;
-
- currentString.Clear();
-
- // Read until we find another lexeme that's not a string character
- for (;;)
- {
- BOOL fIsEscaped = FALSE;
- wcCurrentChar = PopCharacter(&fIsEscaped);
-
- if (wcCurrentChar == INVALID_CHARACTER)
- {
- // Found invalid character encoding
- return LEXEME_TYPE_INVALID;
- }
-
- if (IsEOS(wcCurrentChar))
- {
- if (IsQuoteCharacter(wcOpeningQuote))
- {
- // EOS and unclosed quotes is an error
- return LEXEME_TYPE_INVALID;
- }
- else
- {
- // Reached end of input and therefore of string
- break;
- }
- }
-
- if (fIsFirstCharacter)
- {
- fIsFirstCharacter = FALSE;
-
- // If first character is quote, then record its quoteness
- if (IsQuoteCharacter(wcCurrentChar))
- {
- wcOpeningQuote = wcCurrentChar;
- continue;
- }
- }
-
- if (wcCurrentChar == wcOpeningQuote)
- {
- // We've found the closing quote for a quoted string
- break;
- }
-
- if (!fIsEscaped && IsQuoteCharacter(wcCurrentChar) && !IsQuoteCharacter(wcOpeningQuote))
- {
- // Unescaped quotes in the middle of the string are an error
- return LEXEME_TYPE_INVALID;
- }
-
- if (IsSeparatorChar(wcCurrentChar) && !IsQuoteCharacter(wcOpeningQuote) && !fIsEscaped)
- {
- // Unescaped separator char terminates the string
- PushCharacter(wcCurrentChar, fIsEscaped);
- break;
- }
-
- // Add character to current string
- currentString.Append(wcCurrentChar);
- }
-
- if (!IsQuoteCharacter(wcOpeningQuote))
- {
- // Remove trailing white spaces from unquoted string
- TrimTrailingWhiteSpaces(currentString);
- }
-
- return LEXEME_TYPE_STRING;
- }
-
- void StringLexer::TrimTrailingWhiteSpaces(SString ¤tString)
- {
- SString::Iterator begin = currentString.Begin();
- SString::Iterator cursor = currentString.End() - 1;
- BOOL fFoundWhiteSpace = FALSE;
-
- for (;;)
- {
- if ((cursor >= begin) && IsWhitespace(cursor[0]))
- {
- fFoundWhiteSpace = TRUE;
- cursor--;
- continue;
- }
- break;
- }
-
- if (fFoundWhiteSpace)
- {
- currentString.Truncate(cursor + 1);
- }
- }
-
- BOOL StringLexer::IsSeparatorChar(WCHAR wcChar)
- {
- return ((wcChar == W(',')) || (wcChar == W('=')));
- }
-
- StringLexer::LEXEME_TYPE StringLexer::GetLexemeType(WCHAR wcChar)
- {
- switch (wcChar)
- {
- case W('='):
- return LEXEME_TYPE_EQUALS;
- case W(','):
- return LEXEME_TYPE_COMMA;
- case 0:
- return LEXEME_TYPE_END_OF_STREAM;
- default:
- return LEXEME_TYPE_STRING;
- }
- }
-};
#include "ex.h"
-#define GO_IF_SEEN(kAssemblyIdentityFlag) \
- if ((m_dwAttributesSeen & kAssemblyIdentityFlag) != 0) \
- { \
- fIsValid = FALSE; \
- goto Exit; \
- } \
- else \
- { \
- m_dwAttributesSeen |= kAssemblyIdentityFlag; \
- }
-
-#define GO_IF_WILDCARD(valueString) \
- { \
- SmallStackSString wildCard(W("*")); \
- if (valueString.Equals(wildCard)) \
- { \
- goto Exit; \
- } \
- }
-
-#define GO_IF_VALIDATE_FAILED(validateProc, kIdentityFlag) \
- if (!validateProc(valueString)) \
- { \
- fIsValid = FALSE; \
- goto Exit; \
- } \
- else \
- { \
- m_pAssemblyIdentity->SetHave(kIdentityFlag); \
- }
-
-#define FROMHEX(a) ((a)>=W('a') ? a - W('a') + 10 : a - W('0'))
#define TOHEX(a) ((a)>=10 ? W('a')+(a)-10 : W('0')+(a))
#define TOLOWER(a) (((a) >= W('A') && (a) <= W('Z')) ? (W('a') + (a - W('A'))) : (a))
const int iVersionMax = 65535;
const int iVersionParts = 4;
- inline void UnicodeHexToBin(LPCWSTR pSrc, UINT cSrc, LPBYTE pDest)
- {
- BYTE v;
- LPBYTE pd = pDest;
- LPCWSTR ps = pSrc;
-
- if (cSrc == 0)
- return;
-
- for (UINT i = 0; i < cSrc-1; i+=2)
- {
- v = (BYTE)FROMHEX(TOLOWER(ps[i])) << 4;
- v |= FROMHEX(TOLOWER(ps[i+1]));
- *(pd++) = v;
- }
- }
-
inline void BinToUnicodeHex(const BYTE *pSrc, UINT cSrc, _Out_writes_(2*cSrc) LPWSTR pDst)
{
UINT x;
}
}
- inline bool EqualsCaseInsensitive(const SString &a, LPCWSTR wzB)
- {
- return SString::_wcsicmp(a.GetUnicode(), wzB) == 0;
- }
-
- BOOL ValidateHex(SString &publicKeyOrToken)
- {
- if ((publicKeyOrToken.GetCount() == 0) || ((publicKeyOrToken.GetCount() % 2) != 0))
- {
- return FALSE;
- }
-
- SString::Iterator cursor = publicKeyOrToken.Begin();
- SString::Iterator end = publicKeyOrToken.End() - 1;
-
- while (cursor <= end)
- {
- WCHAR wcCurrentChar = cursor[0];
-
- if (((wcCurrentChar >= W('0')) && (wcCurrentChar <= W('9'))) ||
- ((wcCurrentChar >= W('a')) && (wcCurrentChar <= W('f'))) ||
- ((wcCurrentChar >= W('A')) && (wcCurrentChar <= W('F'))))
- {
- cursor++;
- continue;
- }
-
- return FALSE;
- }
-
- return TRUE;
- }
-
- inline BOOL ValidatePublicKeyToken(SString &publicKeyToken)
- {
- return ((publicKeyToken.GetCount() == (iPublicKeyTokenLength * 2)) &&
- ValidateHex(publicKeyToken));
- }
-
- inline BOOL ValidatePublicKey(SString &publicKey)
- {
- return ValidateHex(publicKey);
- }
-
const struct {
LPCWSTR strValue;
PEKIND enumValue;
{ W("ARM"), peARM },
{ W("MSIL"), peMSIL } };
- BOOL ValidateAndConvertProcessorArchitecture(SString &processorArchitecture,
- PEKIND *pkProcessorArchitecture)
- {
- for (int i = LENGTH_OF(wszKnownArchitectures); i--;)
- {
- if (EqualsCaseInsensitive(processorArchitecture, wszKnownArchitectures[i].strValue))
- {
- *pkProcessorArchitecture = wszKnownArchitectures[i].enumValue;
- return TRUE;
- }
- }
-
- return FALSE;
- }
-
LPCWSTR PeKindToString(PEKIND kProcessorArchitecture)
{
_ASSERTE(kProcessorArchitecture != peNone);
return NULL;
}
- }; // namespace (anonymous)
-
- TextualIdentityParser::TextualIdentityParser(AssemblyIdentity *pAssemblyIdentity)
- {
- m_pAssemblyIdentity = pAssemblyIdentity;
- m_dwAttributesSeen = AssemblyIdentity::IDENTITY_FLAG_EMPTY;
- }
-
- TextualIdentityParser::~TextualIdentityParser()
- {
- // Nothing to do here
- }
-
- /* static */
- HRESULT TextualIdentityParser::Parse(SString &textualIdentity,
- AssemblyIdentity *pAssemblyIdentity)
- {
- HRESULT hr = S_OK;
- IF_FALSE_GO(pAssemblyIdentity != NULL);
-
- EX_TRY
+ BOOL IsWhitespace(WCHAR wcChar)
{
- TextualIdentityParser identityParser(pAssemblyIdentity);
-
- if (!identityParser.Parse(textualIdentity))
- {
- IF_FAIL_GO(FUSION_E_INVALID_NAME);
- }
+ return ((wcChar == L'\n') || (wcChar == L'\r') || (wcChar == L' ') || (wcChar == L'\t'));
}
- EX_CATCH_HRESULT(hr);
-
- Exit:
- return hr;
- }
+ }; // namespace (anonymous)
/* static */
HRESULT TextualIdentityParser::ToString(AssemblyIdentity *pAssemblyIdentity,
}
/* static */
- BOOL TextualIdentityParser::ParseVersion(SString &versionString,
- AssemblyVersion *pAssemblyVersion)
- {
- BOOL fIsValid = FALSE;
- DWORD dwFoundNumbers = 0;
- bool foundUnspecifiedComponent = false;
- const DWORD UnspecifiedNumber = (DWORD)-1;
- DWORD dwCurrentNumber = UnspecifiedNumber;
- DWORD dwNumbers[iVersionParts] = {UnspecifiedNumber, UnspecifiedNumber, UnspecifiedNumber, UnspecifiedNumber};
-
- if (versionString.GetCount() > 0) {
- SString::Iterator cursor = versionString.Begin();
- SString::Iterator end = versionString.End();
-
- while (cursor <= end)
- {
- WCHAR wcCurrentChar = cursor[0];
-
- if (dwFoundNumbers >= static_cast<DWORD>(iVersionParts))
- {
- goto Exit;
- }
- else if (wcCurrentChar == W('.') || wcCurrentChar == W('\0'))
- {
- if (dwCurrentNumber == UnspecifiedNumber)
- {
- // Difference from .NET Framework, compat with Version(string) constructor: A missing version component
- // is considered invalid.
- //
- // Examples:
- // "MyAssembly, Version=."
- // "MyAssembly, Version=1."
- // "MyAssembly, Version=.1"
- // "MyAssembly, Version=1..1"
- goto Exit;
- }
-
- // Compat with .NET Framework: A value of iVersionMax is considered unspecified. Once an unspecified
- // component is found, validate the remaining components but consider them as unspecified as well.
- if (dwCurrentNumber == iVersionMax)
- {
- foundUnspecifiedComponent = true;
- dwCurrentNumber = UnspecifiedNumber;
- }
- else if (!foundUnspecifiedComponent)
- {
- dwNumbers[dwFoundNumbers] = dwCurrentNumber;
- dwCurrentNumber = UnspecifiedNumber;
- }
-
- dwFoundNumbers++;
- }
- else if ((wcCurrentChar >= W('0')) && (wcCurrentChar <= W('9')))
- {
- if (dwCurrentNumber == UnspecifiedNumber)
- {
- dwCurrentNumber = 0;
- }
- dwCurrentNumber = (dwCurrentNumber * 10) + (wcCurrentChar - W('0'));
-
- if (dwCurrentNumber > static_cast<DWORD>(iVersionMax))
- {
- goto Exit;
- }
- }
- else
- {
- goto Exit;
- }
-
- cursor++;
- }
-
- // Difference from .NET Framework: If the major or minor version are unspecified, the version is considered invalid.
- //
- // Examples:
- // "MyAssembly, Version="
- // "MyAssembly, Version=1"
- // "MyAssembly, Version=65535.1"
- // "MyAssembly, Version=1.65535"
- if (dwFoundNumbers < 2 || dwNumbers[0] == UnspecifiedNumber || dwNumbers[1] == UnspecifiedNumber)
- {
- goto Exit;
- }
-
- pAssemblyVersion->SetFeatureVersion(dwNumbers[0], dwNumbers[1]);
- pAssemblyVersion->SetServiceVersion(dwNumbers[2], dwNumbers[3]);
- fIsValid = TRUE;
- }
-
- Exit:
- return fIsValid;
- }
-
- /* static */
- BOOL TextualIdentityParser::HexToBlob(SString &publicKeyOrToken,
- BOOL fValidateHex,
- BOOL fIsToken,
- SBuffer &publicKeyOrTokenBLOB)
- {
- // Optional input verification
- if (fValidateHex)
- {
- if ((fIsToken && !ValidatePublicKeyToken(publicKeyOrToken)) ||
- (!fIsToken && !ValidatePublicKey(publicKeyOrToken)))
- {
- return FALSE;
- }
- }
-
- UINT ccPublicKeyOrToken = publicKeyOrToken.GetCount();
- BYTE *pByteBLOB = publicKeyOrTokenBLOB.OpenRawBuffer(ccPublicKeyOrToken / 2);
-
- UnicodeHexToBin(publicKeyOrToken.GetUnicode(), ccPublicKeyOrToken, pByteBLOB);
- publicKeyOrTokenBLOB.CloseRawBuffer();
-
- return TRUE;
- }
-
- /* static */
void TextualIdentityParser::BlobToHex(SBuffer &publicKeyOrTokenBLOB,
SString &publicKeyOrToken)
{
publicKeyOrToken.CloseBuffer(cbPublicKeyOrTokenBLOB * 2);
}
- BOOL TextualIdentityParser::Parse(SString &textualIdentity)
- {
- BOOL fIsValid = TRUE;
- SString unicodeTextualIdentity;
-
- // Lexer modifies input string
- textualIdentity.ConvertToUnicode(unicodeTextualIdentity);
- Init(unicodeTextualIdentity);
-
- SmallStackSString currentString;
-
- // Identity format is simple name (, attr = value)*
- GO_IF_NOT_EXPECTED(GetNextLexeme(currentString), LEXEME_TYPE_STRING);
- m_pAssemblyIdentity->m_simpleName.Set(currentString);
- m_pAssemblyIdentity->m_simpleName.Normalize();
- m_pAssemblyIdentity->SetHave(AssemblyIdentity::IDENTITY_FLAG_SIMPLE_NAME);
-
- for (;;)
- {
- SmallStackSString attributeString;
- SmallStackSString valueString;
-
- GO_IF_END_OR_NOT_EXPECTED(GetNextLexeme(currentString), LEXEME_TYPE_COMMA);
- GO_IF_NOT_EXPECTED(GetNextLexeme(attributeString), LEXEME_TYPE_STRING);
- GO_IF_NOT_EXPECTED(GetNextLexeme(currentString), LEXEME_TYPE_EQUALS);
- GO_IF_NOT_EXPECTED(GetNextLexeme(valueString), LEXEME_TYPE_STRING);
-
- if (!PopulateAssemblyIdentity(attributeString, valueString))
- {
- fIsValid = FALSE;
- break;
- }
- }
-
- Exit:
- return fIsValid;
- }
-
- BOOL TextualIdentityParser::ParseString(SString &textualString,
- SString &contentString)
- {
- BOOL fIsValid = TRUE;
- SString unicodeTextualString;
-
- // Lexer modifies input string
- textualString.ConvertToUnicode(unicodeTextualString);
- Init(unicodeTextualString);
-
- SmallStackSString currentString;
- GO_IF_NOT_EXPECTED(GetNextLexeme(currentString), LEXEME_TYPE_STRING);
-
- contentString.Set(currentString);
- currentString.Normalize();
-
- Exit:
- return fIsValid;
- }
-
- BOOL TextualIdentityParser::PopulateAssemblyIdentity(SString &attributeString,
- SString &valueString)
- {
- BOOL fIsValid = TRUE;
-
- if (EqualsCaseInsensitive(attributeString, W("culture")))
- {
- GO_IF_SEEN(AssemblyIdentity::IDENTITY_FLAG_CULTURE);
- GO_IF_WILDCARD(valueString);
-
- if (!EqualsCaseInsensitive(valueString, W("neutral")))
- {
- // culture/language is preserved as is
- m_pAssemblyIdentity->m_cultureOrLanguage.Set(valueString);
- m_pAssemblyIdentity->m_cultureOrLanguage.Normalize();
- }
-
- m_pAssemblyIdentity->SetHave(AssemblyIdentity::IDENTITY_FLAG_CULTURE);
- }
- else if (EqualsCaseInsensitive(attributeString, W("version")))
- {
- AssemblyVersion *pAssemblyVersion = &(m_pAssemblyIdentity->m_version);
-
- GO_IF_SEEN(AssemblyIdentity::IDENTITY_FLAG_VERSION);
- GO_IF_WILDCARD(valueString);
-
- if (ParseVersion(valueString, pAssemblyVersion))
- {
- m_pAssemblyIdentity->SetHave(AssemblyIdentity::IDENTITY_FLAG_VERSION);
- }
- else
- {
- fIsValid = FALSE;
- }
- }
- else if (EqualsCaseInsensitive(attributeString, W("publickeytoken")))
- {
- GO_IF_SEEN(AssemblyIdentity::IDENTITY_FLAG_PUBLIC_KEY);
- GO_IF_SEEN(AssemblyIdentity::IDENTITY_FLAG_PUBLIC_KEY_TOKEN);
- GO_IF_WILDCARD(valueString);
-
- if (!EqualsCaseInsensitive(valueString, W("null")))
- {
- GO_IF_VALIDATE_FAILED(ValidatePublicKeyToken,
- AssemblyIdentity::IDENTITY_FLAG_PUBLIC_KEY_TOKEN);
- HexToBlob(valueString,
- FALSE /* fValidateHex */,
- TRUE /* fIsToken */,
- m_pAssemblyIdentity->m_publicKeyOrTokenBLOB);
- }
- else
- {
- m_pAssemblyIdentity->SetHave(AssemblyIdentity::IDENTITY_FLAG_PUBLIC_KEY_TOKEN_NULL);
- }
- }
- else if (EqualsCaseInsensitive(attributeString, W("publickey")))
- {
- GO_IF_SEEN(AssemblyIdentity::IDENTITY_FLAG_PUBLIC_KEY_TOKEN);
- GO_IF_SEEN(AssemblyIdentity::IDENTITY_FLAG_PUBLIC_KEY);
-
- if (!EqualsCaseInsensitive(valueString, W("null")))
- {
- GO_IF_VALIDATE_FAILED(ValidatePublicKey, AssemblyIdentity::IDENTITY_FLAG_PUBLIC_KEY);
- HexToBlob(valueString,
- FALSE /* fValidateHex */,
- FALSE /* fIsToken */,
- m_pAssemblyIdentity->m_publicKeyOrTokenBLOB);
- }
- }
- else if (EqualsCaseInsensitive(attributeString, W("processorarchitecture")))
- {
- PEKIND kProcessorArchitecture = peNone;
-
- GO_IF_SEEN(AssemblyIdentity::IDENTITY_FLAG_PROCESSOR_ARCHITECTURE);
- GO_IF_WILDCARD(valueString);
-
- if (ValidateAndConvertProcessorArchitecture(valueString, &kProcessorArchitecture))
- {
- m_pAssemblyIdentity->m_kProcessorArchitecture = kProcessorArchitecture;
- m_pAssemblyIdentity->SetHave(AssemblyIdentity::IDENTITY_FLAG_PROCESSOR_ARCHITECTURE);
- }
- else
- {
- fIsValid = FALSE;
- }
- }
- else if (EqualsCaseInsensitive(attributeString, W("retargetable")))
- {
- GO_IF_SEEN(AssemblyIdentity::IDENTITY_FLAG_RETARGETABLE);
-
- if (EqualsCaseInsensitive(valueString, W("yes")))
- {
- m_pAssemblyIdentity->SetHave(AssemblyIdentity::IDENTITY_FLAG_RETARGETABLE);
- }
- else if (!EqualsCaseInsensitive(valueString, W("no")))
- {
- fIsValid = FALSE;
- }
- }
- else if (EqualsCaseInsensitive(attributeString, W("contenttype")))
- {
- GO_IF_SEEN(AssemblyIdentity::IDENTITY_FLAG_CONTENT_TYPE);
- GO_IF_WILDCARD(valueString);
-
- if (EqualsCaseInsensitive(valueString, W("windowsruntime")))
- {
- m_pAssemblyIdentity->m_kContentType = AssemblyContentType_WindowsRuntime;
- m_pAssemblyIdentity->SetHave(AssemblyIdentity::IDENTITY_FLAG_CONTENT_TYPE);
- }
- else
- {
- fIsValid = FALSE;
- }
- }
-
- Exit:
- return fIsValid;
- }
-
/* static */
void TextualIdentityParser::EscapeString(SString &input,
SString &result)
<ItemGroup>
<Compile Include="System\Reflection\RuntimeAssembly.cs" />
<Compile Include="System\Reflection\RuntimeAssemblyName.cs" />
- <Compile Include="System\Reflection\AssemblyNameHelpers.cs" />
<Compile Include="System\Reflection\AssemblyRuntimeNameHelpers.cs" />
<Compile Include="System\Reflection\Attribute.CoreRT.cs" />
<Compile Include="System\Reflection\Assembly.CoreRT.cs" />
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System;
-using System.Globalization;
-using System.IO;
-using System.Text;
-using System.Collections.Generic;
-
-namespace System.Reflection
-{
- internal static partial class AssemblyNameHelpers
- {
- //
- // These helpers convert between the combined flags+contentType+processorArchitecture value and the separated parts.
- //
- // Since these are only for trusted callers, they do NOT check for out of bound bits.
- //
-
- internal static AssemblyContentType ExtractAssemblyContentType(this AssemblyNameFlags flags)
- {
- return (AssemblyContentType)((((int)flags) >> 9) & 0x7);
- }
-
- internal static AssemblyNameFlags ExtractAssemblyNameFlags(this AssemblyNameFlags combinedFlags)
- {
- return combinedFlags & unchecked((AssemblyNameFlags)0xFFFFF10F);
- }
- }
-}
// Our "Flags" contain both the classic flags and the ProcessorArchitecture + ContentType bits. The public AssemblyName has separate properties for
// these. The setters for these properties quietly mask out any bits intended for the other one, so we needn't do that ourselves..
- blank.Flags = this.Flags.ExtractAssemblyNameFlags();
- blank.ContentType = this.Flags.ExtractAssemblyContentType();
+ blank.Flags = ExtractAssemblyNameFlags(this.Flags);
+ blank.ContentType = ExtractAssemblyContentType(this.Flags);
#pragma warning disable SYSLIB0037 // AssemblyName.ProcessorArchitecture is obsolete
blank.ProcessorArchitecture = ExtractProcessorArchitecture(this.Flags);
#pragma warning restore SYSLIB0037
get
{
byte[]? pkt = (0 != (Flags & AssemblyNameFlags.PublicKey)) ? AssemblyNameHelpers.ComputePublicKeyToken(PublicKeyOrToken) : PublicKeyOrToken;
- return AssemblyNameFormatter.ComputeDisplayName(Name, Version, CultureName, pkt, Flags.ExtractAssemblyNameFlags(), Flags.ExtractAssemblyContentType());
+ return AssemblyNameFormatter.ComputeDisplayName(Name, Version, CultureName, pkt, ExtractAssemblyNameFlags(Flags), ExtractAssemblyContentType(Flags));
}
}
- internal static ProcessorArchitecture ExtractProcessorArchitecture(AssemblyNameFlags flags)
- {
- return (ProcessorArchitecture)((((int)flags) >> 4) & 0x7);
- }
+ private static AssemblyNameFlags ExtractAssemblyNameFlags(AssemblyNameFlags combinedFlags)
+ => combinedFlags & unchecked((AssemblyNameFlags)0xFFFFF10F);
+
+ private static AssemblyContentType ExtractAssemblyContentType(AssemblyNameFlags flags)
+ => (AssemblyContentType)((((int)flags) >> 9) & 0x7);
+
+ private static ProcessorArchitecture ExtractProcessorArchitecture(AssemblyNameFlags flags)
+ => (ProcessorArchitecture)((((int)flags) >> 4) & 0x7);
}
}
// Create an AssemblyNameObject from the string.
FriendAssemblyNameHolder pFriendAssemblyName;
- StackScratchBuffer buffer;
pFriendAssemblyName = new FriendAssemblyName_t;
- hr = pFriendAssemblyName->Init(displayName.GetUTF8(buffer));
+ hr = pFriendAssemblyName->InitNoThrow(displayName);
if (SUCCEEDED(hr))
{
extern "C" BOOL QCALLTYPE AssemblyNative_IsApplyUpdateSupported();
-#endif
+extern "C" void QCALLTYPE AssemblyName_InitializeAssemblySpec(NativeAssemblyNameParts* pAssemblyNameParts, BaseAssemblySpec* pAssemblySpec);
+#endif
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;
-}
HRESULT Init(mdToken tkAssemblyRef, IMDInternalImport *pImport);
HRESULT Init(mdAssembly tkAssemblyRef, IMetaDataAssemblyImport* pImport);
- HRESULT Init(LPCSTR pAssemblyDisplayName);
+
+ void Init(SString& assemblyDisplayName);
+ HRESULT InitNoThrow(SString& assemblyDisplayName);
// Note that this method does not clone the fields!
VOID CopyFrom(const BaseAssemblySpec *pSpec);
return m_pBinder;
}
- HRESULT ParseName();
DWORD Hash();
LPCSTR GetName() const;
inline void GetName(SString & ssName) const { WRAPPER_NO_CONTRACT; ssName.SetUTF8(GetName()); }
void SetName(LPCSTR szName);
- void SetName(SString const & ssName);
VOID SetCulture(LPCSTR szCulture);
m_context = *pContext;
}
-inline HRESULT BaseAssemblySpec::Init(LPCSTR pAssemblyDisplayName)
-{
- WRAPPER_NO_CONTRACT;
- m_pAssemblyName = pAssemblyDisplayName;
- // We eagerly parse the name to allow FusionBind::Hash to avoid throwing.
- return ParseName();
-}
-
inline VOID BaseAssemblySpec::CloneFields()
{
CONTRACTL
#include "strongnameinternal.h"
#include "strongnameholders.h"
-#include "../binder/inc/textualidentityparser.hpp"
#include "../binder/inc/assemblyidentity.hpp"
#include "../binder/inc/assembly.hpp"
#include "../binder/inc/assemblyname.hpp"
return hr;
}
-HRESULT BaseAssemblySpec::ParseName()
+void BaseAssemblySpec::Init(SString& assemblyDisplayName)
{
CONTRACTL
{
INSTANCE_CHECK;
GC_TRIGGERS;
- NOTHROW;
- INJECT_FAULT(return E_OUTOFMEMORY;);
+ THROWS;
}
CONTRACTL_END;
- if (!m_pAssemblyName)
- return S_OK;
+ PCWSTR pAssemblyDisplayName = assemblyDisplayName.GetUnicode();
- HRESULT hr = S_OK;
+ GCX_COOP();
- EX_TRY
- {
- BINDER_SPACE::AssemblyIdentityUTF8* pAssemblyIdentity;
- AppDomain *pDomain = ::GetAppDomain();
- _ASSERTE(pDomain);
+ OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOADED);
- BINDER_SPACE::ApplicationContext *pAppContext = NULL;
- DefaultAssemblyBinder *pBinder = pDomain->GetDefaultBinder();
+ PREPARE_NONVIRTUAL_CALLSITE(METHOD__ASSEMBLY_NAME__PARSE_AS_ASSEMBLYSPEC);
+ DECLARE_ARGHOLDER_ARRAY(args, 2);
+ args[ARGNUM_0] = PTR_TO_ARGHOLDER(pAssemblyDisplayName);
+ args[ARGNUM_1] = PTR_TO_ARGHOLDER(this);
+ CALL_MANAGED_METHOD_NORET(args);
+}
- hr = pBinder->GetAppContext()->GetAssemblyIdentity(m_pAssemblyName, &pAssemblyIdentity);
+extern "C" void QCALLTYPE AssemblyName_InitializeAssemblySpec(NativeAssemblyNameParts* pAssemblyNameParts, BaseAssemblySpec* pAssemblySpec)
+{
+ QCALL_CONTRACT;
- if (FAILED(hr))
- {
- m_ownedFlags |= BAD_NAME_OWNED;
- IfFailThrow(hr);
- }
+ BEGIN_QCALL;
- // Name - does not copy the data
- SetName(pAssemblyIdentity->GetSimpleNameUTF8());
+ StackSString ssName;
+ SString(SString::Literal, pAssemblyNameParts->_pName).ConvertToUTF8(ssName);
- // Culture - does not copy the data
- if (pAssemblyIdentity->Have(BINDER_SPACE::AssemblyIdentity::IDENTITY_FLAG_CULTURE))
- {
- if (!pAssemblyIdentity->m_cultureOrLanguage.IsEmpty())
- {
- SetCulture(pAssemblyIdentity->GetCultureOrLanguageUTF8());
- }
- else
- {
- SetCulture("");
- }
- }
+ AssemblyMetaDataInternal asmInfo;
+
+ asmInfo.usMajorVersion = pAssemblyNameParts->_major;
+ asmInfo.usMinorVersion = pAssemblyNameParts->_minor;
+ asmInfo.usBuildNumber = pAssemblyNameParts->_build;
+ asmInfo.usRevisionNumber = pAssemblyNameParts->_revision;
- InitializeWithAssemblyIdentity(pAssemblyIdentity);
+ SmallStackSString ssLocale;
+ if (pAssemblyNameParts->_pCultureName != NULL)
+ SString(SString::Literal, pAssemblyNameParts->_pCultureName).ConvertToUTF8(ssLocale);
+ asmInfo.szLocale = (pAssemblyNameParts->_pCultureName != NULL) ? ssLocale.GetUTF8NoConvert() : NULL;
- // Copy and own any fields we do not already own
- CloneFields();
+ // Initialize spec
+ pAssemblySpec->Init(ssName.GetUTF8NoConvert(), &asmInfo,
+ pAssemblyNameParts->_pPublicKeyOrToken, pAssemblyNameParts->_cbPublicKeyOrToken, pAssemblyNameParts->_flags);
+
+ // Copy and own any fields we do not own
+ pAssemblySpec->CloneFields();
+
+ END_QCALL;
+}
+
+HRESULT BaseAssemblySpec::InitNoThrow(SString& assemblyDisplayName)
+{
+ CONTRACTL
+ {
+ INSTANCE_CHECK;
+ GC_TRIGGERS;
+ NOTHROW;
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK;
+
+ EX_TRY
+ {
+ Init(assemblyDisplayName);
}
EX_CATCH_HRESULT(hr);
}
IfFailThrow(BINDER_SPACE::TextualIdentityParser::ToString(&assemblyIdentity,
- assemblyIdentity.m_dwIdentityFlags,
- result));
+ assemblyIdentity.m_dwIdentityFlags,
+ result));
}
void BaseAssemblySpec::PopulateAssemblyNameData(AssemblyNameData &data) const
DEFINE_CLASS(ASSEMBLY_NAME, Reflection, AssemblyName)
DEFINE_METHOD(ASSEMBLY_NAME, CTOR, .ctor, IM_PtrNativeAssemblyNameParts)
+DEFINE_METHOD(ASSEMBLY_NAME, PARSE_AS_ASSEMBLYSPEC, ParseAsAssemblySpec, SM_PtrCharPtrVoid)
DEFINE_CLASS(NATIVE_ASSEMBLY_NAME_PARTS, Reflection, NativeAssemblyNameParts)
// ASSEMBLYBASE is System.ReflectionAssembly while ASSEMBLY is System.Reflection.RuntimeAssembly
BEGIN_EXTERNAL_ENTRYPOINT(&hr);
GCX_COOP_THREAD_EXISTS(GET_THREAD());
- MAKE_UTF8PTR_FROMWIDE(szAssemblyName, wszAssemblyName);
MAKE_UTF8PTR_FROMWIDE(szClassName, wszClassName);
MAKE_UTF8PTR_FROMWIDE(szMethodName, wszMethodName);
GCX_PREEMP();
AssemblySpec spec;
- spec.Init(szAssemblyName);
+ SString ssAssemblyName(wszAssemblyName);
+ spec.Init(ssAssemblyName);
Assembly* pAsm=spec.LoadAssembly(FILE_ACTIVE);
TypeHandle th=pAsm->GetLoader()->LoadTypeByNameThrowing(pAsm,NULL,szClassName);
DEFINE_METASIG_T(IM(RetAssemblyBase, _, C(ASSEMBLYBASE)))
DEFINE_METASIG_T(IM(RetModule, _, C(MODULE)))
DEFINE_METASIG_T(IM(PtrNativeAssemblyNameParts, P(g(NATIVE_ASSEMBLY_NAME_PARTS)), v))
+DEFINE_METASIG(SM(PtrCharPtrVoid, P(u) P(v), v))
DEFINE_METASIG(IM(RetObj, _, j))
DEFINE_METASIG(SM(RetObj, _, j))
DEFINE_METASIG_T(IM(RetIEnumerator, _, C(IENUMERATOR)))
{
STANDARD_VM_CONTRACT;
- // Get the assembly name.
- StackScratchBuffer scratch;
- const ANSI* pAnsiAssemblyName = assemblyName.GetANSI(scratch);
-
AssemblySpec spec;
// Initialize the assembly spec.
- HRESULT hr = spec.Init(pAnsiAssemblyName);
+ HRESULT hr = spec.InitNoThrow(assemblyName);
if (FAILED(hr))
{
return NULL;
while (COMCharacter::nativeIsWhiteSpace(*(++szComma)));
AssemblySpec spec;
- if (SUCCEEDED(spec.Init(szComma)))
+ SString ssAssemblyDisplayName(SString::Utf8, szComma);
+ if (SUCCEEDED(spec.InitNoThrow(ssAssemblyDisplayName)))
{
// Need to perform case insensitive hashing.
SString moduleName(SString::Utf8, szLibName);
DllImportEntry(TypeName_GetTypeArguments)
DllImportEntry(TypeName_GetModifiers)
DllImportEntry(TypeName_GetAssemblyName)
+ DllImportEntry(AssemblyName_InitializeAssemblySpec)
DllImportEntry(AssemblyNative_GetFullName)
DllImportEntry(AssemblyNative_GetLocation)
DllImportEntry(AssemblyNative_GetResource)
{
CONTRACTL
{
- MODE_ANY;
+ MODE_COOPERATIVE;
THROWS;
GC_TRIGGERS;
INJECT_FAULT(COMPlusThrowOM(););
}
CONTRACTL_END;
+
AssemblySpec spec;
DomainAssembly *pDomainAssembly = NULL;
- StackScratchBuffer buffer;
- LPCUTF8 szAssemblySpec = psszAssemblySpec ? psszAssemblySpec->GetUTF8(buffer) : NULL;
- IfFailThrow(spec.Init(szAssemblySpec));
+ StackSString ssAssemblyName(*psszAssemblySpec);
+ spec.Init(ssAssemblyName);
if (pRequestingAssembly)
{
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.IO;
using System.Runtime.CompilerServices;
using System.Text;
//
internal ref struct AssemblyNameParser
{
- public struct AssemblyNameParts
+ public readonly struct AssemblyNameParts
{
public AssemblyNameParts(string name, Version? version, string? cultureName, AssemblyNameFlags flags, byte[]? publicKeyOrToken)
{
_publicKeyOrToken = publicKeyOrToken;
}
- public string _name;
- public Version? _version;
- public string? _cultureName;
- public AssemblyNameFlags _flags;
- public byte[]? _publicKeyOrToken;
+ public readonly string _name;
+ public readonly Version? _version;
+ public readonly string? _cultureName;
+ public readonly AssemblyNameFlags _flags;
+ public readonly byte[]? _publicKeyOrToken;
}
// Token categories for the lexer.
}
private static readonly char[] s_illegalCharactersInSimpleName = { '/', '\\', ':' };
- private string _input;
+ private ReadOnlySpan<char> _input;
private int _index;
- private AssemblyNameParser(string input)
+ private AssemblyNameParser(ReadOnlySpan<char> input)
{
- Debug.Assert(input != null);
if (input.Length == 0)
throw new ArgumentException(SR.Format_StringZeroLength);
_index = 0;
}
- public static AssemblyNameParts Parse(string s)
+ public static AssemblyNameParts Parse(string name)
{
- return new AssemblyNameParser(s).Parse();
+ return new AssemblyNameParser(name).Parse();
+ }
+
+ public static AssemblyNameParts Parse(ReadOnlySpan<char> name)
+ {
+ return new AssemblyNameParser(name).Parse();
}
private void RecordNewSeenOrThrow(ref AttributeKind seenAttributes, AttributeKind newAttribute)
{
if ((seenAttributes & newAttribute) != 0)
{
- ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input);
- }
- else
- {
- seenAttributes |= newAttribute;
+ ThrowInvalidAssemblyName();
}
+ seenAttributes |= newAttribute;
}
private AssemblyNameParts Parse()
{
// Name must come first.
- string name;
- Token token = GetNextToken(out name);
+ Token token = GetNextToken(out string name);
if (token != Token.String)
- ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input);
+ ThrowInvalidAssemblyName();
if (name == string.Empty || name.IndexOfAny(s_illegalCharactersInSimpleName) != -1)
- ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input);
+ ThrowInvalidAssemblyName();
Version? version = null;
string? cultureName = null;
while (token != Token.End)
{
if (token != Token.Comma)
- ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input);
- string attributeName;
+ ThrowInvalidAssemblyName();
- token = GetNextToken(out attributeName);
+ token = GetNextToken(out string attributeName);
if (token != Token.String)
- ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input);
- token = GetNextToken();
+ ThrowInvalidAssemblyName();
+ token = GetNextToken();
if (token != Token.Equals)
- ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input);
- string attributeValue;
- token = GetNextToken(out attributeValue);
+ ThrowInvalidAssemblyName();
+
+ token = GetNextToken(out string attributeValue);
if (token != Token.String)
- ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input);
+ ThrowInvalidAssemblyName();
if (attributeName == string.Empty)
- ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input);
+ ThrowInvalidAssemblyName();
if (attributeName.Equals("Version", StringComparison.OrdinalIgnoreCase))
{
{
RecordNewSeenOrThrow(ref alreadySeen, AttributeKind.Retargetable);
if (attributeValue.Equals("Yes", StringComparison.OrdinalIgnoreCase))
+ {
flags |= AssemblyNameFlags.Retargetable;
+ }
else if (attributeValue.Equals("No", StringComparison.OrdinalIgnoreCase))
{
// nothing to do
}
else
- ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input);
+ {
+ ThrowInvalidAssemblyName();
+ }
}
if (attributeName.Equals("ContentType", StringComparison.OrdinalIgnoreCase))
{
RecordNewSeenOrThrow(ref alreadySeen, AttributeKind.ContentType);
if (attributeValue.Equals("WindowsRuntime", StringComparison.OrdinalIgnoreCase))
+ {
flags |= (AssemblyNameFlags)(((int)AssemblyContentType.WindowsRuntime) << 9);
+ }
else
- ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input);
+ {
+ ThrowInvalidAssemblyName();
+ }
}
// Desktop compat: If we got here, the attribute name is unknown to us. Ignore it.
{
string[] parts = attributeValue.Split('.');
if (parts.Length > 4)
- ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input);
- ushort[] versionNumbers = new ushort[4];
+ ThrowInvalidAssemblyName();
+ Span<ushort> versionNumbers = stackalloc ushort[4];
for (int i = 0; i < versionNumbers.Length; i++)
{
if (i >= parts.Length)
for (int j = 0; j < parts[i].Length; j++)
{
if (!char.IsDigit(parts[i][j]))
- ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input);
+ ThrowInvalidAssemblyName();
}
if (!(ushort.TryParse(parts[i], out versionNumbers[i])))
{
- ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input);
+ ThrowInvalidAssemblyName();
}
}
}
if (versionNumbers[0] == ushort.MaxValue || versionNumbers[1] == ushort.MaxValue)
- ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input);
+ ThrowInvalidAssemblyName();
if (versionNumbers[2] == ushort.MaxValue)
return new Version(versionNumbers[0], versionNumbers[1]);
if (versionNumbers[3] == ushort.MaxValue)
return Array.Empty<byte>();
if (isToken && attributeValue.Length != 8 * 2)
- ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input);
+ ThrowInvalidAssemblyName();
byte[] pkt = new byte[attributeValue.Length / 2];
int srcIndex = 0;
return ProcessorArchitecture.Amd64;
if (attributeValue.Equals("arm", StringComparison.OrdinalIgnoreCase))
return ProcessorArchitecture.Arm;
- ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input);
+ ThrowInvalidAssemblyName();
return default; // unreachable
}
return (byte)(c - 'a' + 10);
if (c >= 'A' && c <= 'F')
return (byte)(c - 'A' + 10);
- ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input);
+ ThrowInvalidAssemblyName();
return default; // unreachable
}
ch = _input[_index++];
if (ch == '\0')
{
- ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input);
+ ThrowInvalidAssemblyName();
}
}
else
if (quoteChar != 0)
{
// EOS and unclosed quotes is an error
- ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input);
- }
- else
- {
- // Reached end of input and therefore of string
- break;
+ ThrowInvalidAssemblyName();
}
+ // Reached end of input and therefore of string
+ break;
}
if (quoteChar != 0 && c == quoteChar)
}
if (quoteChar == 0 && (c == '\'' || c == '\"'))
- ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input);
+ ThrowInvalidAssemblyName();
if (c == '\\')
{
sb.Append('\n');
break;
default:
- ThrowHelper.ThrowFileLoadException_InvalidAssemblyName(_input);
- return default; //unreachable
+ ThrowInvalidAssemblyName();
+ break; //unreachable
}
}
else
tokenString = sb.ToString();
return Token.String;
}
+
+ [DoesNotReturn]
+ private void ThrowInvalidAssemblyName()
+ => throw new FileLoadException(SR.InvalidAssemblyName, _input.ToString());
}
}
}
[DoesNotReturn]
- internal static void ThrowFileLoadException_InvalidAssemblyName(string name)
- {
- throw new FileLoadException(SR.InvalidAssemblyName, name);
- }
-
- [DoesNotReturn]
internal static void ThrowArgumentOutOfRangeException_PrecisionTooLarge()
{
throw new ArgumentOutOfRangeException("precision", SR.Format(SR.Argument_PrecisionTooLarge, StandardFormat.MaxPrecision));