diff options
author | Jan Kotas <jkotas@microsoft.com> | 2017-10-27 16:08:24 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-10-27 16:08:24 -0700 |
commit | 12334b8ad82ce97644b7a28398b5deb15875679c (patch) | |
tree | 61a77174aa83fdae6ec310c13a77da7fb316504a /src/md | |
parent | 0794d67803f0fa7b5159a1f296d3012e4b7ee913 (diff) | |
download | coreclr-12334b8ad82ce97644b7a28398b5deb15875679c.tar.gz coreclr-12334b8ad82ce97644b7a28398b5deb15875679c.tar.bz2 coreclr-12334b8ad82ce97644b7a28398b5deb15875679c.zip |
Delete dead code (#14703)
Diffstat (limited to 'src/md')
-rw-r--r-- | src/md/compiler/mdvalidator.cpp | 7589 | ||||
-rw-r--r-- | src/md/compiler/regmeta.cpp | 4 | ||||
-rw-r--r-- | src/md/compiler/regmeta.h | 40 |
3 files changed, 0 insertions, 7633 deletions
diff --git a/src/md/compiler/mdvalidator.cpp b/src/md/compiler/mdvalidator.cpp deleted file mode 100644 index ce6c14e468..0000000000 --- a/src/md/compiler/mdvalidator.cpp +++ /dev/null @@ -1,7589 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. -//***************************************************************************** -// MDValidator.cpp -// - -// -// Implementation for the MetaData validator. -// Only supported for full mscorwks version. -// -//***************************************************************************** -#include "stdafx.h" - -#ifdef FEATURE_METADATA_VALIDATOR - -#include "regmeta.h" -#include "importhelper.h" -#include "pedecoder.h" -#include "stgio.h" -#include "corhost.h" -#include "sstring.h" -#include "nsutilpriv.h" -#include "holder.h" -#include "vererror.h" - -#include "mdsighelper.h" - -#ifdef DACCESS_COMPILE -#error Dac should be using standalone version of metadata, not Wks version. -#endif - -//----------------------------------------------------------------------------- -// Application specific debug macro. -#define IfBreakGo(EXPR) \ -do {if ((EXPR) != S_OK) IfFailGo(VLDTR_E_INTERRUPTED); } while (0) - -//----------------------------------------------------------------------------- - -//#define CACHE_IMPLMAP_VALIDATION_RESULT -#ifdef CACHE_IMPLMAP_VALIDATION_RESULT -// To avoid multiple validation of the same thing: -struct ValidationResult -{ - mdToken tok; - HRESULT hr; -}; -ValidationResult* g_rValidated=NULL; // allocated in ValidateMetaData -unsigned g_nValidated=0; -#endif - -//----------------------------------------------------------------------------- - -#define BASE_OBJECT_CLASSNAME "Object" -#define BASE_NAMESPACE "System" -#define BASE_VTYPE_CLASSNAME "ValueType" -#define BASE_ENUM_CLASSNAME "Enum" -#define BASE_VALUE_FIELDNAME "value__" -#define BASE_CTOR_NAME ".ctor" -#define BASE_CCTOR_NAME ".cctor" -#define BASE_MCDELEGATE_CLASSNAME "MulticastDelegate" - -#define SYSTEM_OBJECT_TOSTRING_METHODNAME "ToString" -#define SYSTEM_OBJECT_GETHASHCODE_METHODNAME "GetHashCode" -#define SYSTEM_OBJECT_EQUALS_METHODNAME "Equals" - -// string ToString() -static const BYTE g_sigSystemObject_ToString[] = -{ - IMAGE_CEE_CS_CALLCONV_HASTHIS, // 0x20 - 0, // 0x00 ... Param Count - ELEMENT_TYPE_STRING // 0x0e ... Return Type - string -}; - -// int GetHashCode() -static const BYTE g_sigSystemObject_GetHashCode[] = -{ - IMAGE_CEE_CS_CALLCONV_HASTHIS, // 0x20 - 0, // 0x00 ... Param Count - ELEMENT_TYPE_I4 // 0x08 ... Return Type - I4 -}; - -// bool Equals(object) -static const BYTE g_sigSystemObject_Equals[] = -{ - IMAGE_CEE_CS_CALLCONV_HASTHIS, // 0x20 - 1, // 0x01 ... Param Count - ELEMENT_TYPE_BOOLEAN, // 0x02 ... Return Type - bool - ELEMENT_TYPE_OBJECT // 0x1c ... Param #1 - object -}; - -// as defined in src\vm\vars.hpp -#define MAX_CLASSNAME_LENGTH 1024 -//----------------------------------------------------------------------------- -// Class names used in long form signatures (namespace is always "System") -unsigned g_NumSigLongForms = 19; -static const LPCSTR g_SigLongFormName[] = { - "String", - "______", // "Object", <REVISIT_TODO>// uncomment when EE handles ELEMENT_TYPE_OBJECT</REVISIT_TODO> - "Boolean", - "Char", - "Byte", - "SByte", - "UInt16", - "Int16", - "UInt32", - "Int32", - "UInt64", - "Int64", - "Single", - "Double", - "SysInt", // Review this. - "SysUInt", // Review this. - "SingleResult", - "Void", - "IntPtr" -}; - -// <REVISIT_TODO>: Why are these global variables?</REVISIT_TODO> -mdToken g_tkEntryPoint; -bool g_fValidatingMscorlib; -bool g_fIsDLL; - -//----------------------------------------------------------------------------- - -static HRESULT _FindClassLayout( - CMiniMdRW *pMiniMd, // [IN] the minimd to lookup - mdTypeDef tkParent, // [IN] the parent that ClassLayout is associated with - RID *clRid, // [OUT] rid for the ClassLayout. - RID rid); // [IN] rid to be ignored. - -static HRESULT _FindFieldLayout( - CMiniMdRW *pMiniMd, // [IN] the minimd to lookup - mdFieldDef tkParent, // [IN] the parent that FieldLayout is associated with - RID *flRid, // [OUT] rid for the FieldLayout record. - RID rid); // [IN] rid to be ignored. - -static BOOL _IsValidLocale(LPCUTF8 szLocale, - BOOL fIsV2Assembly); - - -#define REPORT_ERROR0(_VECode) \ - IfFailGo(_ValidateErrorHelper(_VECode, veCtxt)) -#define REPORT_ERROR1(_VECode, _Arg0) \ - IfFailGo(_ValidateErrorHelper(_VECode, veCtxt, _Arg0)) -#define REPORT_ERROR2(_VECode, _Arg0, _Arg1) \ - IfFailGo(_ValidateErrorHelper(_VECode, veCtxt, _Arg0, _Arg1)) -#define REPORT_ERROR3(_VECode, _Arg0, _Arg1, _Arg2) \ - IfFailGo(_ValidateErrorHelper(_VECode, veCtxt, _Arg0, _Arg1, _Arg2)) - -//***************************************************************************** -// Returns true if ixPtrTbl and ixParTbl are a valid parent-child combination -// in the pointer table scheme. -//***************************************************************************** -static inline bool IsTblPtr(ULONG ixPtrTbl, ULONG ixParTbl) -{ - if ((ixPtrTbl == TBL_Field && ixParTbl == TBL_TypeDef) || - (ixPtrTbl == TBL_Method && ixParTbl == TBL_TypeDef) || - (ixPtrTbl == TBL_Param && ixParTbl == TBL_Method) || - (ixPtrTbl == TBL_Property && ixParTbl == TBL_PropertyMap) || - (ixPtrTbl == TBL_Event && ixParTbl == TBL_EventMap)) - { - return true; - } - return false; -} // IsTblPtr() - -//***************************************************************************** -// This inline function is used to set the return hr value for the Validate -// functions to one of VLDTR_S_WRN, VLDTR_S_ERR or VLDTR_S_WRNERR based on -// the current hr value and the new success code. -// The general algorithm for error codes from the validation functions is: -// if (no warnings or errors found) -// return S_OK or S_FALSE -// else if (warnings found) -// return VLDTR_S_WRN -// else if (errors found) -// return VLDTR_S_ERR -// else if (warnings and errors found) -// return VLDTR_S_WRNERR -//***************************************************************************** -static inline void SetVldtrCode(HRESULT *phr, HRESULT successcode) -{ - _ASSERTE(successcode == S_OK || successcode == S_FALSE ||successcode == VLDTR_S_WRN || - successcode == VLDTR_S_ERR || successcode == VLDTR_S_WRNERR); - _ASSERTE(*phr == S_OK || *phr == VLDTR_S_WRN || *phr == VLDTR_S_ERR || - *phr == VLDTR_S_WRNERR); - if (successcode == S_OK || successcode == S_FALSE ||*phr == VLDTR_S_WRNERR) - return; - else if (*phr == S_OK || *phr == S_FALSE) - *phr = successcode; - else if (*phr != successcode) - *phr = VLDTR_S_WRNERR; -} // SetVldtrCode() - -//***************************************************************************** -// Initialize the Validator related structures in RegMeta. -//***************************************************************************** -HRESULT RegMeta::ValidatorInit( // S_OK or error. - DWORD dwModuleType, // [IN] Specifies whether the module is a PE file or an obj. - IUnknown *pUnk) // [IN] Validation error handler. -{ - HRESULT hr = S_OK; // Return value. - - BEGIN_ENTRYPOINT_NOTHROW; - - int i = 0; // Index into the function pointer table. - - // Initialize the array of function pointers to the validation function on - // each table. -#undef MiniMdTable -#define MiniMdTable(x) m_ValidateRecordFunctionTable[i++] = &RegMeta::Validate##x; - MiniMdTables() - - // Verify that the ModuleType passed in is a valid one. - if (dwModuleType < ValidatorModuleTypeMin || - dwModuleType > ValidatorModuleTypeMax) - { - IfFailGo(E_INVALIDARG); - } - - // Verify that the interface passed in supports IID_IVEHandler. - IfFailGo(pUnk->QueryInterface(IID_IVEHandler, (void **)&m_pVEHandler)); - - // Set the ModuleType class member. Do this last, this is used in - // ValidateMetaData to see if the validator is correctly initialized. - m_ModuleType = (CorValidatorModuleType)dwModuleType; -ErrExit: - END_ENTRYPOINT_NOTHROW; - - return hr; -} // HRESULT RegMeta::ValidatorInit() - - -//***************************************************************************** -// Public implementation for code:IMetaDataValidate::ValidateMetaData -// -// Validate the entire MetaData. Here is the basic algorithm. -// for each table -// for each record -// { -// Do generic validation - validate that the offsets into the blob -// pool are good, validate that all the rids are within range, -// validate that token encodings are consistent. -// } -// if (problems found in generic validation) -// return; -// for each table -// for each record -// Do semantic validation. -//****************************************************************************** -HRESULT RegMeta::ValidateMetaData() -{ - HRESULT hr = S_OK; - - BEGIN_ENTRYPOINT_NOTHROW; - - CMiniMdRW * pMiniMd = &(m_pStgdb->m_MiniMd); - HRESULT hrSave = S_OK; // Saved hr from generic validation. - ULONG ulCount; // Count of records in the current table. - ULONG i; // Index to iterate over the tables. - ULONG j; // Index to iterate over the records in a given table. - IHostTaskManager * pHostTaskManager = NULL; - -#ifdef CACHE_IMPLMAP_VALIDATION_RESULT - ULONG rValidatedSize=0; // Size of g_rValidated array -#endif - - // Verify that the validator is initialized correctly - if (m_ModuleType == ValidatorModuleTypeInvalid) - { - _ASSERTE(!"Validator not initialized, initialize with ValidatorInit()."); - IfFailGo(VLDTR_E_NOTINIT); - } - - // First do a validation pass to do some basic structural checks based on - // the Meta-Meta data. This'll validate all the offsets into the pools, - // rid value and coded token ranges. - for (i = 0; i < pMiniMd->GetCountTables(); i++) - { - ulCount = pMiniMd->GetCountRecs(i); - -#ifdef CACHE_IMPLMAP_VALIDATION_RESULT - switch(i) - { - case TBL_ImplMap: - rValidatedSize += ulCount; - default: - ; - } -#endif - for (j = 1; j <= ulCount; j++) - { - IfFailGo(ValidateRecord(i, j)); - SetVldtrCode(&hrSave, hr); - } - } - // Validate that the size of the Ptr tables matches with the corresponding - // real tables. - - // Do not do semantic validation if structural validation failed. - if (hrSave != S_OK) - { - hr = hrSave; - goto ErrExit; - } - - // Verify the entry point (if any) - ::g_tkEntryPoint = 0; - ::g_fIsDLL = false; - if(m_pStgdb && m_pStgdb->m_pImage) - { - NewHolder<PEDecoder> pe; - - EX_TRY - { - // We need to use different PEDecoder constructors based on the type of data we give it. - // We use the one with a 'bool' as the second argument when dealing with a mapped file, - // and we use the one that takes a COUNT_T as the second argument when dealing with a - // flat file. - - if (m_pStgdb->m_pStgIO->GetMemoryMappedType() == MTYPE_IMAGE) - pe = new (nothrow) PEDecoder(m_pStgdb->m_pImage, false); - else - pe = new (nothrow) PEDecoder(m_pStgdb->m_pImage, (COUNT_T)(m_pStgdb->m_dwImageSize)); - - hr = S_OK; - } - EX_CATCH - { - hr = COR_E_BADIMAGEFORMAT; - } - EX_END_CATCH(SwallowAllExceptions) - - if (SUCCEEDED(hr) && pe == NULL) - IfFailGo(E_OUTOFMEMORY); - - if(FAILED(hr) || !pe->CheckFormat()) - { - VEContext veCtxt; // Context structure. - - memset(&veCtxt, 0, sizeof(VEContext)); - veCtxt.Token = 0; - veCtxt.uOffset = 0; - REPORT_ERROR0(COR_E_BADIMAGEFORMAT); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else if(!pe->IsILOnly()) - { - VEContext veCtxt; // Context structure. - memset(&veCtxt, 0, sizeof(VEContext)); - veCtxt.Token = 0; - veCtxt.uOffset = 0; - REPORT_ERROR0(VER_E_BAD_PE); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - if((pe->GetCorHeader()->Flags & COMIMAGE_FLAGS_NATIVE_ENTRYPOINT) == 0) - g_tkEntryPoint = pe->GetEntryPointToken(); - g_fIsDLL = pe->IsDll() ? true : false; - - if(g_tkEntryPoint) - { - RID rid = RidFromToken(g_tkEntryPoint); - RID maxrid = 0; - switch(TypeFromToken(g_tkEntryPoint)) - { - case mdtMethodDef: maxrid = pMiniMd->getCountMethods(); break; - case mdtFile: maxrid = pMiniMd->getCountFiles(); break; - default: break; - } - if((rid == 0)||(rid > maxrid)) - { - VEContext veCtxt; // Context structure. - memset(&veCtxt, 0, sizeof(VEContext)); - veCtxt.Token = g_tkEntryPoint; - veCtxt.uOffset = 0; - REPORT_ERROR0(VLDTR_E_EP_BADTOKEN); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - else if(!g_fIsDLL) // exe must have an entry point - { - VEContext veCtxt; // Context structure. - memset(&veCtxt, 0, sizeof(VEContext)); - veCtxt.Token = g_tkEntryPoint; - veCtxt.uOffset = 0; - REPORT_ERROR0(VLDTR_E_EP_BADTOKEN); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - - g_fValidatingMscorlib = false; - if(pMiniMd->GetCountRecs(TBL_Assembly)) - { - AssemblyRec *pRecord; - IfFailGo(pMiniMd->GetAssemblyRecord(1, &pRecord)); - LPCSTR szName; - IfFailGo(pMiniMd->getNameOfAssembly(pRecord, &szName)); - g_fValidatingMscorlib = (0 == SString::_stricmp(szName,"mscorlib")); - } - // Verify there are no circular class hierarchies. - - // Do per record semantic validation on the MetaData. The function - // pointers to the per record validation are stored in the table by the - // ValidatorInit() function. - -#ifdef CACHE_IMPLMAP_VALIDATION_RESULT - g_rValidated = NULL; - ::g_nValidated = 0; - if (rValidatedSize) - { - g_rValidated = new(nothrow) ValidationResult[rValidatedSize]; - IfNullGo(g_rValidated); - } -#endif - pHostTaskManager = CorHost2::GetHostTaskManager(); - -#ifdef Sleep -#undef Sleep -#endif - //DWORD cBegin=0,cEnd=0; - for (i = 0; i < pMiniMd->GetCountTables(); i++) - { - ulCount = pMiniMd->GetCountRecs(i); - //cBegin = GetTickCount(); - for (j = 1; j <= ulCount; j++) - { - IfFailGo((this->*m_ValidateRecordFunctionTable[i])(j)); - SetVldtrCode(&hrSave, hr); - if(pHostTaskManager) - { - // SwitchToTask forces the current thread to give up quantum, while a host can decide what - // to do with Sleep if the current thread has not run out of quantum yet. - ClrSleepEx(0, FALSE); - } - } - //cEnd = GetTickCount(); - //printf("Table %d, recs: %d, time: %d\n",i,ulCount,(cEnd-cBegin)); - } - hr = hrSave; -ErrExit: - -#ifdef CACHE_IMPLMAP_VALIDATION_RESULT - if(g_rValidated) delete [] g_rValidated; -#endif - END_ENTRYPOINT_NOTHROW; - - return hr; -} // RegMeta::ValidateMetaData() - -//***************************************************************************** -// Validate the Module record. -//***************************************************************************** -HRESULT RegMeta::ValidateModule(RID rid) -{ - CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); // MiniMd for the scope. - ModuleRec *pRecord; // Module record. - VEContext veCtxt; // Context structure. - HRESULT hr = S_OK; // Value returned. - HRESULT hrSave = S_OK; // Save state. - LPCSTR szName; - GUID GuidOfModule; - - BEGIN_ENTRYPOINT_NOTHROW; - - memset(&veCtxt, 0, sizeof(VEContext)); - - // Get the Module record. - veCtxt.Token = TokenFromRid(rid, mdtModule); - veCtxt.uOffset = 0; - IfFailGo(pMiniMd->GetModuleRecord(rid, &pRecord)); - - // There can only be one Module record. - if (rid > 1) - { - REPORT_ERROR0(VLDTR_E_MOD_MULTI); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - // Verify the name - IfFailGo(pMiniMd->getNameOfModule(pRecord, &szName)); - if(szName && *szName) - { - ULONG L = (ULONG)strlen(szName); - if(L >= MAX_CLASSNAME_LENGTH) - { - // Name too long - REPORT_ERROR2(VLDTR_E_TD_NAMETOOLONG, L, (ULONG)(MAX_CLASSNAME_LENGTH-1)); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - if(strchr(szName,':') || strchr(szName,'\\')) - { - REPORT_ERROR0(VLDTR_E_MOD_NAMEFULLQLFD); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - else - { - REPORT_ERROR0(VLDTR_E_MOD_NONAME); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // Verify that the MVID is valid. - IfFailGo(pMiniMd->getMvidOfModule(pRecord, &GuidOfModule)); - if (GuidOfModule == GUID_NULL) - { - REPORT_ERROR0(VLDTR_E_MOD_NULLMVID); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - hr = hrSave; -ErrExit: - ; - END_ENTRYPOINT_NOTHROW; - - return hr; -} // RegMeta::ValidateModule() - -//***************************************************************************** -// Validate the given TypeRef. -//***************************************************************************** -HRESULT RegMeta::ValidateTypeRef(RID rid) -{ - CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); // MiniMd of the scope. - TypeRefRec *pRecord; // TypeRef record. - mdToken tkRes; // Resolution scope. - LPCSTR szNamespace; // TypeRef Namespace. - LPCSTR szName; // TypeRef Name. - mdTypeRef tkTypeRef; // Duplicate TypeRef. - VEContext veCtxt; // Context record. - HRESULT hr = S_OK; // Value returned. - HRESULT hrSave = S_OK; // Save state. - - BEGIN_ENTRYPOINT_NOTHROW; - - memset(&veCtxt, 0, sizeof(VEContext)); - // Get the TypeRef record. - veCtxt.Token = TokenFromRid(rid, mdtTypeRef); - veCtxt.uOffset = 0; - - IfFailGo(pMiniMd->GetTypeRefRecord(rid, &pRecord)); - - // Check name is not NULL. - IfFailGo(pMiniMd->getNamespaceOfTypeRef(pRecord, &szNamespace)); - IfFailGo(pMiniMd->getNameOfTypeRef(pRecord, &szName)); - if (!*szName) - { - REPORT_ERROR0(VLDTR_E_TR_NAMENULL); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else - { - RID ridScope; - // Look for a Duplicate, this function reports only one duplicate. - tkRes = pMiniMd->getResolutionScopeOfTypeRef(pRecord); - hr = ImportHelper::FindTypeRefByName(pMiniMd, tkRes, szNamespace, szName, &tkTypeRef, rid); - if (hr == S_OK) - { - REPORT_ERROR1(VLDTR_E_TR_DUP, tkTypeRef); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else if (hr == CLDB_E_RECORD_NOTFOUND) - hr = S_OK; - else - IfFailGo(hr); - ULONG L = (ULONG)(strlen(szName)+strlen(szNamespace)); - if(L >= MAX_CLASSNAME_LENGTH) - { - REPORT_ERROR2(VLDTR_E_TD_NAMETOOLONG, L, (ULONG)(MAX_CLASSNAME_LENGTH-1)); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - ridScope = RidFromToken(tkRes); - if(ridScope) - { - bool badscope = true; - //check if valid scope - switch(TypeFromToken(tkRes)) - { - case mdtAssemblyRef: - case mdtModuleRef: - case mdtModule: - case mdtTypeRef: - badscope = !IsValidToken(tkRes); - break; - default: - break; - } - if(badscope) - { - REPORT_ERROR1(VLDTR_E_TR_BADSCOPE, tkTypeRef); - SetVldtrCode(&hrSave, VLDTR_S_WRN); - } - } - else - { - // check if there is a ExportedType - //hr = ImportHelper::FindExportedType(pMiniMd, szNamespace, szName, tkImpl, &tkExportedType, rid); - } - // Check if there is TypeDef with the same name - if(!ridScope) - { - if((TypeFromToken(tkRes) != mdtTypeRef) && - (S_OK == ImportHelper::FindTypeDefByName(pMiniMd, szNamespace, szName, mdTokenNil,&tkTypeRef, 0))) - { - REPORT_ERROR1(VLDTR_E_TR_HASTYPEDEF, tkTypeRef); - SetVldtrCode(&hrSave, VLDTR_S_WRN); - } - } - } - hr = hrSave; -ErrExit: - ; - END_ENTRYPOINT_NOTHROW; - - return hr; -} // RegMeta::ValidateTypeRef() - -//***************************************************************************** -// Validate the given TypeDef. -//***************************************************************************** -#ifdef _PREFAST_ -#pragma warning(push) -#pragma warning(disable:21000) // Suppress PREFast warning about overly large function -#endif -HRESULT RegMeta::ValidateTypeDef(RID rid) -{ - CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); // MiniMd of the scope. - TypeDefRec *pRecord; // TypeDef record. - TypeDefRec *pExtendsRec = 0; // TypeDef record for the parent class. - mdTypeDef tkTypeDef; // Duplicate TypeDef token. - DWORD dwFlags; // TypeDef flags. - DWORD dwExtendsFlags; // TypeDef flags of the parent class. - LPCSTR szName; // TypeDef Name. - LPCSTR szNameSpace; // TypeDef NameSpace. - LPCSTR szExtName = NULL; // Parent Name. - LPCSTR szExtNameSpace = NULL; // Parent NameSpace. - CQuickBytes qb; // QuickBytes for flexible allocation. - mdToken tkExtends; // TypeDef of the parent class. - VEContext veCtxt; // Context record. - HRESULT hr = S_OK; // Value returned. - HRESULT hrSave = S_OK; // Save state. - mdToken tkEncloser=mdTokenNil; // Encloser, if any - BOOL bIsEnum,bExtendsEnum,bExtendsVType,bIsVType,bExtendsObject,bIsObject,bExtendsMCDelegate; - BOOL bHasMethods=FALSE, bHasFields=FALSE; - - BEGIN_ENTRYPOINT_NOTHROW; - - // Skip validating m_tdModule class. - if (rid == RidFromToken(m_tdModule)) - goto ErrExit; - - memset(&veCtxt, 0, sizeof(VEContext)); - - // Get the TypeDef record. - veCtxt.Token = TokenFromRid(rid, mdtTypeDef); - veCtxt.uOffset = 0; - - IfFailGo(pMiniMd->GetTypeDefRecord(rid, &pRecord)); - - // Do checks for name validity.. - IfFailGo(pMiniMd->getNameOfTypeDef(pRecord, &szName)); - IfFailGo(pMiniMd->getNamespaceOfTypeDef(pRecord, &szNameSpace)); - if (!*szName) - { - // TypeDef Name is null. - REPORT_ERROR0(VLDTR_E_TD_NAMENULL); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else if (!IsDeletedName(szName)) - { - RID iRecord; - IfFailGo(pMiniMd->FindNestedClassHelper(TokenFromRid(rid, mdtTypeDef), &iRecord)); - - if (InvalidRid(iRecord)) - { - tkEncloser = mdTokenNil; - } - else - { - NestedClassRec *pNestedClassRec; - IfFailGo(pMiniMd->GetNestedClassRecord(iRecord, &pNestedClassRec)); - tkEncloser = pMiniMd->getEnclosingClassOfNestedClass(pNestedClassRec); - } - - // Check for duplicates based on Name/NameSpace. Do not do Dup checks - // on deleted records. - hr = ImportHelper::FindTypeDefByName(pMiniMd, szNameSpace, szName, tkEncloser, - &tkTypeDef, rid); - if (hr == S_OK) - { - REPORT_ERROR1(VLDTR_E_TD_DUPNAME, tkTypeDef); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else if (hr == CLDB_E_RECORD_NOTFOUND) - hr = S_OK; - else - IfFailGo(hr); - ULONG L = (ULONG)(strlen(szName)+strlen(szNameSpace)); - if(L >= MAX_CLASSNAME_LENGTH) - { - REPORT_ERROR2(VLDTR_E_TD_NAMETOOLONG, L, (ULONG)(MAX_CLASSNAME_LENGTH-1)); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - - // Get the flag value for the TypeDef. - dwFlags = pMiniMd->getFlagsOfTypeDef(pRecord); - // Do semantic checks on the flags. - // RTSpecialName bit must be set on Deleted records. - if (IsDeletedName(szName)) - { - if(!IsTdRTSpecialName(dwFlags)) - { - REPORT_ERROR0(VLDTR_E_TD_DLTNORTSPCL); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - hr = hrSave; - goto ErrExit; - } - - // If RTSpecialName bit is set, the record must be a Deleted record. - if (IsTdRTSpecialName(dwFlags)) - { - REPORT_ERROR0(VLDTR_E_TD_RTSPCLNOTDLT); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - if(!IsTdSpecialName(dwFlags)) - { - REPORT_ERROR0(VLDTR_E_TD_RTSPCLNOTSPCL); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - - // Check if flag value is valid - { - DWORD dwInvalidMask, dwExtraBits; - dwInvalidMask = (DWORD)~(tdVisibilityMask | tdLayoutMask | tdClassSemanticsMask | - tdAbstract | tdSealed | tdSpecialName | tdImport | tdSerializable | tdWindowsRuntime | - tdStringFormatMask | tdBeforeFieldInit | tdReservedMask); - // check for extra bits - dwExtraBits = dwFlags & dwInvalidMask; - if (dwExtraBits == 0) - { - // if no extra bits, check layout - dwExtraBits = dwFlags & tdLayoutMask; - if (dwExtraBits != tdLayoutMask) - { - // layout OK, check string format - dwExtraBits = dwFlags & tdStringFormatMask; - if (dwExtraBits != tdStringFormatMask) - dwExtraBits = 0; - } - } - if (dwExtraBits != 0) - { - REPORT_ERROR1(VLDTR_E_TD_EXTRAFLAGS, dwExtraBits); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - - // Generic types may be specified to have only AutoLayout or SequentialLayout (never ExplicitLayout). - if (IsTdExplicitLayout(dwFlags)) - { - HENUMInternal hEnumTyPars; - ULONG ulTypeDefArity; - hr = pMiniMd->FindGenericParamHelper(TokenFromRid(rid, mdtTypeDef), &hEnumTyPars); - if (SUCCEEDED(hr)) - { - IfFailGo(HENUMInternal::GetCount(&hEnumTyPars,&ulTypeDefArity)); - HENUMInternal::ClearEnum(&hEnumTyPars); - if (ulTypeDefArity != 0) - { - REPORT_ERROR0(VLDTR_E_TD_GENERICHASEXPLAYOUT); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - } - - } - - // Get the parent of the TypeDef. - tkExtends = pMiniMd->getExtendsOfTypeDef(pRecord); - - // Check if TypeDef extends itself - if (tkExtends == veCtxt.Token) - { - REPORT_ERROR0(VLDTR_E_TD_EXTENDSITSELF); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // Check if TypeDef extends one of its children - if (RidFromToken(tkExtends)&&(TypeFromToken(tkExtends)==mdtTypeDef)) - { - TypeDefRec *pRec; - IfFailGo(pMiniMd->GetTypeDefRecord(RidFromToken(tkExtends), &pRec)); - mdToken tkExtends2 = pMiniMd->getExtendsOfTypeDef(pRec); - if( tkExtends2 == veCtxt.Token) - { - REPORT_ERROR0(VLDTR_E_TD_EXTENDSCHILD); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - - - - if (IsNilToken(tkEncloser) == IsTdNested(dwFlags)) - { - REPORT_ERROR0(IsNilToken(tkEncloser) ? VLDTR_E_TD_NESTEDNOENCL : VLDTR_E_TD_ENCLNOTNESTED); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - bIsObject = bIsEnum = bIsVType = FALSE; - if(0 == strcmp(szNameSpace,BASE_NAMESPACE)) - { - bIsObject = (0 == strcmp(szName,BASE_OBJECT_CLASSNAME)); - if(!bIsObject) - { - bIsEnum = (0 == strcmp(szName,BASE_ENUM_CLASSNAME)); - if(!bIsEnum) - { - bIsVType = (0 == strcmp(szName,BASE_VTYPE_CLASSNAME)); - } - } - } - - if (IsNilToken(tkExtends)) - { - // If the parent token is nil, the class must be marked Interface, - // unless it's the System.Object class. - if ( !(bIsObject || IsTdInterface(dwFlags))) - { - REPORT_ERROR0(VLDTR_E_TD_NOTIFACEOBJEXTNULL); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - szExtName = ""; - szExtNameSpace = ""; - } - else - { - - // If tkExtends is a TypeSpec, extract the generic type and continue - if (TypeFromToken(tkExtends) == mdtTypeSpec) - { - //@GENERICSVER: TODO first validate the spec - - TypeSpecRec *pRec; - IfFailGo(pMiniMd->GetTypeSpecRecord(RidFromToken(tkExtends), &pRec)); - PCCOR_SIGNATURE pSig; - ULONG cSig; - - IfFailGo(pMiniMd->getSignatureOfTypeSpec(pRec, &pSig, &cSig)); - - switch(CorSigUncompressElementType(pSig)) - { - default: - { - REPORT_ERROR1(VLDTR_E_TD_EXTBADTYPESPEC, tkExtends); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - szExtName = ""; - szExtNameSpace = ""; - break; - } - case ELEMENT_TYPE_GENERICINST: - { - switch(CorSigUncompressElementType(pSig)) - { - default: - { - REPORT_ERROR1(VLDTR_E_TD_EXTBADTYPESPEC, tkExtends); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - szExtName = ""; - szExtNameSpace = ""; - break; - } - case ELEMENT_TYPE_VALUETYPE: - case ELEMENT_TYPE_CLASS: - { - tkExtends = CorSigUncompressToken(pSig); - break; - } - } - } - } - } - - // If tkExtends is a TypeRef try to resolve it to a corresponding - // TypeDef. If it resolves successfully, issue a warning. It means - // that the Ref to Def optimization didn't happen successfully. - if (TypeFromToken(tkExtends) == mdtTypeRef) - { - TypeRefRec *pTypeRefRec; - IfFailGo(pMiniMd->GetTypeRefRecord(RidFromToken(tkExtends), &pTypeRefRec)); - - IfFailGo(pMiniMd->getNameOfTypeRef(pTypeRefRec, &szExtName)); - IfFailGo(pMiniMd->getNamespaceOfTypeRef(pTypeRefRec, &szExtNameSpace)); - - BOOL fLookForDef = TRUE; - mdToken tkResScope = pMiniMd->getResolutionScopeOfTypeRef(pTypeRefRec); - if (TypeFromToken(tkResScope) == mdtAssemblyRef) - { // We will look for the TypeDef of the same name, only if the AssemblyRef has the same name as AssemblyDef - fLookForDef = FALSE; - RID ridResScope = RidFromToken(tkResScope); - if ((ridResScope > 0) && (ridResScope <= pMiniMd->GetCountRecs(TBL_AssemblyRef))) - { - if (pMiniMd->GetCountRecs(TBL_Assembly) > 0) - { - AssemblyRefRec * pAsmRefRec; - IfFailGo(pMiniMd->GetAssemblyRefRecord(ridResScope, &pAsmRefRec)); - AssemblyRec *pAsmRec; - IfFailGo(pMiniMd->GetAssemblyRecord(1, &pAsmRec)); - if ((pAsmRec != NULL) && (pAsmRefRec != NULL)) - { - LPCUTF8 szAsmName; - IfFailGo(pMiniMd->getNameOfAssembly(pAsmRec, &szAsmName)); - LPCUTF8 szAsmRefName; - IfFailGo(pMiniMd->getNameOfAssemblyRef(pAsmRefRec, &szAsmRefName)); - if ((szAsmName != NULL) && (szAsmRefName != NULL)) - fLookForDef = (strcmp(szAsmName,szAsmRefName) == 0); - } - } - } - } - - if (fLookForDef) - { - mdTypeDef tkResTd; - - if (ImportHelper::FindTypeDefByName(pMiniMd, - szExtNameSpace, - szExtName, - tkResScope, - &tkResTd) == S_OK) - { - // Ref to Def optimization is not expected to happen for Obj files. - /* - if (m_ModuleType != ValidatorModuleTypeObj) - { - REPORT_ERROR2(VLDTR_E_TD_EXTTRRES, tkExtends, tkResTd); - SetVldtrCode(&hrSave, VLDTR_S_WRN); - } - */ - - // Set tkExtends to the new TypeDef, so we can continue - // with the validation. - tkExtends = tkResTd; - } - } - } - - // Continue validation, even for the case where TypeRef got resolved - // to a corresponding TypeDef in the same Module. - if (TypeFromToken(tkExtends) == mdtTypeDef) - { - // Extends must not be sealed. - IfFailGo(pMiniMd->GetTypeDefRecord(RidFromToken(tkExtends), &pExtendsRec)); - dwExtendsFlags = pMiniMd->getFlagsOfTypeDef(pExtendsRec); - IfFailGo(pMiniMd->getNameOfTypeDef(pExtendsRec, &szExtName)); - IfFailGo(pMiniMd->getNamespaceOfTypeDef(pExtendsRec, &szExtNameSpace)); - if (IsTdSealed(dwExtendsFlags)) - { - REPORT_ERROR1(VLDTR_E_TD_EXTENDSSEALED, tkExtends); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - if (IsTdInterface(dwExtendsFlags)) - { - REPORT_ERROR1(VLDTR_E_TD_EXTENDSIFACE, tkExtends); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - else if(TypeFromToken(tkExtends) == mdtTypeSpec) - { - //If we got here, the instantiated generic type is itself a type spec, which is illegal - REPORT_ERROR1(VLDTR_E_TD_EXTBADTYPESPEC, tkExtends); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - szExtName = ""; - szExtNameSpace = ""; - - } - // If the parent token is non-null, the class must not be System.Object. - if (bIsObject) - { - REPORT_ERROR1(VLDTR_E_TD_OBJEXTENDSNONNULL, tkExtends); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - - bExtendsObject = bExtendsEnum = bExtendsVType = bExtendsMCDelegate = FALSE; - if(0 == strcmp(szExtNameSpace,BASE_NAMESPACE)) - { - bExtendsObject = (0 == strcmp(szExtName,BASE_OBJECT_CLASSNAME)); - if(!bExtendsObject) - { - bExtendsEnum = (0 == strcmp(szExtName,BASE_ENUM_CLASSNAME)); - if(!bExtendsEnum) - { - bExtendsVType = (0 == strcmp(szExtName,BASE_VTYPE_CLASSNAME)); - if(!bExtendsVType) - { - bExtendsMCDelegate = (0 == strcmp(szExtName,BASE_MCDELEGATE_CLASSNAME)); - } - } - } - } - - // System.ValueType must extend System.Object - if(bIsVType && !bExtendsObject) - { - REPORT_ERROR0(VLDTR_E_TD_SYSVTNOTEXTOBJ); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // Validate rules for interface. Some of the VOS rules are verified as - // part of the validation for the corresponding Methods, fields etc. - if (IsTdInterface(dwFlags)) - { - // Interface type must be marked abstract. - if (!IsTdAbstract(dwFlags)) - { - REPORT_ERROR0(VLDTR_E_TD_IFACENOTABS); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - // Interface must not be sealed - if(IsTdSealed(dwFlags)) - { - REPORT_ERROR0(VLDTR_E_TD_IFACESEALED); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - // Interface must have parent Nil token. - if (!IsNilToken(tkExtends)) - { - REPORT_ERROR1(VLDTR_E_TD_IFACEPARNOTNIL, tkExtends); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - //Interface must have only static fields -- checked in ValidateField - //Interface must have only public fields -- checked in ValidateField - //Interface must have only abstract or static methods -- checked in ValidateMethod - //Interface must have only public methods -- checked in ValidateMethod - - // Interface must have GUID - /* - if (*pGuid == GUID_NULL) - { - REPORT_ERROR0(VLDTR_E_TD_IFACEGUIDNULL); - SetVldtrCode(&hrSave, VLDTR_S_WRN); - } - */ - } - - - // Class must have valid method and field lists - { - ULONG ridStart,ridEnd; - ridStart = pMiniMd->getMethodListOfTypeDef(pRecord); - ridEnd = pMiniMd->getCountMethods() + 1; - if(ridStart > ridEnd) - { - REPORT_ERROR0(VLDTR_E_TD_BADMETHODLST); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else - { - IfFailGo(pMiniMd->getEndMethodListOfTypeDef(rid, &ridEnd)); - bHasMethods = (ridStart && (ridStart < ridEnd)); - } - - ridStart = pMiniMd->getFieldListOfTypeDef(pRecord); - ridEnd = pMiniMd->getCountFields() + 1; - if(ridStart > ridEnd) - { - REPORT_ERROR0(VLDTR_E_TD_BADFIELDLST); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else - { - IfFailGo(pMiniMd->getEndFieldListOfTypeDef(rid, &ridEnd)); - bHasFields = (ridStart && (ridStart < ridEnd)); - } - } - - // Validate rules for System.Enum - if(bIsEnum) - { - if(!IsTdClass(dwFlags)) - { - REPORT_ERROR0(VLDTR_E_TD_SYSENUMNOTCLASS); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - if(!bExtendsVType) - { - REPORT_ERROR0(VLDTR_E_TD_SYSENUMNOTEXTVTYPE); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - else - { - if(bExtendsVType || bExtendsEnum) - { - // ValueTypes and Enums must be sealed - if(!IsTdSealed(dwFlags)) - { - REPORT_ERROR0(VLDTR_E_TD_VTNOTSEAL); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // Value class must have fields or size - if(!bHasFields) - { - ULONG ulClassSize = 0; - ClassLayoutRec *pRec; - RID ridClassLayout; - IfFailGo(pMiniMd->FindClassLayoutHelper(TokenFromRid(rid, mdtTypeDef), &ridClassLayout)); - - if (!InvalidRid(ridClassLayout)) - { - IfFailGo(pMiniMd->GetClassLayoutRecord(RidFromToken(ridClassLayout), &pRec)); - ulClassSize = pMiniMd->getClassSizeOfClassLayout(pRec); - } - if(ulClassSize == 0) - { - REPORT_ERROR0(VLDTR_E_TD_VTNOSIZE); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - } - else if(bExtendsMCDelegate) - { - // Delegates must be sealed - if(!IsTdSealed(dwFlags)) - { - REPORT_ERROR0(VLDTR_E_TD_VTNOTSEAL); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - } - - // Enum-related checks - if (bExtendsEnum) - { - { - PCCOR_SIGNATURE pValueSig = NULL; - ULONG cbValueSig = 0; - mdFieldDef tkValueField=0, tkField, tkValue__Field = 0; - ULONG ridStart,ridEnd,index; - FieldRec *pFieldRecord; // Field record. - DWORD dwRecordFlags, dwTally, dwValueFlags, dwValue__Flags = 0; - RID ridField,ridValue=0,ridValue__ = 0; - - ridStart = pMiniMd->getFieldListOfTypeDef(pRecord); - IfFailGo(pMiniMd->getEndFieldListOfTypeDef(rid, &ridEnd)); - // check the instance (value__) field(s) - dwTally = 0; - for (index = ridStart; index < ridEnd; index++ ) - { - IfFailGo(pMiniMd->GetFieldRid(index, &ridField)); - IfFailGo(pMiniMd->GetFieldRecord(ridField, &pFieldRecord)); - dwRecordFlags = pFieldRecord->GetFlags(); - if(!IsFdStatic(dwRecordFlags)) - { - dwTally++; - if(ridValue == 0) - { - ridValue = ridField; - tkValueField = TokenFromRid(ridField, mdtFieldDef); - IfFailGo(pMiniMd->getSignatureOfField(pFieldRecord, &pValueSig, &cbValueSig)); - dwValueFlags = dwRecordFlags; - } - } - LPCSTR szFieldName; - IfFailGo(pMiniMd->getNameOfField(pFieldRecord, &szFieldName)); - if(!strcmp(szFieldName, BASE_VALUE_FIELDNAME)) - { - ridValue__ = ridField; - dwValue__Flags = dwRecordFlags; - tkValue__Field = TokenFromRid(ridField, mdtFieldDef); - } - } - // Enum must have one (and only one) inst.field - if(dwTally == 0) - { - REPORT_ERROR0(VLDTR_E_TD_ENUMNOINSTFLD); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else if(dwTally > 1) - { - REPORT_ERROR0(VLDTR_E_TD_ENUMMULINSTFLD); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - // inst.field name must be "value__" (CLS) - if(ridValue__ == 0) - { - REPORT_ERROR0(VLDTR_E_TD_ENUMNOVALUE); - SetVldtrCode(&hrSave, VLDTR_S_WRN); - } - else - { - // if "value__" field is present ... - // ... it must be 1st instance field - if(ridValue__ != ridValue) - { - REPORT_ERROR1(VLDTR_E_TD_ENUMVALNOT1ST, tkValue__Field); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // ... it must not be static - if(IsFdStatic(dwValue__Flags)) - { - REPORT_ERROR1(VLDTR_E_TD_ENUMVALSTATIC, tkValue__Field); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // ... it must be fdRTSpecialName - if(!IsFdRTSpecialName(dwValue__Flags)) - { - REPORT_ERROR1(VLDTR_E_TD_ENUMVALNOTSN, tkValueField); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // ... its type must be integral - if(cbValueSig && pValueSig) - { - //ULONG ulCurByte = CorSigUncompressedDataSize(pValueSig); - //CorSigUncompressData(pValueSig); - //ULONG ulElemSize,ulElementType; - //ulCurByte += (ulElemSize = CorSigUncompressedDataSize(pValueSig)); - //ulElementType = CorSigUncompressData(pValueSig); - //switch (ulElementType) - BYTE* pB = (BYTE*)pValueSig; - pB++; // skip the calling convention - while((*pB == ELEMENT_TYPE_CMOD_OPT)|| - (*pB == ELEMENT_TYPE_CMOD_REQD)) - { - mdToken tok; - pB++; // move from E_T_... to compressed token - pB += CorSigUncompressToken((PCOR_SIGNATURE)pB,&tok); - } - switch(*pB) - { - case ELEMENT_TYPE_BOOLEAN: - case ELEMENT_TYPE_CHAR: - case ELEMENT_TYPE_I1: - case ELEMENT_TYPE_U1: - case ELEMENT_TYPE_I2: - case ELEMENT_TYPE_U2: - case ELEMENT_TYPE_I4: - case ELEMENT_TYPE_U4: - case ELEMENT_TYPE_I8: - case ELEMENT_TYPE_U8: - case ELEMENT_TYPE_U: - case ELEMENT_TYPE_I: - case ELEMENT_TYPE_R4: - case ELEMENT_TYPE_R8: - break; - default: - REPORT_ERROR1(VLDTR_E_TD_ENUMFLDBADTYPE, tkValue__Field); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - } - // check all the fields - dwTally = 0; - for (index = ridStart; index < ridEnd; index++ ) - { - IfFailGo(pMiniMd->GetFieldRid(index, &ridField)); - if(ridField == ridValue) continue; - IfFailGo(pMiniMd->GetFieldRecord(ridField, &pFieldRecord)); - LPCSTR szFieldName; - IfFailGo(pMiniMd->getNameOfField(pFieldRecord, &szFieldName)); - if(IsFdRTSpecialName(pFieldRecord->GetFlags()) - && IsDeletedName(szFieldName)) continue; - dwTally++; - tkField = TokenFromRid(ridField, mdtFieldDef); - if(!IsFdStatic(pFieldRecord->GetFlags())) - { - REPORT_ERROR1(VLDTR_E_TD_ENUMFLDNOTST, tkField); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - if(!IsFdLiteral(pFieldRecord->GetFlags())) - { - REPORT_ERROR1(VLDTR_E_TD_ENUMFLDNOTLIT, tkField); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - /* - IfFailGo(pMiniMd->getSignatureOfField(pFieldRecord, &pvSigTmp, &cbSig)); - if(!(pvSigTmp && (cbSig==cbValueSig) &&(memcmp(pvSigTmp,pValueSig,cbSig)==0))) - { - REPORT_ERROR1(VLDTR_E_TD_ENUMFLDSIGMISMATCH, tkField); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - */ - } - if(dwTally == 0) - { - REPORT_ERROR0(VLDTR_E_TD_ENUMNOLITFLDS); - SetVldtrCode(&hrSave, VLDTR_S_WRN); - } - } - // Enum must have no methods - if (bHasMethods) - { - REPORT_ERROR0(VLDTR_E_TD_ENUMHASMETHODS); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // Enum must implement no interfaces - { - ULONG ridStart = 1; - ULONG ridEnd = pMiniMd->getCountInterfaceImpls() + 1; - ULONG index; - for (index = ridStart; index < ridEnd; index ++ ) - { - InterfaceImplRec *pInterfaceImplRecord; - IfFailGo(pMiniMd->GetInterfaceImplRecord(index, &pInterfaceImplRecord)); - if (veCtxt.Token == pMiniMd->getClassOfInterfaceImpl(pInterfaceImplRecord)) - { - REPORT_ERROR0(VLDTR_E_TD_ENUMIMPLIFACE); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - break; - } - } - } - // Enum must have no properties - { - ULONG ridStart = 1; - ULONG ridEnd = pMiniMd->getCountPropertys() + 1; - ULONG index; - mdToken tkClass; - for (index = ridStart; index < ridEnd; index ++ ) - { - IfFailGo(pMiniMd->FindParentOfPropertyHelper(index | mdtProperty, &tkClass)); - if (veCtxt.Token == tkClass) - { - REPORT_ERROR0(VLDTR_E_TD_ENUMHASPROP); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - break; - } - } - } - // Enum must have no events - { - ULONG ridStart = 1; - ULONG ridEnd = pMiniMd->getCountEvents() + 1; - ULONG index; - mdToken tkClass; - for (index = ridStart; index < ridEnd; index ++ ) - { - IfFailGo(pMiniMd->FindParentOfEventHelper(index | mdtEvent, &tkClass)); - if (veCtxt.Token == tkClass) - { - REPORT_ERROR0(VLDTR_E_TD_ENUMHASEVENT); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - break; - } - } - } - } // end if(bExtendsEnum) - // Class having security must be marked tdHasSecurity and vice versa - { - ULONG ridStart = 1; - ULONG ridEnd = pMiniMd->getCountDeclSecuritys() + 1; - ULONG index; - BOOL bHasSecurity = FALSE; - for (index = ridStart; index < ridEnd; index ++ ) - { - DeclSecurityRec *pDeclSecurityRecord; - IfFailGo(pMiniMd->GetDeclSecurityRecord(index, &pDeclSecurityRecord)); - if (veCtxt.Token == pMiniMd->getParentOfDeclSecurity(pDeclSecurityRecord)) - { - bHasSecurity = TRUE; - break; - } - } - if (!bHasSecurity) // No records, check for CA "SuppressUnmanagedCodeSecurityAttribute" - { - bHasSecurity = (S_OK == ImportHelper::GetCustomAttributeByName(pMiniMd, veCtxt.Token, - "System.Security.SuppressUnmanagedCodeSecurityAttribute", NULL, NULL)); - } - if(bHasSecurity != (IsTdHasSecurity(pRecord->GetFlags())!=0)) - { - REPORT_ERROR0(bHasSecurity ? VLDTR_E_TD_SECURNOTMARKED : VLDTR_E_TD_MARKEDNOSECUR); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - - hr = hrSave; -ErrExit: - ; - END_ENTRYPOINT_NOTHROW; - - return hr; -} // RegMeta::ValidateTypeDef() -#ifdef _PREFAST_ -#pragma warning(pop) -#endif - -//***************************************************************************** -// Validate the given FieldPtr. -//***************************************************************************** -HRESULT RegMeta::ValidateFieldPtr(RID rid) -{ - return S_OK; -} // RegMeta::ValidateFieldPtr() - - -//***************************************************************************** -// Validate the given Field. -//***************************************************************************** -HRESULT RegMeta::ValidateField(RID rid) -{ - CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); // MiniMd of the scope. - FieldRec *pRecord; // Field record. - mdTypeDef tkTypeDef; // Parent TypeDef token. - mdFieldDef tkFieldDef; // Duplicate FieldDef token. - LPCSTR szName; // FieldDef name. - PCCOR_SIGNATURE pbSig; // FieldDef signature. - ULONG cbSig; // Signature size in bytes. - VEContext veCtxt; // Context record. - HRESULT hr = S_OK; // Value returned. - HRESULT hrSave = S_OK; // Save state. - BOOL bIsValueField; - BOOL bIsGlobalField = FALSE; - BOOL bHasValidRVA = FALSE; - DWORD dwInvalidFlags; - DWORD dwFlags; - RID tempRid; - - BEGIN_ENTRYPOINT_NOTHROW; - - memset(&veCtxt, 0, sizeof(VEContext)); - - // Get the FieldDef record. - veCtxt.Token = TokenFromRid(rid, mdtFieldDef); - veCtxt.uOffset = 0; - - IfFailGo(pMiniMd->GetFieldRecord(rid, &pRecord)); - - // Do checks for name validity. - IfFailGo(pMiniMd->getNameOfField(pRecord, &szName)); - if (!*szName) - { - // Field name is NULL. - REPORT_ERROR0(VLDTR_E_FD_NAMENULL); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else - { - if(!strcmp(szName,COR_DELETED_NAME_A)) goto ErrExit; - ULONG L = (ULONG)strlen(szName); - if(L >= MAX_CLASSNAME_LENGTH) - { - REPORT_ERROR2(VLDTR_E_TD_NAMETOOLONG, L, (ULONG)(MAX_CLASSNAME_LENGTH-1)); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - bIsValueField = (strcmp(szName,BASE_VALUE_FIELDNAME)==0); - // If field is RTSpecialName, its name must be 'value__' and vice versa - if((IsFdRTSpecialName(pRecord->GetFlags())!=0) != bIsValueField) - { - REPORT_ERROR1(bIsValueField ? VLDTR_E_TD_ENUMVALNOTSN : VLDTR_E_FD_NOTVALUERTSN, veCtxt.Token); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - // Validate flags - dwFlags = pRecord->GetFlags(); - dwInvalidFlags = ~(fdFieldAccessMask | fdStatic | fdInitOnly | fdLiteral | fdNotSerialized | fdSpecialName - | fdPinvokeImpl | fdReservedMask); - if(dwFlags & dwInvalidFlags) - { - REPORT_ERROR1(VLDTR_E_TD_EXTRAFLAGS, dwFlags & dwInvalidFlags); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - // Validate access - if((dwFlags & fdFieldAccessMask) == fdFieldAccessMask) - { - REPORT_ERROR0(VLDTR_E_FMD_BADACCESSFLAG); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // Literal : Static, !InitOnly - if(IsFdLiteral(dwFlags)) - { - if(IsFdInitOnly(dwFlags)) - { - REPORT_ERROR0(VLDTR_E_FD_INITONLYANDLITERAL); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - if(!IsFdStatic(dwFlags)) - { - REPORT_ERROR0(VLDTR_E_FD_LITERALNOTSTATIC); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - if(!IsFdHasDefault(dwFlags)) - { - REPORT_ERROR0(VLDTR_E_FD_LITERALNODEFAULT); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - // RTSpecialName => SpecialName - if(IsFdRTSpecialName(dwFlags) && !IsFdSpecialName(dwFlags)) - { - REPORT_ERROR0(VLDTR_E_FMD_RTSNNOTSN); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - // Validate Field signature. - IfFailGo(pMiniMd->getSignatureOfField(pRecord, &pbSig, &cbSig)); - IfFailGo(ValidateFieldSig(TokenFromRid(rid, mdtFieldDef), pbSig, cbSig)); - if (hr != S_OK) - SetVldtrCode(&hrSave, hr); - - // Validate Field RVA - if(IsFdHasFieldRVA(dwFlags)) - { - ULONG iFieldRVARid; - IfFailGo(pMiniMd->FindFieldRVAHelper(TokenFromRid(rid, mdtFieldDef), &iFieldRVARid)); - if((iFieldRVARid==0) || (iFieldRVARid > pMiniMd->getCountFieldRVAs())) - { - REPORT_ERROR0(VLDTR_E_FD_RVAHASNORVA); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else - { - /* - FieldRVARec *pRVARec; - IfFailGo(pMiniMd->GetFieldRVARecord(iFieldRVARid, &pRVARec)); - if(pRVARec->GetRVA() == 0) - { - REPORT_ERROR0(VLDTR_E_FD_RVAHASZERORVA); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else - */ - bHasValidRVA = TRUE; - } - } - - // Get the parent of the Field. - IfFailGo(pMiniMd->FindParentOfFieldHelper(TokenFromRid(rid, mdtFieldDef), &tkTypeDef)); - // Validate that the parent is not nil. - if (IsNilToken(tkTypeDef)) - { - REPORT_ERROR0(VLDTR_E_FD_PARNIL); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else if (RidFromToken(tkTypeDef) != RidFromToken(m_tdModule)) - { - if(IsValidToken(tkTypeDef) && (TypeFromToken(tkTypeDef) == mdtTypeDef)) - { - TypeDefRec *pParentRec; - IfFailGo(pMiniMd->GetTypeDefRecord(RidFromToken(tkTypeDef), &pParentRec)); - // If the name is "value__" ... - if(bIsValueField) - { - // parent must be Enum - mdToken tkExtends = pMiniMd->getExtendsOfTypeDef(pParentRec); - RID ridExtends = RidFromToken(tkExtends); - LPCSTR szExtName="",szExtNameSpace=""; - if(ridExtends) - { - if(TypeFromToken(tkExtends) == mdtTypeRef) - { - TypeRefRec *pExtRec; - IfFailGo(pMiniMd->GetTypeRefRecord(ridExtends, &pExtRec)); - IfFailGo(pMiniMd->getNameOfTypeRef(pExtRec, &szExtName)); - IfFailGo(pMiniMd->getNamespaceOfTypeRef(pExtRec, &szExtNameSpace)); - } - else if(TypeFromToken(tkExtends) == mdtTypeDef) - { - TypeDefRec *pExtRec; - IfFailGo(pMiniMd->GetTypeDefRecord(ridExtends, &pExtRec)); - IfFailGo(pMiniMd->getNameOfTypeDef(pExtRec, &szExtName)); - IfFailGo(pMiniMd->getNamespaceOfTypeDef(pExtRec, &szExtNameSpace)); - } - } - if(strcmp(szExtName,BASE_ENUM_CLASSNAME) || strcmp(szExtNameSpace,BASE_NAMESPACE)) - { - REPORT_ERROR0(VLDTR_E_FD_VALUEPARNOTENUM); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - // field must be instance - checked in ValidateTypeDef - // must be no other instance fields - checked in ValidateTypeDef - // must be first field - checked in ValidateTypeDef - // must be RTSpecialName -- checked in ValidateTypeDef - } - if(IsTdInterface(pMiniMd->getFlagsOfTypeDef(pParentRec))) - { - // Fields in interface are not CLS compliant - REPORT_ERROR0(VLDTR_E_FD_FLDINIFACE); - SetVldtrCode(&hrSave, VLDTR_S_WRN); - - // If field is not static, verify parent is not interface. - if(!IsFdStatic(dwFlags)) - { - REPORT_ERROR0(VLDTR_E_FD_INSTINIFACE); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - // If field is not public, verify parent is not interface. - if(!IsFdPublic(dwFlags)) - { - REPORT_ERROR0(VLDTR_E_FD_NOTPUBINIFACE); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - } - } // end if Valid and TypeDef - else - { - REPORT_ERROR1(VLDTR_E_FD_BADPARENT, tkTypeDef); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - else // i.e. if (RidFromToken(tkTypeDef) == RidFromToken(m_tdModule)) - { - bIsGlobalField = TRUE; - // Globals are not CLS-compliant - REPORT_ERROR0(VLDTR_E_FMD_GLOBALITEM); - SetVldtrCode(&hrSave, VLDTR_S_WRN); - // Validate global field: - // Must be static - if(!IsFdStatic(dwFlags)) - { - REPORT_ERROR0(VLDTR_E_FMD_GLOBALNOTSTATIC); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // Must have a non-zero RVA - /* - if(!bHasValidRVA) - { - REPORT_ERROR0(VLDTR_E_FD_GLOBALNORVA); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - */ - } - - // Check for duplicates, except global fields with PrivateScope. - if (*szName && cbSig && !IsFdPrivateScope(dwFlags)) - { - hr = ImportHelper::FindField(pMiniMd, tkTypeDef, szName, pbSig, cbSig, &tkFieldDef, rid); - if (hr == S_OK) - { - if(!IsFdPrivateScope(dwFlags)) - { - REPORT_ERROR1(VLDTR_E_FD_DUP, tkFieldDef); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else hr = S_OK; - } - else if (hr == CLDB_E_RECORD_NOTFOUND) - { - hr = S_OK; - } - else - { - IfFailGo(hr); - } - } - // Field having security must be marked fdHasSecurity and vice versa - { - ULONG ridStart = 1; - ULONG ridEnd = pMiniMd->getCountDeclSecuritys() + 1; - ULONG index; - BOOL bHasSecurity = FALSE; - for (index = ridStart; index < ridEnd; index ++ ) - { - DeclSecurityRec *pDeclSecurityRecord; - IfFailGo(pMiniMd->GetDeclSecurityRecord(index, &pDeclSecurityRecord)); - if ( veCtxt.Token == pMiniMd->getParentOfDeclSecurity(pDeclSecurityRecord)) - { - bHasSecurity = TRUE; - break; - } - } - if(!bHasSecurity) // No records, check for CA "SuppressUnmanagedCodeSecurityAttribute" - { - bHasSecurity = (S_OK == ImportHelper::GetCustomAttributeByName(pMiniMd, veCtxt.Token, - "System.Security.SuppressUnmanagedCodeSecurityAttribute", NULL, NULL)); - } - if(bHasSecurity) - { - REPORT_ERROR0(VLDTR_E_FMD_SECURNOTMARKED); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - // Field having marshaling must be marked fdHasFieldMarshal and vice versa - IfFailGo(pMiniMd->FindFieldMarshalHelper(veCtxt.Token, &tempRid)); - if (InvalidRid(tempRid) == (IsFdHasFieldMarshal(dwFlags) != 0)) - { - REPORT_ERROR0(IsFdHasFieldMarshal(dwFlags)? VLDTR_E_FD_MARKEDNOMARSHAL : VLDTR_E_FD_MARSHALNOTMARKED); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // Field having const value must be marked fdHasDefault and vice versa - IfFailGo(pMiniMd->FindConstantHelper(veCtxt.Token, &tempRid)); - if(InvalidRid(tempRid) == (IsFdHasDefault(dwFlags) != 0)) - { - REPORT_ERROR0(IsFdHasDefault(dwFlags)? VLDTR_E_FD_MARKEDNODEFLT : VLDTR_E_FD_DEFLTNOTMARKED); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // Check the field's impl.map - { - ULONG iRecord; - IfFailGo(pMiniMd->FindImplMapHelper(veCtxt.Token, &iRecord)); - if(IsFdPinvokeImpl(dwFlags)) - { - // must be static - if(!IsFdStatic(dwFlags)) - { - REPORT_ERROR0(VLDTR_E_FMD_PINVOKENOTSTATIC); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // must have ImplMap - if (InvalidRid(iRecord)) - { - REPORT_ERROR0(VLDTR_E_FMD_MARKEDNOPINVOKE); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - else - { - // must have no ImplMap - if (!InvalidRid(iRecord)) - { - REPORT_ERROR0(VLDTR_E_FMD_PINVOKENOTMARKED); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - if (!InvalidRid(iRecord)) - { - hr = ValidateImplMap(iRecord); - if(hr != S_OK) - { - REPORT_ERROR0(VLDTR_E_FMD_BADIMPLMAP); - SetVldtrCode(&hrSave, VLDTR_S_WRN); - } - } - - } - - hr = hrSave; -ErrExit: - ; - END_ENTRYPOINT_NOTHROW; - - return hr; -} // RegMeta::ValidateField() - -//***************************************************************************** -// Validate the given MethodPtr. -//***************************************************************************** -HRESULT RegMeta::ValidateMethodPtr(RID rid) -{ - return S_OK; -} // RegMeta::ValidateMethodPtr() - - -//***************************************************************************** -// Validate the given Method. -//***************************************************************************** -#ifdef _PREFAST_ -#pragma warning(push) -#pragma warning(disable:21000) // Suppress PREFast warning about overly large function -#endif -HRESULT RegMeta::ValidateMethod(RID rid) -{ - CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); // MiniMd of the scope. - MethodRec *pRecord = NULL; // Method record. - mdTypeDef tkTypeDef; // Parent TypeDef token. - mdMethodDef tkMethodDef; // Duplicate MethodDef token. - LPCSTR szName; // MethodDef name. - DWORD dwFlags = 0; // Method flags. - DWORD dwImplFlags = 0; // Method impl.flags. - PCCOR_SIGNATURE pbSig; // MethodDef signature. - ULONG cbSig; // Signature size in bytes. - VEContext veCtxt; // Context record. - HRESULT hr = S_OK; // Value returned. - HRESULT hrSave = S_OK; // Save state. - BOOL bIsCtor=FALSE; - BOOL bIsCctor=FALSE; - BOOL bIsGlobal=FALSE; - BOOL bIsParentImport = FALSE; - BOOL bIsGeneric = FALSE; - unsigned retType; - - BEGIN_ENTRYPOINT_NOTHROW; - - memset(&veCtxt, 0, sizeof(VEContext)); - - // Get the MethodDef record. - veCtxt.Token = TokenFromRid(rid, mdtMethodDef); - veCtxt.uOffset = 0; - - IfFailGo(pMiniMd->GetMethodRecord(rid, &pRecord)); - - // Do checks for name validity. - IfFailGo(pMiniMd->getNameOfMethod(pRecord, &szName)); - if (!*szName) - { - // Method name is NULL. - REPORT_ERROR0(VLDTR_E_MD_NAMENULL); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else - { - if(!strcmp(szName,COR_DELETED_NAME_A)) goto ErrExit; - bIsCtor = (0 == strcmp(szName,BASE_CTOR_NAME)); - bIsCctor = (0 == strcmp(szName,BASE_CCTOR_NAME)); - ULONG L = (ULONG)strlen(szName); - if(L >= MAX_CLASSNAME_LENGTH) - { - REPORT_ERROR2(VLDTR_E_TD_NAMETOOLONG, L, (ULONG)(MAX_CLASSNAME_LENGTH-1)); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - - // Get the parent, flags and signature of the Method. - IfFailGo(pMiniMd->FindParentOfMethodHelper(TokenFromRid(rid, mdtMethodDef), &tkTypeDef)); - dwFlags = pMiniMd->getFlagsOfMethod(pRecord); - dwImplFlags = pMiniMd->getImplFlagsOfMethod(pRecord); - IfFailGo(pMiniMd->getSignatureOfMethod(pRecord, &pbSig, &cbSig)); - - // Check for duplicates. - if (*szName && cbSig && !IsNilToken(tkTypeDef) && !IsMdPrivateScope(dwFlags)) - { - hr = ImportHelper::FindMethod(pMiniMd, tkTypeDef, szName, pbSig, cbSig, &tkMethodDef, rid); - if (hr == S_OK) - { - REPORT_ERROR1(VLDTR_E_MD_DUP, tkMethodDef); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else if (hr == CLDB_E_RECORD_NOTFOUND) - hr = S_OK; - else - IfFailGo(hr); - } - - // No further error checking for VtblGap methods. - if (IsVtblGapName(szName)) - { - hr = hrSave; - goto ErrExit; - } - - // Validate Method signature. - IfFailGo(ValidateMethodSig(TokenFromRid(rid, mdtMethodDef), pbSig, cbSig, - dwFlags)); - if (hr != S_OK) - SetVldtrCode(&hrSave, hr); - - // Validate that the parent is not nil. - if (IsNilToken(tkTypeDef)) - { - REPORT_ERROR0(VLDTR_E_MD_PARNIL); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else if (RidFromToken(tkTypeDef) != RidFromToken(m_tdModule)) - { - if(TypeFromToken(tkTypeDef) == mdtTypeDef) - { - TypeDefRec *pTDRec; - IfFailGo(pMiniMd->GetTypeDefRecord(RidFromToken(tkTypeDef), &pTDRec)); - DWORD dwTDFlags = pTDRec->GetFlags(); - LPCSTR szTDName; - IfFailGo(pMiniMd->getNameOfTypeDef(pTDRec, &szTDName)); - LPCSTR szTDNameSpace; - IfFailGo(pMiniMd->getNamespaceOfTypeDef(pTDRec, &szTDNameSpace)); - BOOL fIsTdValue=FALSE, fIsTdEnum=FALSE; - mdToken tkExtends = pMiniMd->getExtendsOfTypeDef(pTDRec); - - if(0 == strcmp(szTDNameSpace,BASE_NAMESPACE)) - { - fIsTdEnum = (0 == strcmp(szTDName,BASE_ENUM_CLASSNAME)); - if(!fIsTdEnum) - { - fIsTdValue = (0 == strcmp(szTDName,BASE_VTYPE_CLASSNAME)); - } - } - if(fIsTdEnum || fIsTdValue) - { - fIsTdEnum = fIsTdValue = FALSE; // System.Enum and System.ValueType themselves are classes - } - else if(RidFromToken(tkExtends)) - { - if(TypeFromToken(tkExtends) == mdtTypeDef) - { - IfFailGo(pMiniMd->GetTypeDefRecord(RidFromToken(tkExtends), &pTDRec)); - IfFailGo(pMiniMd->getNameOfTypeDef(pTDRec, &szTDName)); - IfFailGo(pMiniMd->getNamespaceOfTypeDef(pTDRec, &szTDNameSpace)); - } - else if(TypeFromToken(tkExtends) == mdtTypeSpec) - { - fIsTdEnum = fIsTdValue = FALSE; // a type extending a spec cannot be an enum or value type - // the assignments are redundant, but clear. - } - else - { - TypeRefRec *pTRRec; - IfFailGo(pMiniMd->GetTypeRefRecord(RidFromToken(tkExtends), &pTRRec)); - IfFailGo(pMiniMd->getNameOfTypeRef(pTRRec, &szTDName)); - IfFailGo(pMiniMd->getNamespaceOfTypeRef(pTRRec, &szTDNameSpace)); - } - - if(0 == strcmp(szTDNameSpace,BASE_NAMESPACE)) - { - fIsTdEnum = (0 == strcmp(szTDName,BASE_ENUM_CLASSNAME)); - if(!fIsTdEnum) - { - fIsTdValue = (0 == strcmp(szTDName,BASE_VTYPE_CLASSNAME)); - } - else fIsTdValue = FALSE; - } - } - - // If Method is abstract, verify parent is abstract. - if(IsMdAbstract(dwFlags) && !IsTdAbstract(dwTDFlags)) - { - REPORT_ERROR1(VLDTR_E_MD_ABSTPARNOTABST, tkTypeDef); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // If parent is import, method must have zero RVA, otherwise it depends... - if(IsTdImport(dwTDFlags)) bIsParentImport = TRUE; - if(IsTdInterface(dwTDFlags)) - { - if(!IsMdStatic(dwFlags)) - { - // No non-abstract instance methods in interface. - if(!IsMdAbstract(dwFlags)) - { - REPORT_ERROR1(VLDTR_E_MD_NOTSTATABSTININTF, tkTypeDef); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // No non-public instance methods in interface. - if(!IsMdPublic(dwFlags)) - { - REPORT_ERROR1(VLDTR_E_MD_NOTPUBININTF, tkTypeDef); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - // If Method is constructor, verify parent is not interface. - if(bIsCtor) - { - REPORT_ERROR1(VLDTR_E_MD_CTORININTF, tkTypeDef); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - }//end if(interface) - if((fIsTdValue || fIsTdEnum) && IsMiSynchronized(dwImplFlags)) - { - REPORT_ERROR1(VLDTR_E_MD_SYNCMETHODINVTYPE, tkTypeDef); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - if(bIsCtor) - { - // .ctor must be instance - if(IsMdStatic(dwFlags)) - { - REPORT_ERROR1(VLDTR_E_MD_CTORSTATIC, tkTypeDef); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - }//end if .ctor - else if(bIsCctor) - { - // .cctor must be static - if(!IsMdStatic(dwFlags)) - { - REPORT_ERROR1(VLDTR_E_MD_CCTORNOTSTATIC, tkTypeDef); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // ..cctor must have default callconv - IfFailGo(pMiniMd->getSignatureOfMethod(pRecord, &pbSig, &cbSig)); - if(IMAGE_CEE_CS_CALLCONV_DEFAULT != CorSigUncompressData(pbSig)) - { - REPORT_ERROR0(VLDTR_E_MD_CCTORCALLCONV); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // .cctor must have no arguments - if(0 != CorSigUncompressData(pbSig)) - { - REPORT_ERROR0(VLDTR_E_MD_CCTORHASARGS); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - - }//end if .cctor - if(bIsCtor || bIsCctor) - { - // .ctor, .cctor must be SpecialName and RTSpecialName - if(!(IsMdSpecialName(dwFlags) && IsMdRTSpecialName(dwFlags))) - { - REPORT_ERROR1(VLDTR_E_MD_CTORNOTSNRTSN, tkTypeDef); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } -#ifdef NO_SUCH_CHECKS_NEEDED_SPEC_TO_BE_UODATED - // .ctor, .cctor must not be virtual - if(IsMdVirtual(dwFlags)) - { - REPORT_ERROR1(VLDTR_E_MD_CTORVIRT, tkTypeDef); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // .ctor, .cctor must not be abstract - if(IsMdAbstract(dwFlags)) - { - REPORT_ERROR1(VLDTR_E_MD_CTORABST, tkTypeDef); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // .ctor, .cctor must not be PInvoke - if(IsMdPinvokeImpl(dwFlags)) - { - REPORT_ERROR1(VLDTR_E_MD_CTORPINVOKE, tkTypeDef); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // .ctor,.cctor must have RVA!=0 - if(pRecord->GetRVA()==0) - { - REPORT_ERROR0(VLDTR_E_MD_CTORZERORVA); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } -#endif - }//end if .ctor or .cctor - }// end if(parent == TypeDef) - }// end if not Module - else // i.e. if (RidFromToken(tkTypeDef) == RidFromToken(m_tdModule)) - { - bIsGlobal = TRUE; - // Globals are not CLS-compliant - REPORT_ERROR0(VLDTR_E_FMD_GLOBALITEM); - SetVldtrCode(&hrSave, VLDTR_S_WRN); - // Validate global method: - // Must be static - if(!IsMdStatic(dwFlags)) - { - REPORT_ERROR0(VLDTR_E_FMD_GLOBALNOTSTATIC); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // Must not be abstract or virtual - if(IsMdAbstract(dwFlags) || IsMdVirtual(dwFlags)) - { - REPORT_ERROR0(VLDTR_E_MD_GLOBALABSTORVIRT); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // Must be not .ctor or .cctor - if(bIsCtor) - { - REPORT_ERROR0(VLDTR_E_MD_GLOBALCTORCCTOR); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } //end if Module - - // Signature specifics: .ctor, .cctor, entrypoint - if(bIsCtor || bIsCctor) - { - // .ctor, .cctor must return void - IfFailGo(pMiniMd->getSignatureOfMethod(pRecord, &pbSig, &cbSig)); - CorSigUncompressData(pbSig); // get call conv out of the way - CorSigUncompressData(pbSig); // get num args out of the way - while (((retType=CorSigUncompressData(pbSig)) == ELEMENT_TYPE_CMOD_OPT) - || (retType == ELEMENT_TYPE_CMOD_REQD)) CorSigUncompressToken(pbSig); - if(retType != ELEMENT_TYPE_VOID) - { - REPORT_ERROR0(VLDTR_E_MD_CTORNOTVOID); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - if(g_tkEntryPoint == veCtxt.Token) - { - ULONG ulCallConv; - // EP must be static - if(!IsMdStatic(dwFlags)) - { - REPORT_ERROR0(VLDTR_E_EP_INSTANCE); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - // EP can't belong to generic class or nested in generic class - mdToken tkTypeDefCur; - for(tkTypeDefCur = tkTypeDef; tkTypeDefCur != mdTokenNil;) - { - HENUMInternal hEnumTyPars; - ULONG ulTypeDefArity = 0; - hr = pMiniMd->FindGenericParamHelper(tkTypeDefCur, &hEnumTyPars); - if (SUCCEEDED(hr)) - { - IfFailGo(HENUMInternal::GetCount(&hEnumTyPars,&ulTypeDefArity)); - HENUMInternal::ClearEnum(&hEnumTyPars); - if (ulTypeDefArity != 0) - { - REPORT_ERROR0(VLDTR_E_EP_GENERIC_TYPE); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - if(ulTypeDefArity == 0) - { - // This class is not generic, how about the encloser? - RID iRecord; - IfFailGo(pMiniMd->FindNestedClassHelper(tkTypeDefCur, &iRecord)); - - if (InvalidRid(iRecord)) - { - tkTypeDefCur = mdTokenNil; - } - else - { - NestedClassRec *pNestedClassRec; - IfFailGo(pMiniMd->GetNestedClassRecord(iRecord, &pNestedClassRec)); - tkTypeDefCur = pMiniMd->getEnclosingClassOfNestedClass(pNestedClassRec); - } - } - else - tkTypeDefCur = mdTokenNil; - } - - // EP must have a predetermined signature (different for DLL and EXE - IfFailGo(pMiniMd->getSignatureOfMethod(pRecord, &pbSig, &cbSig)); - ulCallConv = CorSigUncompressData(pbSig); // get call conv out of the way - // EP can't be generic - if (ulCallConv & IMAGE_CEE_CS_CALLCONV_GENERIC) - { - // Skip the arity - CorSigUncompressData(pbSig); - REPORT_ERROR0(VLDTR_E_EP_GENERIC_METHOD); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - // EP must have 0 or 1 argument - unsigned nArgs = CorSigUncompressData(pbSig); - if(g_fIsDLL) - { - if(nArgs != 3) - { - REPORT_ERROR1(VLDTR_E_EP_TOOMANYARGS, 3); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - //EP must return I4 - while (((retType=CorSigUncompressData(pbSig)) == ELEMENT_TYPE_CMOD_OPT) - || (retType == ELEMENT_TYPE_CMOD_REQD)) CorSigUncompressToken(pbSig); - - if(retType != ELEMENT_TYPE_I4) - { - REPORT_ERROR0(VLDTR_E_EP_BADRET); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // Arguments must be VOID*, U4, VOID* - if(nArgs) - { - unsigned jj; - bool badarg; - for(jj=0; jj<nArgs;jj++) - { - while (((retType=CorSigUncompressData(pbSig)) == ELEMENT_TYPE_CMOD_OPT) - || (retType == ELEMENT_TYPE_CMOD_REQD)) CorSigUncompressToken(pbSig); - - switch(jj) - { - case 0: - case 2: - badarg = (retType != ELEMENT_TYPE_PTR) - ||(CorSigUncompressData(pbSig) != ELEMENT_TYPE_VOID); - break; - - case 1: - badarg = (retType != ELEMENT_TYPE_U4); - break; - - default: - badarg = true; - } - if(badarg) - { - REPORT_ERROR1(VLDTR_E_EP_BADARG, jj+1); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - } - } - else - { - if(nArgs > 1) - { - REPORT_ERROR1(VLDTR_E_EP_TOOMANYARGS, 1); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - //EP must return VOID, I4 or U4 - while (((retType=CorSigUncompressData(pbSig)) == ELEMENT_TYPE_CMOD_OPT) - || (retType == ELEMENT_TYPE_CMOD_REQD)) CorSigUncompressToken(pbSig); - - if((retType != ELEMENT_TYPE_VOID)&&(retType != ELEMENT_TYPE_I4)&&(retType != ELEMENT_TYPE_U4)) - { - REPORT_ERROR0(VLDTR_E_EP_BADRET); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // Argument (if any) must be vector of strings - if(nArgs) - { - while (((retType=CorSigUncompressData(pbSig)) == ELEMENT_TYPE_CMOD_OPT) - || (retType == ELEMENT_TYPE_CMOD_REQD)) CorSigUncompressToken(pbSig); - - if((retType != ELEMENT_TYPE_SZARRAY)||(CorSigUncompressData(pbSig) != ELEMENT_TYPE_STRING)) - { - REPORT_ERROR1(VLDTR_E_EP_BADARG, 1); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - } // end if(IsDll)--else - } // end if (IsEntryPoint) - - - // Check method RVA - if(pRecord->GetRVA()==0) - { - if(!(IsMdPinvokeImpl(dwFlags) || IsMdAbstract(dwFlags) - || IsMiRuntime(dwImplFlags) || IsMiInternalCall(dwImplFlags) - || bIsParentImport)) - { - REPORT_ERROR0(VLDTR_E_MD_ZERORVA); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - else - { - if(m_pStgdb && m_pStgdb->m_pImage) - { - NewHolder<PEDecoder> pe; - - EX_TRY - { - // We need to use different PEDecoder constructors based on the type of data we give it. - // We use the one with a 'bool' as the second argument when dealing with a mapped file, - // and we use the one that takes a COUNT_T as the second argument when dealing with a - // flat file. - - if (m_pStgdb->m_pStgIO->GetMemoryMappedType() == MTYPE_IMAGE) - pe = new (nothrow) PEDecoder(m_pStgdb->m_pImage, false); - else - pe = new (nothrow) PEDecoder(m_pStgdb->m_pImage, (COUNT_T)(m_pStgdb->m_dwImageSize)); - - } - EX_CATCH - { - hr = COR_E_BADIMAGEFORMAT; - } - EX_END_CATCH(SwallowAllExceptions) - - IfFailGo(hr); - IfNullGo(pe); - - if (!pe->CheckRva(pRecord->GetRVA())) - { - REPORT_ERROR1(VLDTR_E_MD_BADRVA, pRecord->GetRVA()); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else - { - if(IsMiManaged(dwImplFlags) && (IsMiIL(dwImplFlags) || IsMiOPTIL(dwImplFlags))) - { - HRESULT hrTemp = S_OK; - // validate locals signature token - EX_TRY - { - COR_ILMETHOD_DECODER method((COR_ILMETHOD*) pe->GetRvaData(pRecord->GetRVA())); - if (method.LocalVarSigTok) - { - if((TypeFromToken(method.GetLocalVarSigTok()) != mdtSignature) || - (!IsValidToken(method.GetLocalVarSigTok())) || (RidFromToken(method.GetLocalVarSigTok())==0)) - { - hrTemp = _ValidateErrorHelper(VLDTR_E_MD_BADLOCALSIGTOK, veCtxt, method.GetLocalVarSigTok()); - if (SUCCEEDED(hrTemp)) - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - } - EX_CATCH - { - hrTemp = _ValidateErrorHelper(VLDTR_E_MD_BADHEADER, veCtxt); - if (SUCCEEDED(hrTemp)) - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - EX_END_CATCH(SwallowAllExceptions) - - IfFailGo(hrTemp); - } - } - } - - if(IsMdAbstract(dwFlags) || bIsParentImport - || IsMiRuntime(dwImplFlags) || IsMiInternalCall(dwImplFlags)) - { - REPORT_ERROR0(VLDTR_E_MD_ZERORVA); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - // Check the method flags - // Validate access - if((dwFlags & mdMemberAccessMask) == mdMemberAccessMask) - { - REPORT_ERROR0(VLDTR_E_FMD_BADACCESSFLAG); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // Final/NewSlot must be virtual - if((IsMdFinal(dwFlags)||IsMdNewSlot(dwFlags)||IsMdCheckAccessOnOverride(dwFlags)) - && !IsMdVirtual(dwFlags)) - { - REPORT_ERROR0(VLDTR_E_MD_FINNOTVIRT); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // Static can't be final or virtual - if(IsMdStatic(dwFlags)) - { - if(IsMdFinal(dwFlags) || IsMdVirtual(dwFlags) || IsMdNewSlot(dwFlags)) - { - REPORT_ERROR0(VLDTR_E_MD_STATANDFINORVIRT); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - else // non-static can't be an entry point - { - if(g_tkEntryPoint == veCtxt.Token) - { - REPORT_ERROR0(VLDTR_E_EP_INSTANCE); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - if(IsMdAbstract(dwFlags)) - { - // Can't be both abstract and final - if(IsMdFinal(dwFlags)) - { - REPORT_ERROR0(VLDTR_E_MD_ABSTANDFINAL); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // If abstract, must be not miForwardRef, not Pinvoke, and must be virtual - if(IsMiForwardRef(dwImplFlags)) - { - REPORT_ERROR0(VLDTR_E_MD_ABSTANDIMPL); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - if(IsMdPinvokeImpl(dwFlags)) - { - REPORT_ERROR0(VLDTR_E_MD_ABSTANDPINVOKE); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - if(!IsMdVirtual(dwFlags)) - { - REPORT_ERROR0(VLDTR_E_MD_ABSTNOTVIRT); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - // If PrivateScope, must have RVA!=0 - if(IsMdPrivateScope(dwFlags) && (pRecord->GetRVA() ==0)) - { - REPORT_ERROR0(VLDTR_E_MD_PRIVSCOPENORVA); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // RTSpecialName => SpecialName - if(IsMdRTSpecialName(dwFlags) && !IsMdSpecialName(dwFlags)) - { - REPORT_ERROR0(VLDTR_E_FMD_RTSNNOTSN); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - // Method having security must be marked mdHasSecurity and vice versa - { - ULONG ridStart = 1; - ULONG ridEnd = pMiniMd->getCountDeclSecuritys() + 1; - ULONG index; - BOOL bHasSecurity = FALSE; - for (index = ridStart; index < ridEnd; index ++ ) - { - DeclSecurityRec *pDeclSecurityRecord; - IfFailGo(pMiniMd->GetDeclSecurityRecord(index, &pDeclSecurityRecord)); - if ( veCtxt.Token == pMiniMd->getParentOfDeclSecurity(pDeclSecurityRecord)) - { - bHasSecurity = TRUE; - break; - } - } - if(!bHasSecurity) // No records, check for CA "SuppressUnmanagedCodeSecurityAttribute" - { - bHasSecurity = (S_OK == ImportHelper::GetCustomAttributeByName(pMiniMd, veCtxt.Token, - "System.Security.SuppressUnmanagedCodeSecurityAttribute", NULL, NULL)); - } - if(bHasSecurity != (IsMdHasSecurity(dwFlags)!=0)) - { - REPORT_ERROR0(bHasSecurity ? VLDTR_E_FMD_SECURNOTMARKED : VLDTR_E_FMD_MARKEDNOSECUR); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - // Validate method semantics - { - MethodSemanticsRec *pRec; - ULONG ridEnd; - ULONG index; - unsigned uTally = 0; - mdToken tkEventProp; - ULONG iCount; - DWORD dwSemantic; - // get the range of method rids given a typedef - ridEnd = pMiniMd->getCountMethodSemantics(); - - for (index = 1; index <= ridEnd; index++ ) - { - IfFailGo(pMiniMd->GetMethodSemanticsRecord(index, &pRec)); - if ( pMiniMd->getMethodOfMethodSemantics(pRec) == veCtxt.Token ) - { - uTally++; - if(uTally > 1) - { - REPORT_ERROR0(VLDTR_E_MD_MULTIPLESEMANTICS); - SetVldtrCode(&hrSave, VLDTR_S_WRN); - } - tkEventProp = pMiniMd->getAssociationOfMethodSemantics(pRec); - if((TypeFromToken(tkEventProp) == mdtEvent)||(TypeFromToken(tkEventProp) == mdtProperty)) - { - iCount = (TypeFromToken(tkEventProp) == mdtEvent) ? pMiniMd->getCountEvents() : - pMiniMd->getCountPropertys(); - if(RidFromToken(tkEventProp) > iCount) - { - REPORT_ERROR1(VLDTR_E_MD_SEMANTICSNOTEXIST, tkEventProp); - SetVldtrCode(&hrSave, VLDTR_S_WRN); - } - } - else - { - REPORT_ERROR1(VLDTR_E_MD_INVALIDSEMANTICS, tkEventProp); - SetVldtrCode(&hrSave, VLDTR_S_WRN); - } - // One and only one semantics flag must be set - iCount = 0; - dwSemantic = pRec->GetSemantic(); - if(IsMsSetter(dwSemantic)) iCount++; - if(IsMsGetter(dwSemantic)) iCount++; - if(IsMsOther(dwSemantic)) iCount++; - if(IsMsAddOn(dwSemantic)) iCount++; - if(IsMsRemoveOn(dwSemantic)) iCount++; - if(IsMsFire(dwSemantic)) iCount++; - if(iCount != 1) - { - REPORT_ERROR1(iCount ? VLDTR_E_MD_MULTSEMANTICFLAGS : VLDTR_E_MD_NOSEMANTICFLAGS, tkEventProp); - SetVldtrCode(&hrSave, VLDTR_S_WRN); - } - } - }// end for(index) - } - // Check the method's impl.map - { - RID iRecord; - IfFailGo(pMiniMd->FindImplMapHelper(veCtxt.Token, &iRecord)); - if(IsMdPinvokeImpl(dwFlags)) - { - // must be static - if(!IsMdStatic(dwFlags)) - { - REPORT_ERROR0(VLDTR_E_FMD_PINVOKENOTSTATIC); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // must have either ImplMap or RVA == 0 - if (InvalidRid(iRecord)) - { - if(pRecord->GetRVA()==0) - { - REPORT_ERROR0(VLDTR_E_FMD_MARKEDNOPINVOKE); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - else - { - if(pRecord->GetRVA()!=0) - { - // C++ emits ImplMaps for IJW methods, - // with resolution=ModuleRef with name "" - ImplMapRec *pIMRecord; - mdToken tkModuleRef; - IfFailGo(pMiniMd->GetImplMapRecord(iRecord, &pIMRecord)); - tkModuleRef = pMiniMd->getImportScopeOfImplMap(pIMRecord); - if((TypeFromToken(tkModuleRef) == mdtModuleRef) && (!IsNilToken(tkModuleRef))) - { - ModuleRefRec *pMRRecord; // ModuleRef record. - LPCUTF8 szMRName; // ModuleRef name. - // Get the ModuleRef record. - IfFailGo(pMiniMd->GetModuleRefRecord(RidFromToken(tkModuleRef), &pMRRecord)); - // Check ModuleRef name is "". - IfFailGo(pMiniMd->getNameOfModuleRef(pMRRecord, &szMRName)); - if (*szMRName) - { - REPORT_ERROR0(VLDTR_E_MD_RVAANDIMPLMAP); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - } - else - { - hr = ValidateImplMap(iRecord); - if(hr != S_OK) - { - REPORT_ERROR0(VLDTR_E_FMD_BADIMPLMAP); - SetVldtrCode(&hrSave, VLDTR_S_WRN); - } - } - } - - } - else - { - // must have no ImplMap - if (!InvalidRid(iRecord)) - { - REPORT_ERROR0(VLDTR_E_FMD_PINVOKENOTMARKED); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - } - // Validate params - { - ULONG ridStart = pMiniMd->getParamListOfMethod(pRecord); - ULONG ridEnd; - IfFailGo(pMiniMd->getEndParamListOfMethod(rid, &ridEnd)); - ParamRec* pRec; - ULONG cbSigT; - PCCOR_SIGNATURE typePtr; - IfFailGo(pMiniMd->getSignatureOfMethod(pRecord, &typePtr, &cbSigT)); - unsigned callConv = CorSigUncompressData(typePtr); // get the calling convention out of the way - unsigned numTyArgs = 0; - if (callConv & IMAGE_CEE_CS_CALLCONV_GENERIC) - { - bIsGeneric = TRUE; - numTyArgs = CorSigUncompressData(typePtr); - } - - unsigned numArgs = CorSigUncompressData(typePtr); - USHORT usPrevSeq = 0; - - for(ULONG ridP = ridStart; ridP < ridEnd; ridP++) - { - RID tempRid; - IfFailGo(pMiniMd->GetParamRecord(ridP, &pRec)); - // Sequence order must be ascending - if(ridP > ridStart) - { - if(pRec->GetSequence() <= usPrevSeq) - { - REPORT_ERROR2(VLDTR_E_MD_PARAMOUTOFSEQ, ridP-ridStart,pRec->GetSequence()); - SetVldtrCode(&hrSave, VLDTR_S_WRN); - } - } - usPrevSeq = pRec->GetSequence(); - // Sequence value must not exceed num of arguments - if(usPrevSeq > numArgs) - { - REPORT_ERROR2(VLDTR_E_MD_PARASEQTOOBIG, ridP-ridStart,usPrevSeq); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - // Param having marshaling must be marked pdHasFieldMarshal and vice versa - IfFailGo(pMiniMd->FindFieldMarshalHelper(TokenFromRid(ridP,mdtParamDef), &tempRid)); - if (InvalidRid(tempRid) == (IsPdHasFieldMarshal(pRec->GetFlags()) != 0)) - { - REPORT_ERROR1(IsPdHasFieldMarshal(pRec->GetFlags()) ? VLDTR_E_MD_PARMMARKEDNOMARSHAL - : VLDTR_E_MD_PARMMARSHALNOTMARKED, ridP-ridStart); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // Param having const value must be marked pdHasDefault and vice versa - IfFailGo(pMiniMd->FindConstantHelper(TokenFromRid(ridP,mdtParamDef), &tempRid)); - if (InvalidRid(tempRid) == (IsPdHasDefault(pRec->GetFlags()) != 0)) - { - REPORT_ERROR1(IsPdHasDefault(pRec->GetFlags()) ? VLDTR_E_MD_PARMMARKEDNODEFLT - : VLDTR_E_MD_PARMDEFLTNOTMARKED, ridP-ridStart); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - } - - // Generic Method related checks - if (bIsGeneric) - { - if (bIsCctor) - { - REPORT_ERROR0(VLDTR_E_MD_GENERIC_CCTOR); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - if (bIsCtor) - { - REPORT_ERROR0(VLDTR_E_MD_GENERIC_CTOR); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - if (bIsParentImport) - { - REPORT_ERROR0(VLDTR_E_MD_GENERIC_IMPORT); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - } - - hr = hrSave; -ErrExit: - ; - END_ENTRYPOINT_NOTHROW; - - return hr; -} // RegMeta::ValidateMethod() -#ifdef _PREFAST_ -#pragma warning(pop) -#endif - -//***************************************************************************** -// Validate the given ParamPtr. -//***************************************************************************** -HRESULT RegMeta::ValidateParamPtr(RID rid) -{ - return S_OK; -} // RegMeta::ValidateParamPtr() - -//***************************************************************************** -// Validate the given Param. -//***************************************************************************** -HRESULT RegMeta::ValidateParam(RID rid) -{ - CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); // MiniMd of the scope. - ParamRec *pRecord; // Param record - VEContext veCtxt; // Context record. - HRESULT hr = S_OK; // Value returned. - HRESULT hrSave = S_OK; // Save state. - LPCSTR szName; // Param name. - - BEGIN_ENTRYPOINT_NOTHROW; - - memset(&veCtxt, 0, sizeof(VEContext)); - - // Get the InterfaceImpl record. - veCtxt.Token = TokenFromRid(rid, mdtParamDef); - veCtxt.uOffset = 0; - - DWORD dwBadFlags = 0; - DWORD dwFlags = 0; - IfFailGo(pMiniMd->GetParamRecord(rid, &pRecord)); - // Name, if any, must not exceed MAX_CLASSNAME_LENGTH - IfFailGo(pMiniMd->getNameOfParam(pRecord, &szName)); - ULONG L = (ULONG)strlen(szName); - if(L >= MAX_CLASSNAME_LENGTH) - { - REPORT_ERROR2(VLDTR_E_TD_NAMETOOLONG, L, (ULONG)(MAX_CLASSNAME_LENGTH-1)); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - // Flags must be as defined in CorHdr.h - dwBadFlags = ~(pdIn | pdOut | pdOptional | pdHasDefault | pdHasFieldMarshal); - dwFlags = pRecord->GetFlags(); - if(dwFlags & dwBadFlags) - { - REPORT_ERROR1(VLDTR_E_PD_BADFLAGS, dwFlags); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - hr = hrSave; -ErrExit: - ; - END_ENTRYPOINT_NOTHROW; - - return hr; -} // RegMeta::ValidateParam() - -//***************************************************************************** -// Helper function for ValidateInterfaceImpl -//***************************************************************************** -int IsMethodImplementedByClass(CMiniMdRW *pMiniMd, - mdToken tkMethod, - LPCUTF8 szName, - PCCOR_SIGNATURE pSig, - ULONG cbSig, - mdToken tkClass) -{ - HRESULT hr; - int numImpl = 0; - if(TypeFromToken(tkMethod) == mdtMethodDef) - { - if(TypeFromToken(tkClass) == mdtTypeSpec) - { - // We are trying to find out if an interface method is implemented in the generic class tkClass. - // Simple signature comparison doesn't work here, because "int Method()" in the interface might - // be implemented by "T Type.Method()" in the generic type. - // Therefore we assume it is implemented. Atlernatively we could implement better signature - // comparison which would match T with any other type, etc. - numImpl = 1; - } - else if(TypeFromToken(tkClass) == mdtTypeDef) - { - TypeDefRec *pClass; - IfFailRet(pMiniMd->GetTypeDefRecord(RidFromToken(tkClass), &pClass)); - RID ridClsStart = pMiniMd->getMethodListOfTypeDef(pClass); - RID ridClsEnd; - IfFailRet(pMiniMd->getEndMethodListOfTypeDef(RidFromToken(tkClass), &ridClsEnd)); - mdMethodDef tkFoundMethod = 0; - DWORD dwFoundMethodFlags = 0; - // Check among methods - hr = ImportHelper::FindMethod(pMiniMd, tkClass, szName, pSig, cbSig, &tkFoundMethod, 0); - if(SUCCEEDED(hr)) - { - MethodRec * pMethod; - IfFailRet(pMiniMd->GetMethodRecord(RidFromToken(tkFoundMethod), &pMethod)); - if(pMethod) - { - dwFoundMethodFlags = pMiniMd->getFlagsOfMethod(pMethod); - if(IsMdVirtual(dwFoundMethodFlags)) //&&!IsMdNewSlot(dwFoundMethodFlags)) - numImpl = 1; - } - } - if (numImpl==0) //if(hr == CLDB_E_RECORD_NOTFOUND) - { // Check among MethodImpls - RID ridImpl; - for(RID idxCls = ridClsStart; idxCls < ridClsEnd; idxCls++) - { - RID ridCls; - IfFailRet(pMiniMd->GetMethodRid(idxCls, &ridCls)); - - hr = ImportHelper::FindMethodImpl(pMiniMd,tkClass,TokenFromRid(ridCls,mdtMethodDef), - tkMethod,&ridImpl); - if(hr != CLDB_E_RECORD_NOTFOUND) - { - if(SUCCEEDED(hr)) numImpl++; - break; - } - } - if(numImpl == 0) - { - // Check if parent class implements this method - mdToken tkParent = pMiniMd->getExtendsOfTypeDef(pClass); - if(RidFromToken(tkParent)) - numImpl = IsMethodImplementedByClass(pMiniMd,tkMethod,szName,pSig,cbSig,tkParent); - } - } - } - else if (TypeFromToken(tkClass) == mdtTypeRef) - { - TypeRefRec *pRecord; // TypeRef record. - LPCSTR szTRNamespace; // TypeRef Namespace. - LPCSTR szTRName; // TypeRef Name. - - // Get the TypeRef record. - IfFailRet(pMiniMd->GetTypeRefRecord(RidFromToken(tkClass), &pRecord)); - - // Check name is not NULL. - IfFailRet(pMiniMd->getNamespaceOfTypeRef(pRecord, &szTRNamespace)); - IfFailRet(pMiniMd->getNameOfTypeRef(pRecord, &szTRName)); - - mdToken tkRefScope = pMiniMd->getResolutionScopeOfTypeRef(pRecord); - if (tkRefScope == TokenFromRid(1, mdtModule)) - { - // if the typeref is referring to a type in this module then - // we should check the type definition it is referring to - mdTypeDef tkTypeDef; - hr = ImportHelper::FindTypeDefByName(pMiniMd, szTRNamespace, szTRName, tkRefScope, &tkTypeDef); - if (SUCCEEDED(hr)) - numImpl = IsMethodImplementedByClass(pMiniMd, tkMethod, szName, pSig, cbSig, tkTypeDef); - } - else if ((strcmp(szTRNamespace, BASE_NAMESPACE) == 0) && - ((strcmp(szTRName, BASE_OBJECT_CLASSNAME) == 0) || - (strcmp(szTRName, BASE_VTYPE_CLASSNAME) == 0) || - (strcmp(szTRName, BASE_ENUM_CLASSNAME) == 0))) - { - if (((strcmp(szName, SYSTEM_OBJECT_TOSTRING_METHODNAME) == 0) && - (cbSig == _countof(g_sigSystemObject_ToString)) && - (memcmp(pSig, g_sigSystemObject_ToString, cbSig) == 0)) || - ((strcmp(szName, SYSTEM_OBJECT_GETHASHCODE_METHODNAME) == 0) && - (cbSig == _countof(g_sigSystemObject_GetHashCode)) && - (memcmp(pSig, g_sigSystemObject_GetHashCode, cbSig) == 0)) || - ((strcmp(szName, SYSTEM_OBJECT_EQUALS_METHODNAME) == 0) && - (cbSig == _countof(g_sigSystemObject_Equals)) && - (memcmp(pSig, g_sigSystemObject_Equals, cbSig) == 0))) - { - numImpl = 1; // Method signature matches one of System.Object's virtual methods - } - else - { - numImpl = 0; // These classes (System.Object, System.ValueType and System.Enum) don't implement any other virtual methods - } - } - else - { - numImpl = -1; // The method is defined in another module, we cannot verify it (no external modules are loaded) - } - } - } - return numImpl; -} - -//***************************************************************************** -// Validate the given InterfaceImpl. -//***************************************************************************** -//@todo GENERICS: complete logic for type specs -// - for now, we just allow them, but we should be checking more properties -HRESULT RegMeta::ValidateInterfaceImpl(RID rid) -{ - CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); // MiniMd of the scope. - InterfaceImplRec *pRecord; // InterfaceImpl record. - mdTypeDef tkClass; // Class implementing the interface. - mdToken tkInterface; // TypeDef for the interface. - mdInterfaceImpl tkInterfaceImpl; // Duplicate InterfaceImpl. - VEContext veCtxt; // Context record. - HRESULT hr = S_OK; // Value returned. - HRESULT hrSave = S_OK; // Save state. - BOOL fCheckTheMethods=TRUE; - - BEGIN_ENTRYPOINT_NOTHROW; - - memset(&veCtxt, 0, sizeof(VEContext)); - - // Get the InterfaceImpl record. - veCtxt.Token = TokenFromRid(rid, mdtInterfaceImpl); - veCtxt.uOffset = 0; - - IfFailGo(pMiniMd->GetInterfaceImplRecord(rid, &pRecord)); - - // Get implementing Class and the TypeDef for the interface. - tkClass = pMiniMd->getClassOfInterfaceImpl(pRecord); - - // No validation needs to be done on deleted records. - if (IsNilToken(tkClass)) - goto ErrExit; - - tkInterface = pMiniMd->getInterfaceOfInterfaceImpl(pRecord); - - // Validate that the Class is TypeDef. - if((!IsValidToken(tkClass))||(TypeFromToken(tkClass) != mdtTypeDef)/*&&(TypeFromToken(tkClass) != mdtTypeRef)*/) - { - REPORT_ERROR1(VLDTR_E_IFACE_BADIMPL, tkClass); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - fCheckTheMethods = FALSE; - } - // Validate that the Interface is TypeDef or TypeRef or TypeSpec - if((!IsValidToken(tkInterface))||(TypeFromToken(tkInterface) != mdtTypeDef)&&(TypeFromToken(tkInterface) != mdtTypeRef) - &&(TypeFromToken(tkInterface) != mdtTypeSpec)) - { - REPORT_ERROR1(VLDTR_E_IFACE_BADIFACE, tkInterface); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - fCheckTheMethods = FALSE; - } - // Validate that Interface is marked tdInterface. - else if(TypeFromToken(tkInterface) == mdtTypeDef) - { - TypeDefRec *pTDRec; - IfFailGo(pMiniMd->GetTypeDefRecord(RidFromToken(tkInterface), &pTDRec)); - if(!IsTdInterface(pTDRec->GetFlags())) - { - REPORT_ERROR1(VLDTR_E_IFACE_NOTIFACE, tkInterface); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - } - - // Look for duplicates. - hr = ImportHelper::FindInterfaceImpl(pMiniMd, tkClass, tkInterface, - &tkInterfaceImpl, rid); - if (hr == S_OK) - { - REPORT_ERROR1(VLDTR_E_IFACE_DUP, tkInterfaceImpl); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else if (hr == CLDB_E_RECORD_NOTFOUND) - hr = S_OK; - else - IfFailGo(hr); - - // Validate that the Class (if not interface or abstract) implements all the methods of Interface - if((TypeFromToken(tkInterface) == mdtTypeDef) && fCheckTheMethods && (tkInterface != tkClass)) - { - TypeDefRec *pClass; - IfFailGo(pMiniMd->GetTypeDefRecord(RidFromToken(tkClass), &pClass)); - if(!(IsTdAbstract(pClass->GetFlags()) - ||IsTdImport(pClass->GetFlags()) - ||IsTdInterface(pClass->GetFlags()))) - { - TypeDefRec *pInterface; - IfFailGo(pMiniMd->GetTypeDefRecord(RidFromToken(tkInterface), &pInterface)); - RID ridIntStart = pMiniMd->getMethodListOfTypeDef(pInterface); - RID ridIntEnd; - IfFailGo(pMiniMd->getEndMethodListOfTypeDef(RidFromToken(tkInterface), &ridIntEnd)); - MethodRec* pIntMethod; - for(RID idxInt = ridIntStart; idxInt < ridIntEnd; idxInt++) - { - RID ridInt; - IfFailGo(pMiniMd->GetMethodRid(idxInt, &ridInt)); - IfFailGo(pMiniMd->GetMethodRecord(ridInt, &pIntMethod)); - const char* szName; - IfFailGo(pMiniMd->getNameOfMethod(pIntMethod, &szName)); - if(!IsMdStatic(pIntMethod->GetFlags()) - && !IsDeletedName(szName) - && !IsVtblGapName(szName)) - { - ULONG cbSig; - PCCOR_SIGNATURE pSig; - IfFailGo(pMiniMd->getSignatureOfMethod(pIntMethod, &pSig, &cbSig)); - if(cbSig) - { - int num = IsMethodImplementedByClass(pMiniMd,TokenFromRid(ridInt,mdtMethodDef),szName,pSig,cbSig,tkClass); - if(num == 0) - { // Error: method not implemented - REPORT_ERROR3(VLDTR_E_IFACE_METHNOTIMPL, tkClass, tkInterface, TokenFromRid(ridInt,mdtMethodDef)); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - if(num == -1) - { - // Traced to a TypeRef, which might implement the method, give warning - REPORT_ERROR3(VLDTR_E_IFACE_METHNOTIMPLTHISMOD, tkClass, tkInterface, TokenFromRid(ridInt,mdtMethodDef)); - SetVldtrCode(&hrSave, VLDTR_S_WRN); - } - if(num > 1) - { // Error: multiple method implementation - REPORT_ERROR3(VLDTR_E_IFACE_METHMULTIMPL, tkClass, tkInterface, TokenFromRid(ridInt,mdtMethodDef)); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - } - } - } - } - hr = hrSave; -ErrExit: - ; - END_ENTRYPOINT_NOTHROW; - - return hr; -} // RegMeta::ValidateInterfaceImpl() - -//***************************************************************************** -// Validate the given GenericParam. -//***************************************************************************** -HRESULT RegMeta::ValidateGenericParam(RID rid) -{ - CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); // MiniMd of the scope. - GenericParamRec *pRecord; // GenericParam record. - LPCSTR szName; // GenericParam name field. - mdToken tkOwner; // GenericParam owner field. - ULONG ulNumber; // GenericParam number field. - DWORD dwFlags; // GenericParam flags field - - VEContext veCtxt; // Context record. - HRESULT hr = S_OK; // Value returned. - HRESULT hrSave = S_OK; // Save state. - - BEGIN_ENTRYPOINT_NOTHROW; - - memset(&veCtxt, 0, sizeof(VEContext)); - - // Get the GenericParam record. - veCtxt.Token = TokenFromRid(rid, mdtGenericParam); - veCtxt.uOffset = 0; - IfFailGo(pMiniMd->GetGenericParamRecord(rid, &pRecord)); - - // 1. GenericParam may contain zero or more rows. - // (Nothing to check.) - - tkOwner = pMiniMd->getOwnerOfGenericParam(pRecord); - // 2. Owner must be a valid token and a type def or method def - // (Already checked by ValidateRecord) - - // CLR tolerates Nil owners, ECMA does not - if(IsNilToken(tkOwner)) - { - REPORT_ERROR0(VLDTR_E_GP_OWNERNIL); - SetVldtrCode(&hrSave, VLDTR_S_WRN); - } - - //3. Every generic type shall own one row in the Generic Param table for each of its type parameters. [ERROR] - // (Nothing to check, as the arity of a generic type is, by definition, the number of generic param entries). - - //4. Every generic method shall own one row in the Generic Param table for each of its type parameters. [ERROR] - // (This is checked in ValidateMethodSig, error VLDTR_E_MD_GPMISMATCH). - - ulNumber = pMiniMd->getNumberOfGenericParam(pRecord); - - // 5. Flags must be valid - { - DWORD dwInvalidMask, dwExtraBits; - - dwFlags = pMiniMd->getFlagsOfGenericParam(pRecord); - - - // check for extra bits - dwInvalidMask = (DWORD)~(gpVarianceMask|gpSpecialConstraintMask); - dwExtraBits = dwFlags & dwInvalidMask; - if(dwExtraBits) - { - //@GENERICS: we could use a custom error, - // but this is one is already used in more than one context. - REPORT_ERROR1(VLDTR_E_TD_EXTRAFLAGS, dwExtraBits); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - //Check Variance - { - DWORD dwVariance = dwFlags & gpVarianceMask; - switch (dwVariance) - { - case gpNonVariant: - // always ok - break; - case gpCovariant: - case gpContravariant: - if (TypeFromToken(tkOwner)==mdtTypeDef) - { - if (IsNilToken(tkOwner)) - break; - TypeDefRec *pTypeDefRec; - IfFailGo(pMiniMd->GetTypeDefRecord(RidFromToken(tkOwner), &pTypeDefRec)); - // co-contra variance only legal on interfaces and delegates - // If owner is not an interface and does not extend MultiCastDelegate, report an error - if(!IsTdInterface(pTypeDefRec->GetFlags())) - { - // Get the parent of the TypeDef. - mdToken tkExtends = pMiniMd->getExtendsOfTypeDef(pTypeDefRec); - LPCSTR szExtName = NULL; // Parent Name. - LPCSTR szExtNameSpace = NULL; // Parent NameSpace. - BOOL bExtendsMCDelegate = FALSE; - - // Determine if the parent is MCDelegate - if (TypeFromToken(tkExtends) != mdtTypeSpec) - { - if (TypeFromToken(tkExtends) == mdtTypeRef) - { - TypeRefRec *pExtTypeRefRec; - IfFailGo(pMiniMd->GetTypeRefRecord(RidFromToken(tkExtends), &pExtTypeRefRec)); - mdToken tkResScope = pMiniMd->getResolutionScopeOfTypeRef(pExtTypeRefRec); - if (RidFromToken(tkResScope) && (TypeFromToken(tkResScope) == mdtAssemblyRef)) - { - AssemblyRefRec * pARRec; - IfFailGo(pMiniMd->GetAssemblyRefRecord(RidFromToken(tkResScope), &pARRec)); - LPCSTR szAssemblyRefName; - IfFailGo(pMiniMd->getNameOfAssemblyRef(pARRec, &szAssemblyRefName)); - if ((0 == SString::_stricmp("mscorlib", szAssemblyRefName)) || (0 == SString::_stricmp("System.Runtime", szAssemblyRefName))) - // otherwise don't even bother extracting the name - { - IfFailGo(pMiniMd->getNameOfTypeRef(pExtTypeRefRec, &szExtName)); - IfFailGo(pMiniMd->getNamespaceOfTypeRef(pExtTypeRefRec, &szExtNameSpace)); - } - } - } - else if (TypeFromToken(tkExtends) == mdtTypeDef) - { - if (g_fValidatingMscorlib) // otherwise don't even bother extracting the name - { - TypeDefRec * pExtTypeRefRec; - IfFailGo(pMiniMd->GetTypeDefRecord(RidFromToken(tkExtends), &pExtTypeRefRec)); - IfFailGo(pMiniMd->getNameOfTypeDef(pExtTypeRefRec, &szExtName)); - IfFailGo(pMiniMd->getNamespaceOfTypeDef(pExtTypeRefRec, &szExtNameSpace)); - } - } - - bExtendsMCDelegate = - szExtNameSpace && szExtName && - (0 == strcmp(szExtNameSpace,BASE_NAMESPACE)) && - (0 == strcmp(szExtName,BASE_MCDELEGATE_CLASSNAME)); - } - - // Report any error - if (!bExtendsMCDelegate) - { - REPORT_ERROR1(VLDTR_E_GP_UNEXPECTED_OWNER_FOR_VARIANT_VAR,tkOwner); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - } - else - { - // co-contra variance never legal on MVARs - REPORT_ERROR0(VLDTR_E_GP_ILLEGAL_VARIANT_MVAR); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - break; - default: - REPORT_ERROR1(VLDTR_E_GP_ILLEGAL_VARIANCE_FLAGS,dwFlags); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - break; - } - } - - // Check special constraints - { - DWORD dwSpecialConstraints = dwFlags & gpSpecialConstraintMask; - // It is illegal go declare both gpNotNullableValueTypeConstraint - // and gpReferenceTypeConstraint, but gpDefaultConstructorConstraint - // is legal with either (or neither). - if ((dwSpecialConstraints & (gpReferenceTypeConstraint | gpNotNullableValueTypeConstraint)) == - (gpReferenceTypeConstraint | gpNotNullableValueTypeConstraint)) - { - REPORT_ERROR1(VLDTR_E_GP_REFANDVALUETYPE,dwFlags); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - } - - // 6. Number shall have a value >=0 and < number of type parameters in owner type or method. - // 7. Successive rows of the GenericParam table that are owned by the same method (sic) (owner?) shall - // be ordered by increasing Number value; there can be no gaps in the Number sequence. - { - if(ulNumber>0) - { if(rid==1) - { - REPORT_ERROR0(VLDTR_E_GP_NONSEQ_BY_NUMBER); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else - { - GenericParamRec *pPredRecord; - IfFailGo(pMiniMd->GetGenericParamRecord(rid-1, &pPredRecord)); - mdToken tkPredOwner = pMiniMd->getOwnerOfGenericParam(pPredRecord); - ULONG ulPredNumber = pMiniMd->getNumberOfGenericParam(pPredRecord); - if (tkPredOwner != tkOwner) - { - REPORT_ERROR0(VLDTR_E_GP_NONSEQ_BY_OWNER); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - if (ulPredNumber != ulNumber-1) - { - REPORT_ERROR0(VLDTR_E_GP_NONSEQ_BY_NUMBER); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - } - } - - // 8. Name must be non-null and not too long - IfFailGo(pMiniMd->getNameOfGenericParam(pRecord, &szName)); - if (!*szName) - { - // name is NULL. - REPORT_ERROR0(VLDTR_E_GP_NAMENULL); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else - { - if(!strcmp(szName,COR_DELETED_NAME_A)) goto ErrExit; //@GENERICS: do we allow parameters to be deleted? - ULONG L = (ULONG)strlen(szName); - if(L >= MAX_CLASSNAME_LENGTH) - { - REPORT_ERROR2(VLDTR_E_TD_NAMETOOLONG, L, (ULONG)(MAX_CLASSNAME_LENGTH-1)); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - -#ifdef THIS_RULE_IS_DISABLED_BECAUSE_CSHARP_EMITS_DUP_NAMES_AND_DOESNT_WANT_TO_STOP - // 9. There shall be no duplicates based upon Owner and Name - if (szName) - { - mdGenericParam tkDupGenericParam; - hr = ImportHelper::FindGenericParamByOwner(pMiniMd, tkOwner, szName, NULL, &tkDupGenericParam, rid); - if (hr == S_OK) - { - REPORT_ERROR1(VLDTR_E_GP_DUPNAME, tkDupGenericParam); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else if (hr == CLDB_E_RECORD_NOTFOUND) - hr = S_OK; - else - IfFailGo(hr); - } -#endif - - // 10. There shall be no duplicates based upon Owner and Number - { - mdGenericParam tkDupGenericParam; - hr = ImportHelper::FindGenericParamByOwner(pMiniMd, tkOwner, NULL, &ulNumber, &tkDupGenericParam, rid); - if (hr == S_OK) - { - REPORT_ERROR1(VLDTR_E_GP_DUPNUMBER, tkDupGenericParam); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else if (hr == CLDB_E_RECORD_NOTFOUND) - hr = S_OK; - else - IfFailGo(hr); - } - - hr = hrSave; - -ErrExit: - ; - END_ENTRYPOINT_NOTHROW; - - return hr; -} // RegMeta::ValidateGenericParam() - -//***************************************************************************** -// Validate the given MemberRef. -//***************************************************************************** -HRESULT RegMeta::ValidateMemberRef(RID rid) -{ - CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); // MiniMd of the scope. - MemberRefRec *pRecord; // MemberRef record. - mdMemberRef tkMemberRef; // Duplicate MemberRef. - mdToken tkClass; // MemberRef parent. - LPCSTR szName; // MemberRef name. - PCCOR_SIGNATURE pbSig; // MemberRef signature. - PCCOR_SIGNATURE pbSigTmp; // Temp copy of pbSig, so that can be changed. - ULONG cbSig; // Size of sig in bytes. - VEContext veCtxt; // Context record. - HRESULT hr = S_OK; // Value returned. - HRESULT hrSave = S_OK; // Save state. - - BEGIN_ENTRYPOINT_NOTHROW; - - memset(&veCtxt, 0, sizeof(VEContext)); - - // Get the MemberRef record. - veCtxt.Token = TokenFromRid(rid, mdtMemberRef); - veCtxt.uOffset = 0; - - IfFailGo(pMiniMd->GetMemberRefRecord(rid, &pRecord)); - - // Do checks for name validity. - IfFailGo(pMiniMd->getNameOfMemberRef(pRecord, &szName)); - if (!*szName) - { - REPORT_ERROR0(VLDTR_E_MR_NAMENULL); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else - { - if (IsVtblGapName(szName)) - { - REPORT_ERROR0(VLDTR_E_MR_VTBLNAME); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else if (IsDeletedName(szName)) - { - REPORT_ERROR0(VLDTR_E_MR_DELNAME); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - ULONG L = (ULONG)strlen(szName); - if(L >= MAX_CLASSNAME_LENGTH) - { - // Name too long - REPORT_ERROR2(VLDTR_E_TD_NAMETOOLONG, L, (ULONG)(MAX_CLASSNAME_LENGTH-1)); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - - // MemberRef parent should never be nil in a PE file. - tkClass = pMiniMd->getClassOfMemberRef(pRecord); - if (m_ModuleType == ValidatorModuleTypePE && IsNilToken(tkClass)) - { - REPORT_ERROR0(VLDTR_E_MR_PARNIL); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - // Verify that the signature is a valid signature as per signature spec. - IfFailGo(pMiniMd->getSignatureOfMemberRef(pRecord, &pbSig, &cbSig)); - - // Do some semantic checks based on the signature. - if (hr == S_OK) - { - ULONG ulCallingConv; - ULONG ulArgCount; - ULONG ulTyArgCount = 0; - ULONG ulCurByte = 0; - - // Extract calling convention. - pbSigTmp = pbSig; - ulCurByte += CorSigUncompressedDataSize(pbSigTmp); - ulCallingConv = CorSigUncompressData(pbSigTmp); - - // Get the type argument count - if (ulCallingConv & IMAGE_CEE_CS_CALLCONV_GENERIC) - { - ulCurByte += CorSigUncompressedDataSize(pbSigTmp); - ulTyArgCount = CorSigUncompressData(pbSigTmp); - } - - // Get the argument count. - ulCurByte += CorSigUncompressedDataSize(pbSigTmp); - ulArgCount = CorSigUncompressData(pbSigTmp); - - // Calling convention must be one of IMAGE_CEE_CS_CALLCONV_DEFAULT, - // IMAGE_CEE_CS_CALLCONV_VARARG or IMAGE_CEE_CS_CALLCONV_FIELD. - if (!isCallConv(ulCallingConv, IMAGE_CEE_CS_CALLCONV_DEFAULT) && - !isCallConv(ulCallingConv, IMAGE_CEE_CS_CALLCONV_VARARG) && - !isCallConv(ulCallingConv, IMAGE_CEE_CS_CALLCONV_FIELD)) - { - REPORT_ERROR1(VLDTR_E_MR_BADCALLINGCONV, ulCallingConv); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // [CLS] Calling convention must not be VARARG - if(isCallConv(ulCallingConv, IMAGE_CEE_CS_CALLCONV_VARARG)) - { - REPORT_ERROR0(VLDTR_E_MR_VARARGCALLINGCONV); - SetVldtrCode(&hrSave, VLDTR_S_WRN); - } - - // If the parent is a MethodDef... - if (TypeFromToken(tkClass) == mdtMethodDef) - { - if (RidFromToken(tkClass) != 0) - { - // The MethodDef must be the same name and the fixed part of the - // vararg signature must be the same. - MethodRec *pMethodRecord; // Method Record. - LPCSTR szMethodName; // Method name. - PCCOR_SIGNATURE pbMethodSig; // Method signature. - ULONG cbMethodSig; // Size in bytes of signature. - - // Get Method record, name and signature. - IfFailGo(pMiniMd->GetMethodRecord(RidFromToken(tkClass), &pMethodRecord)); - IfFailGo(pMiniMd->getNameOfMethod(pMethodRecord, &szMethodName)); - IfFailGo(pMiniMd->getSignatureOfMethod(pMethodRecord, &pbMethodSig, &cbMethodSig)); - - // Verify that the name of the Method is the same as the MemberRef. - if (strcmp(szName, szMethodName)) - { - REPORT_ERROR1(VLDTR_E_MR_NAMEDIFF, tkClass); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - if (isCallConv(ulCallingConv, IMAGE_CEE_CS_CALLCONV_VARARG)) - { // It's VARARG calling convention - CQuickBytes qbFixedSig; // Quick bytes to hold the fixed part of the variable signature. - ULONG cbFixedSig; // Size in bytes of the fixed part. - - // Get the fixed part of the vararg signature of the MemberRef. - hr = _GetFixedSigOfVarArg(pbSig, cbSig, &qbFixedSig, &cbFixedSig); - if (FAILED(hr) || cbFixedSig != cbMethodSig || - memcmp(pbMethodSig, qbFixedSig.Ptr(), cbFixedSig)) - { - UnifiedAssemblySigComparer uasc(*this); - MDSigComparer sc(MDSigParser(pbMethodSig, cbMethodSig), - MDSigParser((PCCOR_SIGNATURE)qbFixedSig.Ptr(), cbFixedSig), - uasc); - - hr = sc.CompareMethodSignature(); - if (FAILED(hr)) - { - hr = S_OK; - REPORT_ERROR1(VLDTR_E_MR_SIGDIFF, tkClass); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - } - else - { // It's not VARARG calling convention - a MemberRef is referencing MethodDef (part of - // NoPIA) - UnifiedAssemblySigComparer uasc(*this); - MDSigComparer sc(MDSigParser(pbMethodSig, cbMethodSig), - MDSigParser(pbSig, cbSig), - uasc); - - // Compare signatures - hr = sc.CompareMethodSignature(); - if (FAILED(hr)) - { - hr = S_OK; - REPORT_ERROR1(VLDTR_E_MR_SIGDIFF, tkClass); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - } - } - - // There should be no duplicate MemberRefs. - if (*szName && pbSig && cbSig) - { - hr = ImportHelper::FindMemberRef(pMiniMd, tkClass, szName, pbSig, - cbSig, &tkMemberRef, rid, - ImportHelper::CreateHash); // Optimize for multiple calls - if (hr == S_OK) - { - REPORT_ERROR1(VLDTR_E_MR_DUP, tkMemberRef); - SetVldtrCode(&hrSave, VLDTR_S_WRN); - } - else if (hr == CLDB_E_RECORD_NOTFOUND) - { - hr = S_OK; - } - else - { - IfFailGo(hr); - } - } - - if (!isCallConv(ulCallingConv, IMAGE_CEE_CS_CALLCONV_FIELD)) - { - hr = ValidateMethodSig(veCtxt.Token,pbSig, cbSig,0); - SetVldtrCode(&hrSave,hr); - } - } - hr = hrSave; -ErrExit: - ; - END_ENTRYPOINT_NOTHROW; - - return hr; -} // RegMeta::ValidateMemberRef() - -//***************************************************************************** -// Validate the given Constant. -//***************************************************************************** -HRESULT RegMeta::ValidateConstant(RID rid) -{ - CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); // MiniMd of the scope. - ConstantRec *pRecord; // Constant record. - mdToken tkParent; // Constant parent. - const VOID* pbBlob; // Constant value blob ptr - DWORD cbBlob; // Constant value blob size - VEContext veCtxt; // Context record. - HRESULT hr = S_OK; // Value returned. - HRESULT hrSave = S_OK; // Save state. - - BEGIN_ENTRYPOINT_NOTHROW; - - memset(&veCtxt, 0, sizeof(VEContext)); - - // Get the MemberRef record. - veCtxt.Token = rid; - veCtxt.uOffset = 0; - - ULONG maxrid = 0; - ULONG typ = 0; - IfFailGo(pMiniMd->GetConstantRecord(rid, &pRecord)); - IfFailGo(pMiniMd->getValueOfConstant(pRecord, (const BYTE **)&pbBlob, &cbBlob)); - switch(pRecord->GetType()) - { - case ELEMENT_TYPE_BOOLEAN: - case ELEMENT_TYPE_CHAR: - case ELEMENT_TYPE_I1: - case ELEMENT_TYPE_U1: - case ELEMENT_TYPE_I2: - case ELEMENT_TYPE_U2: - case ELEMENT_TYPE_I4: - case ELEMENT_TYPE_U4: - case ELEMENT_TYPE_R4: - case ELEMENT_TYPE_I8: - case ELEMENT_TYPE_U8: - case ELEMENT_TYPE_R8: - if(pbBlob == NULL) - { - REPORT_ERROR1(VLDTR_E_CN_BLOBNULL, pRecord->GetType()); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - case ELEMENT_TYPE_STRING: - break; - - case ELEMENT_TYPE_CLASS: - if(GET_UNALIGNED_32(pbBlob) != 0) - { - REPORT_ERROR1(VLDTR_E_CN_BLOBNOTNULL, pRecord->GetType()); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - break; - - default: - REPORT_ERROR1(VLDTR_E_CN_BADTYPE, pRecord->GetType()); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - break; - } - tkParent = pMiniMd->getParentOfConstant(pRecord); - typ = TypeFromToken(tkParent); - switch(typ) - { - case mdtFieldDef: - maxrid = pMiniMd->getCountFields(); - break; - case mdtParamDef: - maxrid = pMiniMd->getCountParams(); - break; - case mdtProperty: - maxrid = pMiniMd->getCountPropertys(); - break; - } - switch(typ) - { - case mdtFieldDef: - case mdtParamDef: - case mdtProperty: - { - ULONG rid_p = RidFromToken(tkParent); - if((0==rid_p)||(rid_p > maxrid)) - { - REPORT_ERROR1(VLDTR_E_CN_PARENTRANGE, tkParent); - SetVldtrCode(&hrSave, VLDTR_S_WRN); - } - break; - } - - default: - REPORT_ERROR1(VLDTR_E_CN_PARENTTYPE, tkParent); - SetVldtrCode(&hrSave, VLDTR_S_WRN); - break; - } - - hr = hrSave; -ErrExit: - ; - END_ENTRYPOINT_NOTHROW; - - return hr; -} // RegMeta::ValidateConstant() - -//***************************************************************************** -// Validate the given CustomAttribute. -//***************************************************************************** -HRESULT RegMeta::ValidateCustomAttribute(RID rid) -{ - CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); // MiniMd of the scope. - VEContext veCtxt; // Context record. - HRESULT hr = S_OK; // Value returned. - HRESULT hrSave = S_OK; // Save state. - - BEGIN_ENTRYPOINT_NOTHROW; - - CustomAttributeRec *pRecord; - IfFailGo(pMiniMd->GetCustomAttributeRecord(rid, &pRecord)); - - memset(&veCtxt, 0, sizeof(VEContext)); - - veCtxt.Token = TokenFromRid(rid,mdtCustomAttribute); - veCtxt.uOffset = 0; - - if (pRecord != NULL) - { - mdToken tkOwner = pMiniMd->getParentOfCustomAttribute(pRecord); - if(RidFromToken(tkOwner)) - { // if 0, it's deleted CA, don't pay attention - mdToken tkCAType = pMiniMd->getTypeOfCustomAttribute(pRecord); - DWORD cbValue=0; - const BYTE *pbValue; - IfFailGo(pMiniMd->getValueOfCustomAttribute(pRecord, &pbValue, &cbValue)); - if((TypeFromToken(tkOwner)==mdtCustomAttribute)||(!IsValidToken(tkOwner))) - { - REPORT_ERROR1(VLDTR_E_CA_BADPARENT, tkOwner); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - if(((TypeFromToken(tkCAType)!=mdtMethodDef)&&(TypeFromToken(tkCAType)!=mdtMemberRef)) - ||(!IsValidToken(tkCAType))||(RidFromToken(tkCAType)==0)) - { - REPORT_ERROR1(VLDTR_E_CA_BADTYPE, tkCAType); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else - { //i.e. Type is valid MethodDef or MemberRef - LPCUTF8 szName; - PCCOR_SIGNATURE pSig=NULL; - DWORD cbSig=0; - DWORD dwFlags=0; - if (TypeFromToken(tkCAType) == mdtMethodDef) - { - MethodRec *pTypeRec; - IfFailGo(pMiniMd->GetMethodRecord(RidFromToken(tkCAType), &pTypeRec)); - IfFailGo(pMiniMd->getNameOfMethod(pTypeRec, &szName)); - IfFailGo(pMiniMd->getSignatureOfMethod(pTypeRec, &pSig, &cbSig)); - dwFlags = pTypeRec->GetFlags(); - } - else // it can be only MemberRef, otherwise we wouldn't be here - { - MemberRefRec *pTypeRec; - IfFailGo(pMiniMd->GetMemberRefRecord(RidFromToken(tkCAType), &pTypeRec)); - IfFailGo(pMiniMd->getNameOfMemberRef(pTypeRec, &szName)); - IfFailGo(pMiniMd->getSignatureOfMemberRef(pTypeRec, &pSig, &cbSig)); - } - if (strcmp(szName, ".ctor") != 0) - { - REPORT_ERROR1(VLDTR_E_CA_NOTCTOR, tkCAType); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - if ((cbSig > 0) && (pSig != NULL)) - { - if(FAILED(ValidateMethodSig(tkCAType, pSig,cbSig,dwFlags)) - || (!((*pSig) & IMAGE_CEE_CS_CALLCONV_HASTHIS))) - { - REPORT_ERROR1(VLDTR_E_CA_BADSIG, tkCAType); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else - { // sig seems to be OK - if ((pbValue != NULL) && (cbValue > 0)) - { - // Check if prolog is OK - WORD pW = *((UNALIGNED WORD*)pbValue); - if(pW != 0x0001) - { - REPORT_ERROR1(VLDTR_E_CA_BADPROLOG, pW); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // Check if blob corresponds to the signature - } - } - - } - else - { - REPORT_ERROR1(VLDTR_E_CA_NOSIG, tkCAType); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } // end if bad Type - else - } // end if RidFromToken(tkOwner) - } // end if pRecord - - hr = hrSave; -ErrExit: - ; - END_ENTRYPOINT_NOTHROW; - - return hr; -} // RegMeta::ValidateCustomAttribute() - -//***************************************************************************** -// Validate the given FieldMarshal. -//***************************************************************************** -HRESULT RegMeta::ValidateFieldMarshal(RID rid) -{ - return S_OK; -} // RegMeta::ValidateFieldMarshal() - -//***************************************************************************** -// Validate the given DeclSecurity. -//***************************************************************************** -HRESULT RegMeta::ValidateDeclSecurity(RID rid) -{ - CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); // MiniMd of the scope. - VEContext veCtxt; // Context record. - HRESULT hr = S_OK; // Value returned. - HRESULT hrSave = S_OK; // Save state. - DeclSecurityRec *pRecord; - mdToken tkOwner; // Owner of the decl security - DWORD dwAction; // action flags - BOOL bIsValidOwner = FALSE; - - BEGIN_ENTRYPOINT_NOTHROW; - - IfFailGo(pMiniMd->GetDeclSecurityRecord(rid, &pRecord)); - - memset(&veCtxt, 0, sizeof(VEContext)); - - veCtxt.Token = TokenFromRid(rid,mdtPermission); - veCtxt.uOffset = 0; - - // Must have a valid owner - tkOwner = pMiniMd->getParentOfDeclSecurity(pRecord); - if(RidFromToken(tkOwner)==0) goto ErrExit; // deleted record, no need to validate - switch(TypeFromToken(tkOwner)) - { - case mdtModule: - case mdtAssembly: - case mdtTypeDef: - case mdtMethodDef: - case mdtFieldDef: - case mdtInterfaceImpl: - bIsValidOwner = IsValidToken(tkOwner); - break; - default: - break; - } - if(!bIsValidOwner) - { - REPORT_ERROR1(VLDTR_E_DS_BADOWNER, tkOwner); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // Must have one and only one flag set - dwAction = pRecord->GetAction() & dclActionMask; - if(dwAction > dclMaximumValue) // the flags are 0,1,2,3,...,dclMaximumValue - { - REPORT_ERROR1(VLDTR_E_DS_BADFLAGS, dwAction); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // If field has DeclSecurity, verify its parent is not an interface.-- checked in ValidateField - // If method has DeclSecurity, verify its parent is not an interface.-- checked in ValidateMethod - - hr = hrSave; -ErrExit: - ; - END_ENTRYPOINT_NOTHROW; - - return hr; -} // RegMeta::ValidateDeclSecurity() - -//***************************************************************************** -// Validate the given ClassLayout. -//***************************************************************************** -HRESULT RegMeta::ValidateClassLayout(RID rid) -{ - CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); // MiniMd of the scope. - ClassLayoutRec *pRecord; // ClassLayout record. - TypeDefRec *pTypeDefRec; // Parent TypeDef record. - DWORD dwPackingSize; // Packing size. - mdTypeDef tkParent; // Parent TypeDef token. - DWORD dwTypeDefFlags; // Parent TypeDef flags. - RID clRid; // Duplicate ClassLayout rid. - VEContext veCtxt; // Context record. - HRESULT hr = S_OK; // Value returned. - HRESULT hrSave = S_OK; // Save state. - - memset(&veCtxt, 0, sizeof(VEContext)); - - BEGIN_ENTRYPOINT_NOTHROW; - - // Extract the record. - veCtxt.Token = rid; - veCtxt.uOffset = 0; - IfFailGo(pMiniMd->GetClassLayoutRecord(rid, &pRecord)); - - // Get the parent, if parent is nil its a deleted record. Skip validation. - tkParent = pMiniMd->getParentOfClassLayout(pRecord); - if (IsNilToken(tkParent)) - goto ErrExit; - - // Parent should not have AutoLayout set on it. - IfFailGo(pMiniMd->GetTypeDefRecord(RidFromToken(tkParent), &pTypeDefRec)); - dwTypeDefFlags = pMiniMd->getFlagsOfTypeDef(pTypeDefRec); - if (IsTdAutoLayout(dwTypeDefFlags)) - { - REPORT_ERROR1(VLDTR_E_CL_TDAUTO, tkParent); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // Parent must not be an Interface - if(IsTdInterface(dwTypeDefFlags)) - { - REPORT_ERROR1(VLDTR_E_CL_TDINTF, tkParent); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - // Validate the PackingSize. - dwPackingSize = pMiniMd->getPackingSizeOfClassLayout(pRecord); - if((dwPackingSize > 128)||((dwPackingSize & (dwPackingSize-1)) !=0 )) - { - REPORT_ERROR2(VLDTR_E_CL_BADPCKSZ, tkParent, dwPackingSize); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - // Validate that there are no duplicates. - hr = _FindClassLayout(pMiniMd, tkParent, &clRid, rid); - if (hr == S_OK) - { - REPORT_ERROR2(VLDTR_E_CL_DUP, tkParent, clRid); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else if (hr == CLDB_E_RECORD_NOTFOUND) - hr = S_OK; - else - IfFailGo(hr); - hr = hrSave; -ErrExit: - ; - END_ENTRYPOINT_NOTHROW; - - return hr; -} // RegMeta::ValidateClassLayout() - -//***************************************************************************** -// Validate the given FieldLayout. -//***************************************************************************** -HRESULT RegMeta::ValidateFieldLayout(RID rid) -{ - CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); // MiniMd of the scope. - FieldLayoutRec *pRecord; // FieldLayout record. - mdFieldDef tkField; // Field token. - ULONG ulOffset; // Field offset. - FieldRec *pFieldRec; // Field record. - TypeDefRec *pTypeDefRec; // Parent TypeDef record. - mdTypeDef tkTypeDef; // Parent TypeDef token. - RID clRid; // Corresponding ClassLayout token. - RID flRid = 0; // Duplicate FieldLayout rid. - DWORD dwTypeDefFlags; // Parent TypeDef flags. - DWORD dwFieldFlags; // Field flags. - VEContext veCtxt; // Context record. - HRESULT hr = S_OK; // Value returned. - HRESULT hrSave = S_OK; // Save state. - - BEGIN_ENTRYPOINT_NOTHROW; - - memset(&veCtxt, 0, sizeof(VEContext)); - - // Extract the record. - veCtxt.Token = rid; - veCtxt.uOffset = 0; - IfFailGo(pMiniMd->GetFieldLayoutRecord(rid, &pRecord)); - - // Get the field, if it's nil it's a deleted record, so just skip it. - tkField = pMiniMd->getFieldOfFieldLayout(pRecord); - if (IsNilToken(tkField)) - goto ErrExit; - - // Validate the Offset value. - ulOffset = pMiniMd->getOffSetOfFieldLayout(pRecord); - if (ulOffset == ULONG_MAX) - { - REPORT_ERROR2(VLDTR_E_FL_BADOFFSET, tkField, ulOffset); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - // Get the parent of the Field. - IfFailGo(pMiniMd->FindParentOfFieldHelper(tkField, &tkTypeDef)); - // Validate that the parent is not nil. - if (IsNilToken(tkTypeDef)) - { - REPORT_ERROR1(VLDTR_E_FL_TDNIL, tkField); - SetVldtrCode(&hr, hrSave); - goto ErrExit; - } - - // Validate that there exists a ClassLayout record associated with - // this TypeDef. - IfFailGo(pMiniMd->FindClassLayoutHelper(tkTypeDef, &clRid)); - if (InvalidRid(rid)) - { - REPORT_ERROR2(VLDTR_E_FL_NOCL, tkField, tkTypeDef); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - // Validate that ExplicitLayout is set on the TypeDef flags. - IfFailGo(pMiniMd->GetTypeDefRecord(RidFromToken(tkTypeDef), &pTypeDefRec)); - dwTypeDefFlags = pMiniMd->getFlagsOfTypeDef(pTypeDefRec); - if (IsTdAutoLayout(dwTypeDefFlags)) - { - REPORT_ERROR2(VLDTR_E_FL_TDNOTEXPLCT, tkField, tkTypeDef); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - // Extract Field record. - IfFailGo(pMiniMd->GetFieldRecord(RidFromToken(tkField), &pFieldRec)); - // Validate that the field is non-static. - dwFieldFlags = pMiniMd->getFlagsOfField(pFieldRec); - if (IsFdStatic(dwFieldFlags)) - { - REPORT_ERROR1(VLDTR_E_FL_FLDSTATIC, tkField); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - // Look for duplicates. - hr = _FindFieldLayout(pMiniMd, tkField, &flRid, rid); - if (hr == S_OK) - { - REPORT_ERROR1(VLDTR_E_FL_DUP, flRid); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else if (hr == CLDB_E_RECORD_NOTFOUND) - hr = S_OK; - else - IfFailGo(hr); - hr = hrSave; -ErrExit: - ; - END_ENTRYPOINT_NOTHROW; - - return hr; -} // RegMeta::ValidateFieldLayout() - -//***************************************************************************** -// Validate the given StandAloneSig. -//***************************************************************************** -HRESULT RegMeta::ValidateStandAloneSig(RID rid) -{ - CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); // MiniMd of the scope. - StandAloneSigRec *pRecord; // FieldLayout record. - PCCOR_SIGNATURE pbSig; // Signature. - ULONG cbSig; // Size in bytes of the signature. - VEContext veCtxt; // Context record. - HRESULT hr = S_OK; // Value returned. - HRESULT hrSave = S_OK; // Save state. - ULONG ulCurByte = 0; // Current index into the signature. - ULONG ulCallConv; // Calling convention. - ULONG ulArgCount; // Count of arguments. - ULONG ulTyArgCount = 0; // Count of type arguments. - ULONG i; // Looping index. - ULONG ulNSentinels = 0; // Number of sentinels in the signature - BOOL bNoVoidAllowed=TRUE; - - BEGIN_ENTRYPOINT_NOTHROW; - - memset(&veCtxt, 0, sizeof(VEContext)); - - // Extract the record. - veCtxt.Token = TokenFromRid(rid,mdtSignature); - veCtxt.uOffset = 0; - IfFailGo(pMiniMd->GetStandAloneSigRecord(rid, &pRecord)); - IfFailGo(pMiniMd->getSignatureOfStandAloneSig(pRecord, &pbSig, &cbSig)); - - // Validate the signature is well-formed with respect to the compression - // scheme. If this fails, no further validation needs to be done. - if ( (hr = ValidateSigCompression(veCtxt.Token, pbSig, cbSig)) != S_OK) - goto ErrExit; - - //_ASSERTE((rid != 0x2c2)&&(rid!=0x2c8)&&(rid!=0x2c9)&&(rid!=0x2d6)&&(rid!=0x38b)); - // Validate the calling convention. - ulCurByte += CorSigUncompressedDataSize(pbSig); - ulCallConv = CorSigUncompressData(pbSig); - i = ulCallConv & IMAGE_CEE_CS_CALLCONV_MASK; - if(i == IMAGE_CEE_CS_CALLCONV_FIELD) // <REVISIT_TODO>it's a temporary bypass (VB bug)</REVISIT_TODO> - ulArgCount = 1; - else - { - if(i != IMAGE_CEE_CS_CALLCONV_LOCAL_SIG) // then it is function sig for calli - { - if((i >= IMAGE_CEE_CS_CALLCONV_FIELD) - ||((ulCallConv & IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS) - &&(!(ulCallConv & IMAGE_CEE_CS_CALLCONV_HASTHIS)))) - { - REPORT_ERROR1(VLDTR_E_MD_BADCALLINGCONV, ulCallConv); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - bNoVoidAllowed = FALSE; - } - // Is there any sig left for arguments? - _ASSERTE(ulCurByte <= cbSig); - if (cbSig == ulCurByte) - { - REPORT_ERROR1(VLDTR_E_MD_NOARGCNT, ulCurByte+1); - SetVldtrCode(&hr, hrSave); - goto ErrExit; - } - - // Get the type argument count. - if (ulCallConv & IMAGE_CEE_CS_CALLCONV_GENERIC) - { - ulCurByte += CorSigUncompressedDataSize(pbSig); - ulTyArgCount = CorSigUncompressData(pbSig); - } - - // Get the argument count. - ulCurByte += CorSigUncompressedDataSize(pbSig); - ulArgCount = CorSigUncompressData(pbSig); - } - // Validate the the arguments. - if(ulArgCount) - { - for(i=1; ulCurByte < cbSig; i++) - { - hr = ValidateOneArg(veCtxt.Token, pbSig, cbSig, &ulCurByte,&ulNSentinels,bNoVoidAllowed); - if (hr != S_OK) - { - if(hr == VLDTR_E_SIG_MISSARG) - { - REPORT_ERROR1(VLDTR_E_SIG_MISSARG, i); - } - SetVldtrCode(&hr, hrSave); - hrSave = hr; - break; - } - bNoVoidAllowed = TRUE; // whatever it was for the 1st arg, it must be TRUE for the rest - } - if((ulNSentinels != 0) && (!isCallConv(ulCallConv, IMAGE_CEE_CS_CALLCONV_VARARG ))) - { - REPORT_ERROR0(VLDTR_E_SIG_SENTMUSTVARARG); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - if(ulNSentinels > 1) - { - REPORT_ERROR0(VLDTR_E_SIG_MULTSENTINELS); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - hr = hrSave; -ErrExit: - ; - END_ENTRYPOINT_NOTHROW; - - return hr; -} // RegMeta::ValidateStandAloneSig() - -//***************************************************************************** -// Validate the given EventMap. -//***************************************************************************** -HRESULT RegMeta::ValidateEventMap(RID rid) -{ - return S_OK; -} // RegMeta::ValidateEventMap() - -//***************************************************************************** -// Validate the given EventPtr. -//***************************************************************************** -HRESULT RegMeta::ValidateEventPtr(RID rid) -{ - return S_OK; -} // RegMeta::ValidateEventPtr() - -//***************************************************************************** -// Validate the given Event. -//***************************************************************************** -HRESULT RegMeta::ValidateEvent(RID rid) -{ - CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); // MiniMd of the scope. - VEContext veCtxt; // Context record. - HRESULT hr = S_OK; // Value returned. - HRESULT hrSave = S_OK; // Save state. - mdToken tkClass; // Declaring TypeDef - mdToken tkEventType; // Event Type (TypeDef/TypeRef) - EventRec *pRecord; - HENUMInternal hEnum; - - BEGIN_ENTRYPOINT_NOTHROW; - - IfFailGo(pMiniMd->GetEventRecord(rid, &pRecord)); - - memset(&veCtxt, 0, sizeof(VEContext)); - memset(&hEnum, 0, sizeof(HENUMInternal)); - veCtxt.Token = TokenFromRid(rid,mdtEvent); - veCtxt.uOffset = 0; - - // The scope must be a valid TypeDef - if (FAILED(pMiniMd->FindParentOfEventHelper(veCtxt.Token, &tkClass)) || - (TypeFromToken(tkClass) != mdtTypeDef) || - !IsValidToken(tkClass)) - { - REPORT_ERROR1(VLDTR_E_EV_BADSCOPE, tkClass); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - tkClass = 0; - } - // Must have name - { - LPCUTF8 szName; - IfFailGo(pMiniMd->getNameOfEvent(pRecord, &szName)); - - if (*szName == 0) - { - REPORT_ERROR0(VLDTR_E_EV_NONAME); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else - { - if (strcmp(szName, COR_DELETED_NAME_A) == 0) - goto ErrExit; - if (tkClass != 0) // Must be no duplicates - { - RID ridEventMap; - EventMapRec *pEventMapRec; - EventRec *pRec; - ULONG ridStart; - ULONG ridEnd; - ULONG i; - - IfFailGo(pMiniMd->FindEventMapFor(RidFromToken(tkClass), &ridEventMap)); - if (!InvalidRid(ridEventMap)) - { - IfFailGo(pMiniMd->GetEventMapRecord(ridEventMap, &pEventMapRec)); - ridStart = pMiniMd->getEventListOfEventMap(pEventMapRec); - IfFailGo(pMiniMd->getEndEventListOfEventMap(ridEventMap, &ridEnd)); - - for (i = ridStart; i < ridEnd; i++) - { - if (i == rid) - continue; - IfFailGo(pMiniMd->GetEventRecord(i, &pRec)); - - LPCSTR szEventName; - IfFailGo(pMiniMd->getNameOfEvent(pRec, &szEventName)); - if (strcmp(szName, szEventName) != 0) - continue; - - REPORT_ERROR1(VLDTR_E_EV_DUP, TokenFromRid(i, mdtEvent)); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - } - } - }// end of name block - // EventType must be Nil or valid TypeDef, TypeRef or TypeSpec representing an instantiated generic type - tkEventType = pMiniMd->getEventTypeOfEvent(pRecord); - if (!IsNilToken(tkEventType)) - { - if(IsValidToken(tkEventType) && - ((TypeFromToken(tkEventType)==mdtTypeDef)|| - (TypeFromToken(tkEventType)==mdtTypeRef)|| - (TypeFromToken(tkEventType)==mdtTypeSpec))) - { - // TypeSpecs can be many things, we only handle instantiated generic types currently. - if (TypeFromToken(tkEventType)==mdtTypeSpec) - { - TypeSpecRec *pRec; - IfFailGo(pMiniMd->GetTypeSpecRecord(RidFromToken(tkEventType), &pRec)); - PCCOR_SIGNATURE pSig; - ULONG cSig; - - IfFailGo(pMiniMd->getSignatureOfTypeSpec(pRec, &pSig, &cSig)); - - if (CorSigUncompressElementType(pSig) == ELEMENT_TYPE_GENERICINST && - CorSigUncompressElementType(pSig) == ELEMENT_TYPE_CLASS) - { - // Just update the event type token variable and fall through to the validation code below (it doesn't care - // whether the type is generic or not). - tkEventType = CorSigUncompressToken(pSig); - } - else - { - REPORT_ERROR1(VLDTR_E_EV_BADEVTYPE, tkEventType); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - - // EventType must not be Interface or ValueType - if(TypeFromToken(tkEventType)==mdtTypeDef) // can't say anything about TypeRef: no flags available! - { - TypeDefRec *pTypeDefRecord; - IfFailGo(pMiniMd->GetTypeDefRecord(RidFromToken(tkEventType), &pTypeDefRecord)); - DWORD dwFlags = pTypeDefRecord->GetFlags(); - if(!IsTdClass(dwFlags)) - { - REPORT_ERROR2(VLDTR_E_EV_EVTYPENOTCLASS, tkEventType, dwFlags); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - } - else - { - REPORT_ERROR1(VLDTR_E_EV_BADEVTYPE, tkEventType); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - // Validate related methods - { - MethodSemanticsRec *pSemantics; - RID ridCur; - ULONG ulSemantics; - mdMethodDef tkMethod; - bool bHasAddOn = false; - bool bHasRemoveOn = false; - - IfFailGo( pMiniMd->FindMethodSemanticsHelper(veCtxt.Token, &hEnum) ); - while (HENUMInternal::EnumNext(&hEnum, (mdToken *)&ridCur)) - { - IfFailGo(pMiniMd->GetMethodSemanticsRecord(ridCur, &pSemantics)); - ulSemantics = pMiniMd->getSemanticOfMethodSemantics(pSemantics); - tkMethod = TokenFromRid( pMiniMd->getMethodOfMethodSemantics(pSemantics), mdtMethodDef ); - // Semantics must be Setter, Getter or Other - switch (ulSemantics) - { - case msAddOn: - bHasAddOn = true; - break; - case msRemoveOn: - bHasRemoveOn = true; - break; - case msFire: - case msOther: - break; - default: - REPORT_ERROR2(VLDTR_E_EV_BADSEMANTICS, tkMethod,ulSemantics); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // Method must be valid - if(!IsValidToken(tkMethod)) - { - REPORT_ERROR1(VLDTR_E_EV_BADMETHOD, tkMethod); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else - { - // Method's parent must be the same - mdToken tkTypeDef; - IfFailGo(pMiniMd->FindParentOfMethodHelper(tkMethod, &tkTypeDef)); - if(tkTypeDef != tkClass) - { - REPORT_ERROR2(VLDTR_E_EV_ALIENMETHOD, tkMethod,tkTypeDef); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - } // end loop over methods - // AddOn and RemoveOn are a must - if(!bHasAddOn) - { - REPORT_ERROR0(VLDTR_E_EV_NOADDON); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - if(!bHasRemoveOn) - { - REPORT_ERROR0(VLDTR_E_EV_NOREMOVEON); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - }// end of related method validation block - - hr = hrSave; -ErrExit: - HENUMInternal::ClearEnum(&hEnum); - - END_ENTRYPOINT_NOTHROW; - - return hr; -} // RegMeta::ValidateEvent() - - -//***************************************************************************** -// Validate the given PropertyMap. -//***************************************************************************** -HRESULT RegMeta::ValidatePropertyMap(RID rid) -{ - return S_OK; -} // RegMeta::ValidatePropertyMap(0 - -//***************************************************************************** -// Validate the given PropertyPtr. -//***************************************************************************** -HRESULT RegMeta::ValidatePropertyPtr(RID rid) -{ - return S_OK; -} // RegMeta::ValidatePropertyPtr() - -//***************************************************************************** -// Validate the given Property. -//***************************************************************************** -HRESULT RegMeta::ValidateProperty(RID rid) -{ - CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); // MiniMd for the scope. - VEContext veCtxt; // Context record. - HRESULT hr = S_OK; // Value returned. - HRESULT hrSave = S_OK; // Save state. - mdToken tkClass = mdTokenNil; // Declaring TypeDef - PropertyRec *pRecord; - HENUMInternal hEnum; - RID tempRid; - - BEGIN_ENTRYPOINT_NOTHROW; - - IfFailGo(pMiniMd->GetPropertyRecord(rid, &pRecord)); - - memset(&veCtxt, 0, sizeof(VEContext)); - memset(&hEnum, 0, sizeof(HENUMInternal)); - veCtxt.Token = TokenFromRid(rid,mdtProperty); - veCtxt.uOffset = 0; - // The scope must be a valid TypeDef - IfFailGo(pMiniMd->FindParentOfPropertyHelper( veCtxt.Token, &tkClass)); - if ((TypeFromToken(tkClass) != mdtTypeDef) || - !IsValidToken(tkClass) || - IsNilToken(tkClass)) - { - REPORT_ERROR1(VLDTR_E_PR_BADSCOPE, tkClass); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // Must have name and signature - { - ULONG cbSig; - PCCOR_SIGNATURE pvSig; - IfFailGo(pMiniMd->getTypeOfProperty(pRecord, &pvSig, &cbSig)); - - LPCUTF8 szName; - IfFailGo(pMiniMd->getNameOfProperty(pRecord, &szName)); - ULONG ulNameLen = (szName != NULL) ? (ULONG)strlen(szName) : 0; - - if (ulNameLen == 0) - { - REPORT_ERROR0(VLDTR_E_PR_NONAME); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else - { - if(strcmp(szName, COR_DELETED_NAME_A) == 0) - goto ErrExit; - } - if (cbSig == 0) - { - REPORT_ERROR0(VLDTR_E_PR_NOSIG); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // Must be no duplicates - if ((ulNameLen != 0) && (cbSig != 0)) - { - RID ridPropertyMap; - PropertyMapRec *pPropertyMapRec; - PropertyRec *pRec; - ULONG ridStart; - ULONG ridEnd; - ULONG i; - ULONG cbSig1; - PCCOR_SIGNATURE pvSig1; - - IfFailGo(pMiniMd->FindPropertyMapFor(RidFromToken(tkClass), &ridPropertyMap)); - if (!InvalidRid(ridPropertyMap) ) - { - IfFailGo(pMiniMd->GetPropertyMapRecord(ridPropertyMap, &pPropertyMapRec)); - ridStart = pMiniMd->getPropertyListOfPropertyMap(pPropertyMapRec); - IfFailGo(pMiniMd->getEndPropertyListOfPropertyMap(ridPropertyMap, &ridEnd)); - - for (i = ridStart; i < ridEnd; i++) - { - if (i == rid) - continue; - IfFailGo(pMiniMd->GetPropertyRecord(i, &pRec)); - IfFailGo(pMiniMd->getTypeOfProperty(pRec, &pvSig1, &cbSig1)); - - if (cbSig != cbSig1) - continue; - if (memcmp(pvSig,pvSig1,cbSig) != 0) - continue; - - LPCSTR szPropertyName; - IfFailGo(pMiniMd->getNameOfProperty(pRec, &szPropertyName)); - if (strcmp(szName, szPropertyName) != 0) - continue; - - REPORT_ERROR1(VLDTR_E_PR_DUP, TokenFromRid(i,mdtProperty)); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - } - // Validate the signature - if ((pvSig != NULL) && (cbSig != 0)) - { - ULONG ulCurByte = 0; // Current index into the signature. - ULONG ulCallConv; // Calling convention. - ULONG ulArgCount; - ULONG i; - ULONG ulNSentinels = 0; - - // Validate the calling convention. - ulCurByte += CorSigUncompressedDataSize(pvSig); - ulCallConv = CorSigUncompressData(pvSig); - if (!isCallConv(ulCallConv, IMAGE_CEE_CS_CALLCONV_PROPERTY )) - { - REPORT_ERROR1(VLDTR_E_PR_BADCALLINGCONV, ulCallConv); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // Get the argument count. - ulCurByte += CorSigUncompressedDataSize(pvSig); - ulArgCount = CorSigUncompressData(pvSig); - - // Validate the arguments. - for (i = 0; i < ulArgCount; i++) - { - hr = ValidateOneArg(veCtxt.Token, pvSig, cbSig, &ulCurByte,&ulNSentinels,(i>0)); - if (hr != S_OK) - { - if (hr == VLDTR_E_SIG_MISSARG) - { - REPORT_ERROR1(VLDTR_E_SIG_MISSARG, i+1); - } - SetVldtrCode(&hr, hrSave); - break; - } - } - }//end if(pvSig && cbSig) - }// end of name/signature block - - // Marked HasDefault <=> has default value - IfFailGo(pMiniMd->FindConstantHelper(veCtxt.Token, &tempRid)); - if (InvalidRid(tempRid) == IsPrHasDefault(pRecord->GetPropFlags())) - { - REPORT_ERROR0(IsPrHasDefault(pRecord->GetPropFlags())? VLDTR_E_PR_MARKEDNODEFLT : VLDTR_E_PR_DEFLTNOTMARKED); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - // Validate related methods - { - MethodSemanticsRec *pSemantics; - RID ridCur; - ULONG ulSemantics; - mdMethodDef tkMethod; - - IfFailGo( pMiniMd->FindMethodSemanticsHelper(veCtxt.Token, &hEnum) ); - while (HENUMInternal::EnumNext(&hEnum, (mdToken *) &ridCur)) - { - IfFailGo(pMiniMd->GetMethodSemanticsRecord(ridCur, &pSemantics)); - ulSemantics = pMiniMd->getSemanticOfMethodSemantics(pSemantics); - tkMethod = TokenFromRid( pMiniMd->getMethodOfMethodSemantics(pSemantics), mdtMethodDef ); - // Semantics must be Setter, Getter or Other - switch (ulSemantics) - { - case msSetter: - case msGetter: - case msOther: - break; - default: - REPORT_ERROR2(VLDTR_E_PR_BADSEMANTICS, tkMethod, ulSemantics); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // Method must be valid - if(!IsValidToken(tkMethod)) - { - REPORT_ERROR1(VLDTR_E_PR_BADMETHOD, tkMethod); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else - { - // Method's parent must be the same - mdToken tkTypeDef; - IfFailGo(pMiniMd->FindParentOfMethodHelper(tkMethod, &tkTypeDef)); - if(tkTypeDef != tkClass) - { - REPORT_ERROR2(VLDTR_E_PR_ALIENMETHOD, tkMethod, tkTypeDef); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - } // end loop over methods - }// end of related method validation block - - hr = hrSave; -ErrExit: - HENUMInternal::ClearEnum(&hEnum); - - END_ENTRYPOINT_NOTHROW; - - return hr; -} // RegMeta::ValidateProperty() - -//***************************************************************************** -// Validate the given MethodSemantics. -//***************************************************************************** -HRESULT RegMeta::ValidateMethodSemantics(RID rid) -{ - return S_OK; -} // RegMeta::ValidateMethodSemantics() - -//***************************************************************************** -// Validate the given MethodImpl. -//***************************************************************************** -HRESULT RegMeta::ValidateMethodImpl(RID rid) -{ - CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); // MiniMd for the scope. - MethodImplRec* pRecord; - MethodImplRec* pRec; - VEContext veCtxt; // Context record. - HRESULT hr = S_OK; // Value returned. - HRESULT hrSave = S_OK; // Save state. - mdToken tkClass; // Declaring TypeDef - mdToken tkBody; // Implementing method (MethodDef or MemberRef) - mdToken tkDecl; // Implemented method (MethodDef or MemberRef) - unsigned iCount; - unsigned index; - - BEGIN_ENTRYPOINT_NOTHROW; - - memset(&veCtxt, 0, sizeof(VEContext)); - veCtxt.Token = TokenFromRid(rid, mdtMethodImpl); - veCtxt.uOffset = 0; - - PCCOR_SIGNATURE pbBodySig = NULL; - PCCOR_SIGNATURE pbDeclSig = NULL; - - IfFailGo(pMiniMd->GetMethodImplRecord(rid, &pRecord)); - tkClass = pMiniMd->getClassOfMethodImpl(pRecord); - // Class must be valid - if(!IsValidToken(tkClass) || (TypeFromToken(tkClass) != mdtTypeDef)) - { - REPORT_ERROR1(VLDTR_E_MI_BADCLASS, tkClass); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else - { // ... and not an Interface - TypeDefRec *pTypeDefRecord; - IfFailGo(pMiniMd->GetTypeDefRecord(RidFromToken(tkClass), &pTypeDefRecord)); - if(IsTdInterface(pTypeDefRecord->GetFlags())) - { - REPORT_ERROR1(VLDTR_E_MI_CLASSISINTF, tkClass); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - // Decl must be valid MethodDef or MemberRef - tkDecl = pMiniMd->getMethodDeclarationOfMethodImpl(pRecord); - if(!(IsValidToken(tkDecl) && - ((TypeFromToken(tkDecl) == mdtMethodDef) || (TypeFromToken(tkDecl) == mdtMemberRef)))) - { - REPORT_ERROR1(VLDTR_E_MI_BADDECL, tkDecl); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // Body must be valid MethodDef or MemberRef - tkBody = pMiniMd->getMethodBodyOfMethodImpl(pRecord); - if(!(IsValidToken(tkBody) && - ((TypeFromToken(tkBody) == mdtMethodDef) || (TypeFromToken(tkBody) == mdtMemberRef)))) - { - REPORT_ERROR1(VLDTR_E_MI_BADBODY, tkBody); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // No duplicates based on (tkClass,tkDecl) - iCount = pMiniMd->getCountMethodImpls(); - for(index = rid+1; index <= iCount; index++) - { - IfFailGo(pMiniMd->GetMethodImplRecord(index, &pRec)); - if((tkClass == pMiniMd->getClassOfMethodImpl(pRec)) && - (tkDecl == pMiniMd->getMethodDeclarationOfMethodImpl(pRec))) - { - REPORT_ERROR1(VLDTR_E_MI_DUP, index); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - - mdToken tkBodyParent; - ULONG cbBodySig; - - if(TypeFromToken(tkBody) == mdtMethodDef) - { - MethodRec *pBodyRec; - IfFailGo(pMiniMd->GetMethodRecord(RidFromToken(tkBody), &pBodyRec)); - IfFailGo(pMiniMd->getSignatureOfMethod(pBodyRec, &pbBodySig, &cbBodySig)); - IfFailGo(pMiniMd->FindParentOfMethodHelper(tkBody, &tkBodyParent)); - // Body must not be static - if(IsMdStatic(pBodyRec->GetFlags())) - { - REPORT_ERROR1(VLDTR_E_MI_BODYSTATIC, tkBody); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - else if(TypeFromToken(tkBody) == mdtMemberRef) - { - MemberRefRec *pBodyRec; - IfFailGo(pMiniMd->GetMemberRefRecord(RidFromToken(tkBody), &pBodyRec)); - tkBodyParent = pMiniMd->getClassOfMemberRef(pBodyRec); - IfFailGo(pMiniMd->getSignatureOfMemberRef(pBodyRec, &pbBodySig, &cbBodySig)); - } - // Body must belong to the same class - if(tkBodyParent != tkClass) - { - REPORT_ERROR1(VLDTR_E_MI_ALIENBODY, tkBodyParent); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - mdToken tkDeclParent; - ULONG cbDeclSig; - - if(TypeFromToken(tkDecl) == mdtMethodDef) - { - MethodRec *pDeclRec; - IfFailGo(pMiniMd->GetMethodRecord(RidFromToken(tkDecl), &pDeclRec)); - IfFailGo(pMiniMd->getSignatureOfMethod(pDeclRec, &pbDeclSig, &cbDeclSig)); - IfFailGo(pMiniMd->FindParentOfMethodHelper(tkDecl, &tkDeclParent)); - // Decl must be virtual - if(!IsMdVirtual(pDeclRec->GetFlags())) - { - REPORT_ERROR1(VLDTR_E_MI_DECLNOTVIRT, tkDecl); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // Decl must not be final - if(IsMdFinal(pDeclRec->GetFlags())) - { - REPORT_ERROR1(VLDTR_E_MI_DECLFINAL, tkDecl); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // Decl must not be private - if(IsMdPrivate(pDeclRec->GetFlags()) && IsMdCheckAccessOnOverride(pDeclRec->GetFlags())) - { - REPORT_ERROR1(VLDTR_E_MI_DECLPRIV, tkDecl); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - else if(TypeFromToken(tkDecl) == mdtMemberRef) - { - MemberRefRec *pDeclRec; - IfFailGo(pMiniMd->GetMemberRefRecord(RidFromToken(tkDecl), &pDeclRec)); - tkDeclParent = pMiniMd->getClassOfMemberRef(pDeclRec); - IfFailGo(pMiniMd->getSignatureOfMemberRef(pDeclRec, &pbDeclSig, &cbDeclSig)); - } - - // Compare the signatures as best we can, delegating some comparisons to the loader. - if (*pbBodySig & IMAGE_CEE_CS_CALLCONV_GENERIC) - { - // decl's callconv must be generic - if (*pbDeclSig & IMAGE_CEE_CS_CALLCONV_GENERIC) - { - // and the arities must match - ULONG ulBodyArity = CorSigUncompressData(++pbBodySig); - ULONG ulDeclArity = CorSigUncompressData(++pbDeclSig); - if(ulBodyArity != ulDeclArity) - { - REPORT_ERROR3(VLDTR_E_MI_ARITYMISMATCH,tkDecl,ulDeclArity,ulBodyArity); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - else - { - REPORT_ERROR1(VLDTR_E_MI_DECLNOTGENERIC,tkDecl); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // delegate precise signature checking to the loader, - // as this requires signature comparison modulo substitution - } - else if (*pbDeclSig & IMAGE_CEE_CS_CALLCONV_GENERIC) - { - REPORT_ERROR1(VLDTR_E_MI_IMPLNOTGENERIC,tkDecl); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else if (TypeFromToken(tkDeclParent) == mdtTypeSpec) - { - // do nothing for now... - // delegate precise signature checking to the loader, - // as this requires signature comparison modulo substitution - } - // Signatures must match (except call conv) - else if((cbDeclSig != cbBodySig)||(memcmp(pbDeclSig+1,pbBodySig+1,cbDeclSig-1))) - { - //@GENERICSVER: todo: - /* - //@TODO: Fix to have peverify resolve assemblies - // through the runtime. At that point, use this method instead - // of the current compare - - // @TODO: check for other bad memcmp sig comparisons in peverify - - // Can't use memcmp because there may be two AssemblyRefs - // in this scope, pointing to the same assembly, etc.). - if (!MetaSig::CompareMethodSigs(pbDeclSig, - cbDeclSig, - Module* pModule1, - pbBodySig, - cbDeclSig, - Module* pModule2)) - */ - UnifiedAssemblySigComparer uasc(*this); - MDSigComparer sc(MDSigParser(pbDeclSig, cbDeclSig), - MDSigParser(pbBodySig, cbBodySig), - uasc); - - hr = sc.CompareMethodSignature(); - - if (FAILED(hr)) - { - REPORT_ERROR2(VLDTR_E_MI_SIGMISMATCH,tkDecl,tkBody); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - - hr = hrSave; -ErrExit: - ; - END_ENTRYPOINT_NOTHROW; - - return hr; -} // RegMeta::ValidateMethodImpl() - -//***************************************************************************** -// Validate the given ModuleRef. -//***************************************************************************** -HRESULT RegMeta::ValidateModuleRef(RID rid) -{ - CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); // MiniMd for the scope. - ModuleRefRec *pRecord; // ModuleRef record. - LPCUTF8 szName; // ModuleRef name. - mdModuleRef tkModuleRef; // Duplicate ModuleRef. - VEContext veCtxt; // Context record. - HRESULT hr = S_OK; // Value returned. - HRESULT hrSave = S_OK; // Save state. - - BEGIN_ENTRYPOINT_NOTHROW; - - memset(&veCtxt, 0, sizeof(VEContext)); - // Get the ModuleRef record. - veCtxt.Token = TokenFromRid(rid, mdtModuleRef); - veCtxt.uOffset = 0; - - IfFailGo(pMiniMd->GetModuleRefRecord(rid, &pRecord)); - - // C++ emits IJW methods with ImplMaps - // which have resolution=ModuleRef with empty name - IfFailGo(pMiniMd->getNameOfModuleRef(pRecord, &szName)); - if (*szName) - { - // Look for a Duplicate, this function reports only one duplicate. - hr = ImportHelper::FindModuleRef(pMiniMd, szName, &tkModuleRef, rid); - if (hr == S_OK) - { - REPORT_ERROR1(VLDTR_E_MODREF_DUP, tkModuleRef); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else if (hr == CLDB_E_RECORD_NOTFOUND) - hr = S_OK; - else - IfFailGo(hr); - } - else - hrSave = S_FALSE; - hr = hrSave; -ErrExit: - ; - END_ENTRYPOINT_NOTHROW; - - return hr; -} // RegMeta::ValidateModuleRef() - -//***************************************************************************** -// Validate the given TypeSpec. -//***************************************************************************** -//@todo GENERICS: reject duplicate specs? -HRESULT RegMeta::ValidateTypeSpec(RID rid) -{ - CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); // MiniMd of the scope. - TypeSpecRec *pRecord; // TypeSpec record. - PCCOR_SIGNATURE pbSig; // Signature. - ULONG cbSig; // Size in bytes of the signature. - VEContext veCtxt; // Context record. - HRESULT hr = S_OK; // Value returned. - HRESULT hrSave = S_OK; // Save state. - ULONG ulCurByte = 0; // Current index into the signature. - ULONG ulNSentinels = 0; // Number of sentinels in the signature - - BEGIN_ENTRYPOINT_NOTHROW; - - memset(&veCtxt, 0, sizeof(VEContext)); - // Extract the record. - veCtxt.Token = TokenFromRid(rid,mdtTypeSpec); - veCtxt.uOffset = 0; - IfFailGo(pMiniMd->GetTypeSpecRecord(rid, &pRecord)); - IfFailGo(pMiniMd->getSignatureOfTypeSpec(pRecord, &pbSig, &cbSig)); - - // Validate the signature is well-formed with respect to the compression - // scheme. If this fails, no further validation needs to be done. - if ( (hr = ValidateSigCompression(veCtxt.Token, pbSig, cbSig)) != S_OK) - goto ErrExit; - - hr = ValidateOneArg(veCtxt.Token, pbSig, cbSig, &ulCurByte,&ulNSentinels,FALSE); - if (hr != S_OK) - { - if(hr == VLDTR_E_SIG_MISSARG) - { - REPORT_ERROR0(VLDTR_E_TS_EMPTY); - } - SetVldtrCode(&hr, hrSave); - hrSave = hr; - } - if(ulNSentinels != 0) - { - REPORT_ERROR0(VLDTR_E_TS_HASSENTINALS); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - hr = hrSave; -ErrExit: - ; - END_ENTRYPOINT_NOTHROW; - - return hr; -} // RegMeta::ValidateTypeSpec() - -//***************************************************************************** -// This function validates the given Field signature. This function works -// with Field signature for both the MemberRef and FieldDef. -//***************************************************************************** -HRESULT RegMeta::ValidateMethodSpecSig( - mdMethodSpec tk, // [IN] Token whose signature needs to be validated. - PCCOR_SIGNATURE pbSig, // [IN] Signature. - ULONG cbSig, // [IN] Size in bytes of the signature. - ULONG *pArity) // [Out] Arity of the instantiation -{ - ULONG ulCurByte = 0; // Current index into the signature. - ULONG ulCallConv; // Calling convention. - ULONG ulArity; // Arity of instantiation. - ULONG ulArgCnt; - VEContext veCtxt; // Context record. - HRESULT hr = S_OK; // Value returned. - HRESULT hrSave = S_OK; // Save state. - - BEGIN_ENTRYPOINT_NOTHROW; - - memset(&veCtxt, 0, sizeof(VEContext)); - _ASSERTE(TypeFromToken(tk) == mdtMethodSpec); - - veCtxt.Token = tk; - veCtxt.uOffset = 0; - - // Validate the calling convention. - ulCurByte += CorSigUncompressedDataSize(pbSig); - ulCallConv = CorSigUncompressData(pbSig); - if (!isCallConv(ulCallConv, IMAGE_CEE_CS_CALLCONV_GENERICINST)) - { - REPORT_ERROR1(VLDTR_E_MS_BADCALLINGCONV, ulCallConv); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - if (cbSig == ulCurByte) - { - REPORT_ERROR1(VLDTR_E_MS_MISSARITY, ulCurByte + 1); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - ulCurByte += CorSigUncompressedDataSize(pbSig); - ulArity = CorSigUncompressData(pbSig); - - if (ulArity == 0) - { - REPORT_ERROR1(VLDTR_E_MS_ARITYZERO, ulCurByte); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - ulArgCnt = ulArity; - - if(pArity != NULL) - { - *pArity = ulArity; - } - - // Validate and consume the arguments. - while(ulArgCnt--) - { - - PCCOR_SIGNATURE pbTypeArg = pbSig; - ULONG ulTypeArgByte = ulCurByte; - - IfFailGo(ValidateOneArg(tk, pbSig, cbSig, &ulCurByte, NULL, TRUE)); - if (hr != S_OK) - { - if(hr == VLDTR_E_SIG_MISSARG) - { - REPORT_ERROR1(VLDTR_E_MS_MISSARG, ulArity-ulArgCnt); - } - SetVldtrCode(&hrSave, VLDTR_S_ERR); - break; - } - // reject byref-like args - switch (CorSigUncompressData(pbTypeArg)) - { - case ELEMENT_TYPE_TYPEDBYREF: - case ELEMENT_TYPE_BYREF: - { - REPORT_ERROR1(VLDTR_E_MS_BYREFINST, ulTypeArgByte); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - break; - } - default: - break; - } - } - - hr = hrSave; -ErrExit: - ; - END_ENTRYPOINT_NOTHROW; - - return hr; -} // RegMeta::ValidateMethodSpecSig() - - -//***************************************************************************** -// Validate the given MethodSpec. -//***************************************************************************** -HRESULT RegMeta::ValidateMethodSpec(RID rid) -{ - CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); // MiniMd of the scope. - MethodSpecRec *pRecord; // MethodSpec record. - mdToken tkMethod; // Method field (a MethodDefOrRef) - PCCOR_SIGNATURE pInstantiation; // MethodSpec instantiation (a signature) - ULONG cbInstantiation; // Size of instantiation. - ULONG ulInstantiationArity; // Arity of the Instantiation - - VEContext veCtxt; // Context record. - HRESULT hr = S_OK; // Value returned. - HRESULT hrSave = S_OK; // Save state. - - BEGIN_ENTRYPOINT_NOTHROW; - - memset(&veCtxt, 0, sizeof(VEContext)); - // Get the GenericParamConstraint record. - veCtxt.Token = TokenFromRid(rid, mdtMethodSpec); - veCtxt.uOffset = 0; - IfFailGo(pMiniMd->GetMethodSpecRecord(rid, &pRecord)); - - // 1. The MethodSpec table may contain zero or more rows. - // (Nothing to check.) - - // Implicit (missing from spec): Method is not nil [ERROR] - tkMethod = pMiniMd->getMethodOfMethodSpec(pRecord); - if(IsNilToken(tkMethod)) - { - REPORT_ERROR0(VLDTR_E_MS_METHODNIL); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - // Implicit in ValidateRecord: Method is a valid mdMethodDefOrRef. - - // 2. One or more rows may refer to the same row in the MethodDef or MethodRef table. - // (There may be more multiple instantions of the same generic method) - // (nothing to check!) - - // 3. "The signature stored at Instantiation shall be a valid instantiation of the signature of the generic method stored at Method. [ERROR] - { - IfFailGo(pMiniMd->getInstantiationOfMethodSpec(pRecord, &pInstantiation, &cbInstantiation)); - IfFailGo(ValidateMethodSpecSig(TokenFromRid(rid, mdtMethodSpec), pInstantiation, cbInstantiation,&ulInstantiationArity)); - if (hr != S_OK) - SetVldtrCode(&hrSave, hr); - } - - IfFailGo(pMiniMd->getInstantiationOfMethodSpec(pRecord, &pInstantiation, &cbInstantiation)); - // 4. There shall be no duplicate rows based upon Method and Instantiation [ERROR] - { - mdMethodSpec tkDupMethodSpec; - hr = ImportHelper::FindMethodSpecByMethodAndInstantiation(pMiniMd, tkMethod, pInstantiation, cbInstantiation, &tkDupMethodSpec, rid); - if (hr == S_OK) - { - REPORT_ERROR1(VLDTR_E_MS_DUP, tkDupMethodSpec); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else if (hr == CLDB_E_RECORD_NOTFOUND) - hr = S_OK; - else - IfFailGo(hr); - } - - // check the method is generic and that the arity of the instantiation is correct - { - PCCOR_SIGNATURE pbGenericMethodSig; - ULONG cbGenericMethodSig; - - if(TypeFromToken(tkMethod) == mdtMethodDef) - { - MethodRec *pMethodRec; - IfFailGo(m_pStgdb->m_MiniMd.GetMethodRecord(RidFromToken(tkMethod), &pMethodRec)); - IfFailGo(pMiniMd->getSignatureOfMethod(pMethodRec, &pbGenericMethodSig, &cbGenericMethodSig)); - } - else - { - _ASSERTE(TypeFromToken(tkMethod) == mdtMemberRef); - MemberRefRec *pMethodRefRec; - IfFailGo(pMiniMd->GetMemberRefRecord(RidFromToken(tkMethod), &pMethodRefRec)); - IfFailGo(pMiniMd->getSignatureOfMemberRef(pMethodRefRec, &pbGenericMethodSig, &cbGenericMethodSig)); - } - - if (*pbGenericMethodSig & IMAGE_CEE_CS_CALLCONV_GENERIC) - { - ULONG ulGenericArity = CorSigUncompressData(++pbGenericMethodSig); - if(ulGenericArity != ulInstantiationArity) - { - REPORT_ERROR2(VLDTR_E_MS_ARITYMISMATCH,ulGenericArity,ulInstantiationArity); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - else - { - REPORT_ERROR1(VLDTR_E_MS_METHODNOTGENERIC, tkMethod); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - - hr = hrSave; - -ErrExit: - ; - END_ENTRYPOINT_NOTHROW; - - return hr; -} // RegMeta::ValidateMethodSpec() - - -//***************************************************************************** -// Validate the given GenericParamConstraint. -//***************************************************************************** -HRESULT RegMeta::ValidateGenericParamConstraint(RID rid) -{ - CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); // MiniMd of the scope. - GenericParamConstraintRec *pRecord; // GenericParamConstraint record. - mdGenericParam tkOwner; // GenericParamConstraint owner field. - mdToken tkConstraint; // GenericParamConstraint constraint field. - VEContext veCtxt; // Context record. - HRESULT hr = S_OK; // Value returned. - HRESULT hrSave = S_OK; // Save state. - - BEGIN_ENTRYPOINT_NOTHROW; - - memset(&veCtxt, 0, sizeof(VEContext)); - // Get the GenericParamConstraint record. - veCtxt.Token = TokenFromRid(rid, mdtGenericParamConstraint); - veCtxt.uOffset = 0; - IfFailGo(pMiniMd->GetGenericParamConstraintRecord(rid, &pRecord)); - - // 1. GenericParamConstraint may contain zero or more rows. - // (Nothing to check.) - - // 2. Each row shall have one, and only one, owner row in the GenericParamTable [ERROR] - // (Nothing to check except owner not nil) - tkOwner = pMiniMd->getOwnerOfGenericParamConstraint(pRecord); - if(IsNilToken(tkOwner)) - { - REPORT_ERROR0(VLDTR_E_GPC_OWNERNIL); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - // 3. Each row in the GenericParam table shall own a separate row in the GenericParamConstraint table for each constraint that type parameter has [ERROR] - // (Nothing to check) - - // 4.All of the rows in the GenericParamConstraint table that are owned by a given row in the GenericParamTable - // shall form a contiguous range of rows [ERROR] - //@NOTE: this check is (iterated over all rows) is quadratic in the (typically small) number of constraints - { - RID curRid = rid; - GenericParamConstraintRec *pCurRecord; - mdGenericParam tkCurOwner = tkOwner; - // find the first preceding row with a distinct owner - while (curRid > 1 && tkCurOwner == tkOwner) - { - curRid--; - IfFailGo(pMiniMd->GetGenericParamConstraintRecord(curRid, &pCurRecord)); - tkCurOwner = pMiniMd->getOwnerOfGenericParamConstraint(pCurRecord); - }; - // reject this row if there is some row preceding the current row with this owner - while (curRid > 1) - { - curRid--; - IfFailGo(pMiniMd->GetGenericParamConstraintRecord(curRid, &pCurRecord)); - tkCurOwner = pMiniMd->getOwnerOfGenericParamConstraint(pCurRecord); - if (tkCurOwner == tkOwner) - { - REPORT_ERROR1(VLDTR_E_GPC_NONCONTIGUOUS,tkOwner); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - break; - } - }; - } - - // 5. "At most one class constraint per GenericParam" --- no longer required. - // 6. "Zero or more interface constraints per GenericParam" --- no longer required. - - tkConstraint = pMiniMd->getConstraintOfGenericParamConstraint(pRecord); - // 7. There shall be no duplicates based upon Owner and Constraint - { - mdGenericParamConstraint tkDupGenericParamConstraint; - hr = ImportHelper::FindGenericParamConstraintByOwnerAndConstraint(pMiniMd, tkOwner, tkConstraint, &tkDupGenericParamConstraint, rid); - if (hr == S_OK) - { - REPORT_ERROR1(VLDTR_E_GPC_DUP, tkDupGenericParamConstraint); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else if (hr == CLDB_E_RECORD_NOTFOUND) - hr = S_OK; - else - IfFailGo(hr); - } - - hr = hrSave; - -ErrExit: - ; - END_ENTRYPOINT_NOTHROW; - - return hr; -} // RegMeta::ValidateGenericParamConstraint() - -//***************************************************************************** -// Validate the given ImplMap. -//***************************************************************************** -HRESULT RegMeta::ValidateImplMap(RID rid) -{ - CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); // MiniMd for the scope. - ImplMapRec *pRecord; - VEContext veCtxt; // Context record. - HRESULT hr = S_OK; // Value returned. - HRESULT hrSave = S_OK; // Save state. - HRESULT hrModuleRef=S_OK; - mdToken tkModuleRef; - mdToken tkMember; - USHORT usFlags; - - BEGIN_ENTRYPOINT_NOTHROW; - - memset(&veCtxt, 0, sizeof(VEContext)); -#ifdef CACHE_IMPLMAP_VALIDATION_RESULT - for(unsigned jjj=0; jjj<g_nValidated; jjj++) - { - if(g_rValidated[jjj].tok == (rid | 0x51000000)) return g_rValidated[jjj].hr; - } -#endif - veCtxt.Token = rid; - veCtxt.uOffset = 0; - IfFailGo(pMiniMd->GetImplMapRecord(rid, &pRecord)); - if(pRecord == NULL) IfFailGo(E_FAIL); - // ImplMap must have ModuleRef - tkModuleRef = pMiniMd->getImportScopeOfImplMap(pRecord); - if((TypeFromToken(tkModuleRef) != mdtModuleRef) || IsNilToken(tkModuleRef) - || FAILED(hrModuleRef= ValidateModuleRef(RidFromToken(tkModuleRef)))) - { - REPORT_ERROR1(VLDTR_E_IMAP_BADMODREF, tkModuleRef); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // ImplMap must belong to FieldDef or MethodDef - tkMember = pMiniMd->getMemberForwardedOfImplMap(pRecord); - if((TypeFromToken(tkMember) != mdtFieldDef) && (TypeFromToken(tkMember) != mdtMethodDef)) - { - REPORT_ERROR1(VLDTR_E_IMAP_BADMEMBER, tkMember); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // ImplMap must have import name, unless ModuleRef has no name - // (special case for C++ IJW methods) - if(hrModuleRef != S_FALSE) - { - LPCSTR szName; // Import name. - IfFailGo(pMiniMd->getImportNameOfImplMap(pRecord, &szName)); - if((szName==NULL)||(*szName == 0)) - { - REPORT_ERROR0(VLDTR_E_IMAP_BADIMPORTNAME); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - // ImplMap must have valid flags: - // one value of pmCharSetMask - always so, no check needed (values: 0,2,4,6, mask=6) - // one value of pmCallConvMask... - // ...and it's not pmCallConvThiscall - usFlags = pRecord->GetMappingFlags() & pmCallConvMask; - if((usFlags < pmCallConvWinapi)||(usFlags > pmCallConvFastcall)) - { - REPORT_ERROR1(VLDTR_E_IMAP_BADCALLCONV, usFlags); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } -ErrExit: - -#ifdef CACHE_IMPLMAP_VALIDATION_RESULT - g_rValidated[g_nValidated].tok = rid | 0x51000000; - g_rValidated[g_nValidated].hr = hrSave; - g_nValidated++; -#endif - ; - END_ENTRYPOINT_NOTHROW; - - return hr; -} // RegMeta::ValidateImplMap() - -//***************************************************************************** -// Validate the given FieldRVA. -//***************************************************************************** -HRESULT RegMeta::ValidateFieldRVA(RID rid) -{ - CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); // MiniMd for the scope. - FieldRVARec *pRecord; - VEContext veCtxt; // Context record. - HRESULT hr = S_OK; // Value returned. - HRESULT hrSave = S_OK; // Save state. - mdToken tkField; - ULONG ulRVA; - - BEGIN_ENTRYPOINT_NOTHROW; - - memset(&veCtxt, 0, sizeof(VEContext)); - veCtxt.Token = rid; - veCtxt.uOffset = 0; - IfFailGo(pMiniMd->GetFieldRVARecord(rid, &pRecord)); - ulRVA = pRecord->GetRVA(); - tkField = pMiniMd->getFieldOfFieldRVA(pRecord); - /* - if(ulRVA == 0) - { - REPORT_ERROR1(VLDTR_E_FRVA_ZERORVA, tkField); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - */ - if((0==RidFromToken(tkField))||(TypeFromToken(tkField) != mdtFieldDef)||(!IsValidToken(tkField))) - { - REPORT_ERROR2(VLDTR_E_FRVA_BADFIELD, tkField, ulRVA); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - { - RID N = pMiniMd->getCountFieldRVAs(); - RID tmp; - FieldRVARec* pRecTmp; - for(tmp = rid+1; tmp <= N; tmp++) - { - IfFailGo(pMiniMd->GetFieldRVARecord(tmp, &pRecTmp)); - if(tkField == pMiniMd->getFieldOfFieldRVA(pRecTmp)) - { - REPORT_ERROR2(VLDTR_E_FRVA_DUPFIELD, tkField, tmp); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - } - - hr = hrSave; -ErrExit: - ; - END_ENTRYPOINT_NOTHROW; - - return hr; -} // RegMeta::ValidateFieldRVA() - -//***************************************************************************** -// Validate the given ENCLog. -//***************************************************************************** -HRESULT RegMeta::ValidateENCLog(RID rid) -{ - return S_OK; -} // RegMeta::ValidateENCLog() - -//***************************************************************************** -// Validate the given ENCMap. -//***************************************************************************** -HRESULT RegMeta::ValidateENCMap(RID rid) -{ - return S_OK; -} // RegMeta::ValidateENCMap() - -//***************************************************************************** -// Validate the given Assembly. -//***************************************************************************** -HRESULT RegMeta::ValidateAssembly(RID rid) -{ - CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); // MiniMd for the scope. - AssemblyRec *pRecord; // Assembly record. - CorAssemblyFlags dwFlags; // Assembly flags. - LPCSTR szName; // Assembly Name. - VEContext veCtxt; // Context structure. - HRESULT hr = S_OK; // Value returned. - HRESULT hrSave = S_OK; // Save state. - BOOL invalidAssemblyFlags; // Whether the CorAssemblyFlags are valid. - BOOL fIsV2Assembly = FALSE; - - BEGIN_ENTRYPOINT_NOTHROW; - - memset(&veCtxt, 0, sizeof(VEContext)); - // Get the Assembly record. - veCtxt.Token = TokenFromRid(rid, mdtAssembly); - veCtxt.uOffset = 0; - - IfFailGo(pMiniMd->GetAssemblyRecord(rid, &pRecord)); - - // There can only be one Assembly record. - if (rid > 1) - { - REPORT_ERROR0(VLDTR_E_AS_MULTI); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - // Do checks for name validity.. - IfFailGo(pMiniMd->getNameOfAssembly(pRecord, &szName)); - if (!*szName) - { - // Assembly Name is null. - REPORT_ERROR0(VLDTR_E_AS_NAMENULL); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else - { - unsigned L = (unsigned)strlen(szName); - if((*szName==' ')||strchr(szName,':') || strchr(szName,'\\') || strchr(szName, '/') - || strchr(szName, ',') || strchr(szName, '\n') || strchr(szName, '\r') - || ((L > 4)&&((!SString::_stricmp(&szName[L-4],".exe"))||(!SString::_stricmp(&szName[L-4],".dll"))))) - { - //Assembly name has path and/or extension - REPORT_ERROR0(VLDTR_E_AS_BADNAME); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - - // Get the flags value for the Assembly. - dwFlags = (CorAssemblyFlags) pMiniMd->getFlagsOfAssembly(pRecord); - - // Validate the flags - invalidAssemblyFlags = dwFlags & (~(afPublicKey | afRetargetable | afPA_FullMask | afDebuggableAttributeMask | afContentType_Mask)); - - // Validate we only set a legal processor architecture flags - // The processor architecture flags were introduced in CLR v2.0. - // Note that METAMODEL_MINOR_VER_V2_0 is 0. GCC points out the comparison - // is useless, so that part is commented out. - fIsV2Assembly = (m_pStgdb->m_MiniMd.m_Schema.m_major >= METAMODEL_MAJOR_VER_V2_0 - /* && m_pStgdb->m_MiniMd.m_Schema.m_minor >= METAMODEL_MINOR_VER_V2_0*/); - if (fIsV2Assembly) - { - if ((dwFlags & afPA_Mask) > afPA_AMD64 && !IsAfPA_NoPlatform(dwFlags)) - invalidAssemblyFlags = true; - } - else { - if ((dwFlags & afPA_Mask) != 0) - invalidAssemblyFlags = true; - } - - if (!IsAfContentType_Default(dwFlags) && !IsAfContentType_WindowsRuntime(dwFlags)) - { // Unknown ContentType value - invalidAssemblyFlags = true; - } - - if (invalidAssemblyFlags) - { - REPORT_ERROR1(VLDTR_E_AS_BADFLAGS, dwFlags); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - // Validate hash algorithm ID - switch(pRecord->GetHashAlgId()) - { - case CALG_MD2: - case CALG_MD4: - case CALG_MD5: - case CALG_SHA: - //case CALG_SHA1: // same as CALG_SHA - case CALG_MAC: - case CALG_SSL3_SHAMD5: - case CALG_HMAC: - case 0: - break; - default: - REPORT_ERROR1(VLDTR_E_AS_HASHALGID, pRecord->GetHashAlgId()); - SetVldtrCode(&hrSave, VLDTR_S_WRN); - } - // Validate locale - { - LPCSTR szLocale; - IfFailGo(pMiniMd->getLocaleOfAssembly(pRecord, &szLocale)); - if(!_IsValidLocale(szLocale, fIsV2Assembly)) - { - REPORT_ERROR0(VLDTR_E_AS_BADLOCALE); - SetVldtrCode(&hrSave, VLDTR_S_WRN); - } - } - - hr = hrSave; -ErrExit: - ; - END_ENTRYPOINT_NOTHROW; - - return hr; -} // RegMeta::ValidateAssembly() - -//***************************************************************************** -// Validate the given AssemblyProcessor. -//***************************************************************************** -HRESULT RegMeta::ValidateAssemblyProcessor(RID rid) -{ - return S_OK; -} // RegMeta::ValidateAssemblyProcessor() - -//***************************************************************************** -// Validate the given AssemblyOS. -//***************************************************************************** -HRESULT RegMeta::ValidateAssemblyOS(RID rid) -{ - return S_OK; -} // RegMeta::ValidateAssemblyOS() - -//***************************************************************************** -// Validate the given AssemblyRef. -//***************************************************************************** -HRESULT RegMeta::ValidateAssemblyRef(RID rid) -{ - CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); // MiniMd for the scope. - AssemblyRefRec *pRecord; // Assembly record. - LPCSTR szName; // AssemblyRef Name. - VEContext veCtxt; // Context structure. - HRESULT hr = S_OK; // Value returned. - HRESULT hrSave = S_OK; // Save state. - - BEGIN_ENTRYPOINT_NOTHROW; - - memset(&veCtxt, 0, sizeof(VEContext)); - veCtxt.Token = TokenFromRid(rid, mdtAssemblyRef); - veCtxt.uOffset = 0; - - // Get the AssemblyRef record. - IfFailGo(pMiniMd->GetAssemblyRefRecord(rid, &pRecord)); - - // Do checks for name and alias validity. - IfFailGo(pMiniMd->getNameOfAssemblyRef(pRecord, &szName)); - if (!*szName) - { - // AssemblyRef Name is null. - REPORT_ERROR0(VLDTR_E_AR_NAMENULL); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else - { - unsigned L = (unsigned)strlen(szName); - if((*szName==' ')||strchr(szName,':') || strchr(szName,'\\') || strchr(szName, '/') - || strchr(szName, ',') || strchr(szName, '\n') || strchr(szName, '\r') - || ((L > 4)&&((!SString::_stricmp(&szName[L-4],".exe"))||(!SString::_stricmp(&szName[L-4],".dll"))))) - { - //Assembly name has path and/or extension - REPORT_ERROR0(VLDTR_E_AS_BADNAME); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - - // Validate locale - { - LPCSTR szLocale; - IfFailGo(pMiniMd->getLocaleOfAssemblyRef(pRecord, &szLocale)); - BOOL fIsV2Assembly = (m_pStgdb->m_MiniMd.m_Schema.m_major >= METAMODEL_MAJOR_VER_V2_0 - /* && m_pStgdb->m_MiniMd.m_Schema.m_minor >= METAMODEL_MINOR_VER_V2_0*/); - if(!_IsValidLocale(szLocale, fIsV2Assembly)) - { - REPORT_ERROR0(VLDTR_E_AS_BADLOCALE); - SetVldtrCode(&hrSave, VLDTR_S_WRN); - } - } - - hr = hrSave; -ErrExit: - ; - END_ENTRYPOINT_NOTHROW; - - return hr; -} // RegMeta::ValidateAssemblyRef() - -//***************************************************************************** -// Validate the given AssemblyRefProcessor. -//***************************************************************************** -HRESULT RegMeta::ValidateAssemblyRefProcessor(RID rid) -{ - return S_OK; -} // RegMeta::ValidateAssemblyRefProcessor() - -//***************************************************************************** -// Validate the given AssemblyRefOS. -//***************************************************************************** -HRESULT RegMeta::ValidateAssemblyRefOS(RID rid) -{ - return S_OK; -} // RegMeta::ValidateAssemblyRefOS() - -//***************************************************************************** -// Validate the given File. -//***************************************************************************** -HRESULT RegMeta::ValidateFile(RID rid) -{ - CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); // MiniMd for the scope. - FileRec *pRecord; // File record. - mdFile tkFile; // Duplicate File token. - LPCSTR szName; // File Name. - VEContext veCtxt; // Context structure. - HRESULT hr = S_OK; // Value returned. - HRESULT hrSave = S_OK; // Save state. - - BEGIN_ENTRYPOINT_NOTHROW; - - memset(&veCtxt, 0, sizeof(VEContext)); - veCtxt.Token = TokenFromRid(rid, mdtFile); - veCtxt.uOffset = 0; - - // Get the File record. - IfFailGo(pMiniMd->GetFileRecord(rid, &pRecord)); - - // Do checks for name validity. - IfFailGo(pMiniMd->getNameOfFile(pRecord, &szName)); - if (!*szName) - { - // File Name is null. - REPORT_ERROR0(VLDTR_E_FILE_NAMENULL); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else - { - ULONG L = (ULONG)strlen(szName); - if(L >= MAX_PATH_FNAME) - { - // Name too long - REPORT_ERROR2(VLDTR_E_TD_NAMETOOLONG, L, (ULONG)(MAX_PATH_FNAME-1)); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // Check for duplicates based on Name. - hr = ImportHelper::FindFile(pMiniMd, szName, &tkFile, rid); - if (hr == S_OK) - { - REPORT_ERROR1(VLDTR_E_FILE_DUP, tkFile); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else if (hr == CLDB_E_RECORD_NOTFOUND) - hr = S_OK; - else - IfFailGo(hr); - - // File name must not be fully qualified. - if(strchr(szName,':') || strchr(szName,'\\') || strchr(szName,'/')) - { - REPORT_ERROR0(VLDTR_E_FILE_NAMEFULLQLFD); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - // File name must not be one of system names. - char *sysname[6]={"con","aux","lpt","prn","null","com"}; - char *syssymbol = "0123456789$:"; - for(unsigned i=0; i<6; i++) - { - L = (ULONG)strlen(sysname[i]); - if(!SString::_strnicmp(szName,sysname[i],L)) - { - if((szName[L]==0)|| strchr(syssymbol,szName[L])) - { - REPORT_ERROR0(VLDTR_E_FILE_SYSNAME); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - break; - } - } - } - } - - if (pRecord->GetFlags() & (~0x00000003)) - { - REPORT_ERROR1(VLDTR_E_FILE_BADFLAGS, pRecord->GetFlags()); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - // Validate hash value - { - const BYTE *pbHashValue = NULL; - ULONG cbHashValue; - IfFailGo(m_pStgdb->m_MiniMd.getHashValueOfFile(pRecord, &pbHashValue, &cbHashValue)); - if ((pbHashValue == NULL) || (cbHashValue == 0)) - { - REPORT_ERROR0(VLDTR_E_FILE_NULLHASH); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - - // Validate that the name is not the same as the file containing - // the manifest. - - // File name must be a valid file name. - - // Each ModuleRef in the assembly must have a corresponding File table entry. - - hr = hrSave; -ErrExit: - ; - END_ENTRYPOINT_NOTHROW; - - return hr; -} // RegMeta::ValidateFile() - -//***************************************************************************** -// Validate the given ExportedType. -//***************************************************************************** -HRESULT RegMeta::ValidateExportedType(RID rid) -{ - CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); // MiniMd for the scope. - ExportedTypeRec *pRecord; // ExportedType record. - mdExportedType tkExportedType; // Duplicate ExportedType. - mdToken tkImpl; // Implementation token - mdToken tkTypeDef; // TypeDef token - - LPCSTR szName; // ExportedType Name. - LPCSTR szNamespace; // ExportedType Namespace. - VEContext veCtxt; // Context structure. - HRESULT hr = S_OK; // Value returned. - HRESULT hrSave = S_OK; // Save state. - - BEGIN_ENTRYPOINT_NOTHROW; - - memset(&veCtxt, 0, sizeof(VEContext)); - veCtxt.Token = TokenFromRid(rid, mdtExportedType); - veCtxt.uOffset = 0; - - // Get the ExportedType record. - IfFailGo(pMiniMd->GetExportedTypeRecord(rid, &pRecord)); - - tkImpl = pMiniMd->getImplementationOfExportedType(pRecord); - - tkTypeDef = pRecord->GetTypeDefId(); - if ((TypeFromToken(tkImpl) == mdtFile) && IsNilToken(tkTypeDef)) - { // Report 'No TypeDefId' warning only for types exported from other modules (do not report it for - // type forwarders) - REPORT_ERROR0(VLDTR_E_CT_NOTYPEDEFID); - SetVldtrCode(&hrSave, VLDTR_S_WRN); - } - - // Do checks for name validity. - IfFailGo(pMiniMd->getTypeNameOfExportedType(pRecord, &szName)); - IfFailGo(pMiniMd->getTypeNamespaceOfExportedType(pRecord, &szNamespace)); - if (!*szName) - { - // ExportedType Name is null. - REPORT_ERROR0(VLDTR_E_CT_NAMENULL); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else - { - if(!strcmp(szName,COR_DELETED_NAME_A)) goto ErrExit; - ULONG L = (ULONG)(strlen(szName)+strlen(szNamespace)); - if(L >= MAX_CLASSNAME_LENGTH) - { - // Name too long - REPORT_ERROR2(VLDTR_E_TD_NAMETOOLONG, L, (ULONG)(MAX_CLASSNAME_LENGTH-1)); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // Check for duplicates based on Name and Enclosing ExportedType. - hr = ImportHelper::FindExportedType(pMiniMd, szNamespace, szName, tkImpl, &tkExportedType, rid); - if (hr == S_OK) - { - REPORT_ERROR1(VLDTR_E_CT_DUP, tkExportedType); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else if (hr == CLDB_E_RECORD_NOTFOUND) - hr = S_OK; - else - IfFailGo(hr); - // Check for duplicate TypeDef based on Name/NameSpace - only for top-level ExportedTypes. - if(TypeFromToken(tkImpl)==mdtFile) - { - mdToken tkTypeDef2; - hr = ImportHelper::FindTypeDefByName(pMiniMd, szNamespace, szName, mdTypeDefNil, - &tkTypeDef2, 0); - if (hr == S_OK) - { - REPORT_ERROR1(VLDTR_E_CT_DUPTDNAME, tkTypeDef2); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else if (hr == CLDB_E_RECORD_NOTFOUND) - hr = S_OK; - else - IfFailGo(hr); - } - } - // Check if flag value is valid - { - DWORD dwFlags = pRecord->GetFlags(); - DWORD dwInvalidMask, dwExtraBits; - dwInvalidMask = (DWORD)~(tdVisibilityMask | tdLayoutMask | tdClassSemanticsMask | - tdAbstract | tdSealed | tdSpecialName | tdImport | tdSerializable | tdForwarder | - tdStringFormatMask | tdBeforeFieldInit | tdReservedMask); - // check for extra bits - dwExtraBits = dwFlags & dwInvalidMask; - if(!dwExtraBits) - { - // if no extra bits, check layout - dwExtraBits = dwFlags & tdLayoutMask; - if(dwExtraBits != tdLayoutMask) - { - // layout OK, check string format - dwExtraBits = dwFlags & tdStringFormatMask; - if(dwExtraBits != tdStringFormatMask) dwExtraBits = 0; - } - } - if(dwExtraBits) - { - REPORT_ERROR1(VLDTR_E_TD_EXTRAFLAGS, dwExtraBits); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - - if(IsNilToken(tkImpl) - || ((TypeFromToken(tkImpl) != mdtFile)&&(TypeFromToken(tkImpl) != mdtExportedType)&&(TypeFromToken(tkImpl) != mdtAssemblyRef)) - || (!IsValidToken(tkImpl))) - { - REPORT_ERROR1(VLDTR_E_CT_BADIMPL, tkImpl); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - hr = hrSave; -ErrExit: - ; - END_ENTRYPOINT_NOTHROW; - - return hr; -} // RegMeta::ValidateExportedType() - -//***************************************************************************** -// Validate the given ManifestResource. -//***************************************************************************** -HRESULT RegMeta::ValidateManifestResource(RID rid) -{ - CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); // MiniMd for the scope. - ManifestResourceRec *pRecord; // ManifestResource record. - LPCSTR szName; // ManifestResource Name. - DWORD dwFlags; // ManifestResource flags. - mdManifestResource tkmar; // Duplicate ManifestResource. - VEContext veCtxt; // Context structure. - HRESULT hr = S_OK; // Value returned. - HRESULT hrSave = S_OK; // Save state. - mdToken tkImplementation; - BOOL bIsValidImplementation = TRUE; - - BEGIN_ENTRYPOINT_NOTHROW; - - memset(&veCtxt, 0, sizeof(VEContext)); - veCtxt.Token = TokenFromRid(rid, mdtManifestResource); - veCtxt.uOffset = 0; - - // Get the ManifestResource record. - IfFailGo(pMiniMd->GetManifestResourceRecord(rid, &pRecord)); - - // Do checks for name validity. - IfFailGo(pMiniMd->getNameOfManifestResource(pRecord, &szName)); - if (!*szName) - { - // ManifestResource Name is null. - REPORT_ERROR0(VLDTR_E_MAR_NAMENULL); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else - { - // Check for duplicates based on Name. - hr = ImportHelper::FindManifestResource(pMiniMd, szName, &tkmar, rid); - if (hr == S_OK) - { - REPORT_ERROR1(VLDTR_E_MAR_DUP, tkmar); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else if (hr == CLDB_E_RECORD_NOTFOUND) - hr = S_OK; - else - IfFailGo(hr); - } - - // Get the flags of the ManifestResource. - dwFlags = pMiniMd->getFlagsOfManifestResource(pRecord); - if(dwFlags &(~0x00000003)) - { - REPORT_ERROR1(VLDTR_E_MAR_BADFLAGS, dwFlags); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - // Visibility of ManifestResource flags must either be public or private. - if (!IsMrPublic(dwFlags) && !IsMrPrivate(dwFlags)) - { - REPORT_ERROR0(VLDTR_E_MAR_NOTPUBPRIV); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - // Implementation must be Nil or valid AssemblyRef or File - tkImplementation = pMiniMd->getImplementationOfManifestResource(pRecord); - if(!IsNilToken(tkImplementation)) - { - switch(TypeFromToken(tkImplementation)) - { - case mdtAssemblyRef: - bIsValidImplementation = IsValidToken(tkImplementation); - break; - case mdtFile: - if((bIsValidImplementation = IsValidToken(tkImplementation))) - { // if file not PE, offset must be 0 - FileRec *pFR; - IfFailGo(pMiniMd->GetFileRecord(RidFromToken(tkImplementation), &pFR)); - if(IsFfContainsNoMetaData(pFR->GetFlags()) - && pRecord->GetOffset()) - { - REPORT_ERROR1(VLDTR_E_MAR_BADOFFSET, tkImplementation); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - break; - default: - bIsValidImplementation = FALSE; - } - } - if(!bIsValidImplementation) - { - REPORT_ERROR1(VLDTR_E_MAR_BADIMPL, tkImplementation); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - // Validate the Offset into the PE file. - - hr = hrSave; -ErrExit: - ; - END_ENTRYPOINT_NOTHROW; - - return hr; -} // RegMeta::ValidateManifestResource() - -//***************************************************************************** -// Validate the given NestedClass. -//***************************************************************************** -HRESULT RegMeta::ValidateNestedClass(RID rid) -{ - CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); // MiniMd for the scope. - NestedClassRec *pRecord; // NestedClass record. - HRESULT hr = S_OK; // Value returned. - HRESULT hrSave = S_OK; // Save the current state. - VEContext veCtxt; // Context structure. - mdToken tkNested; - mdToken tkEncloser; - - BEGIN_ENTRYPOINT_NOTHROW; - - memset(&veCtxt, 0, sizeof(VEContext)); - veCtxt.Token = rid; - veCtxt.uOffset = 0; - - // Get the NestedClass record. - IfFailGo(pMiniMd->GetNestedClassRecord(rid, &pRecord)); - tkNested = pMiniMd->getNestedClassOfNestedClass(pRecord); - tkEncloser = pMiniMd->getEnclosingClassOfNestedClass(pRecord); - - // Nested must be valid TypeDef - if((TypeFromToken(tkNested) != mdtTypeDef) || !IsValidToken(tkNested)) - { - REPORT_ERROR1(VLDTR_E_NC_BADNESTED, tkNested); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // Encloser must be valid TypeDef - if((TypeFromToken(tkEncloser) != mdtTypeDef) || !IsValidToken(tkEncloser)) - { - REPORT_ERROR1(VLDTR_E_NC_BADENCLOSER, tkEncloser); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - // Check for duplicates - { - RID N = pMiniMd->getCountNestedClasss(); - RID tmp; - NestedClassRec* pRecTmp; - mdToken tkEncloserTmp; - for(tmp = rid+1; tmp <= N; tmp++) - { - IfFailGo(pMiniMd->GetNestedClassRecord(tmp, &pRecTmp)); - if(tkNested == pMiniMd->getNestedClassOfNestedClass(pRecTmp)) - { - if(tkEncloser == (tkEncloserTmp = pMiniMd->getEnclosingClassOfNestedClass(pRecTmp))) - { - REPORT_ERROR1(VLDTR_E_NC_DUP, tmp); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - else - { - REPORT_ERROR3(VLDTR_E_NC_DUPENCLOSER, tkNested, tkEncloser, tkEncloserTmp); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - } - } - - hr = hrSave; -ErrExit: - ; - END_ENTRYPOINT_NOTHROW; - - return hr; -} // RegMeta::ValidateLocalVariable() - -//***************************************************************************** -// Given a Table ID and a Row ID, validate all the columns contain meaningful -// values given the column definitions. Validate that the offsets into the -// different pools are valid, the rids are within range and the coded tokens -// are valid. Every failure here is considered an error. -//***************************************************************************** -HRESULT RegMeta::ValidateRecord(ULONG ixTbl, RID rid) -{ - CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); - HRESULT hr = S_OK; // Value returned. - HRESULT hrSave = S_OK; // Save the current state. - ULONG ulCount; // Count of records in the table. - ULONG ulRawColVal; // Raw value of the column. - void *pRow; // Row with the data. - CMiniTableDef *pTbl; // Table definition. - CMiniColDef *pCol; // Column definition. - const CCodedTokenDef *pCdTkn; // Coded token definition. - ULONG ix; // Index into the array of coded tokens. - - BEGIN_ENTRYPOINT_NOTHROW; - - // Get the table definition. - pTbl = &pMiniMd->m_TableDefs[ixTbl]; - - // Get the row. We may assume that the Row pointer we get back from - // this call is correct since we do the verification on the Record - // pools for each table during the open sequence. The only place - // this is not valid is for Dynamic IL and we don't do this - // verification in that case since we go through IMetaData* APIs - // in that case and it should all be consistent. - IfFailGo(m_pStgdb->m_MiniMd.getRow(ixTbl, rid, &pRow)); - - for (ULONG ixCol = 0; ixCol < pTbl->m_cCols; ixCol++) - { - // Get the column definition. - pCol = &pTbl->m_pColDefs[ixCol]; - - // Get the raw value stored in the column. getIX currently doesn't - // handle byte sized fields, but there are some BYTE fields in the - // MetaData. So using the conditional to access BYTE fields. - if (pCol->m_cbColumn == 1) - ulRawColVal = pMiniMd->getI1(pRow, *pCol); - else - ulRawColVal = pMiniMd->getIX(pRow, *pCol); - - // Do some basic checks on the non-absurdity of the value stored in the - // column. - if (IsRidType(pCol->m_Type)) - { - // Verify that the RID is within range. - _ASSERTE(pCol->m_Type < pMiniMd->GetCountTables()); - ulCount = pMiniMd->GetCountRecs(pCol->m_Type); - // For records storing rids to pointer tables, the stored value may - // be one beyond the last record. - if (IsTblPtr(pCol->m_Type, ixTbl)) - ulCount++; - if (ulRawColVal > ulCount) - { - VEContext veCtxt; - memset(&veCtxt, 0, sizeof(VEContext)); - veCtxt.Token = 0; - veCtxt.uOffset = 0; - REPORT_ERROR3(VLDTR_E_RID_OUTOFRANGE, ixTbl, ixCol, rid); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - else if (IsCodedTokenType(pCol->m_Type)) - { - // Verify that the Coded token and rid are valid. - pCdTkn = &g_CodedTokens[pCol->m_Type - iCodedToken]; - ix = ulRawColVal & ~(-1 << CMiniMdRW::m_cb[pCdTkn->m_cTokens]); - if (ix >= pCdTkn->m_cTokens) - { - VEContext veCtxt; - memset(&veCtxt, 0, sizeof(VEContext)); - veCtxt.Token = 0; - veCtxt.uOffset = 0; - REPORT_ERROR3(VLDTR_E_CDTKN_OUTOFRANGE, ixTbl, ixCol, rid); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - ulCount = pMiniMd->GetCountRecs(TypeFromToken(pCdTkn->m_pTokens[ix]) >> 24); - if ( (ulRawColVal >> CMiniMdRW::m_cb[pCdTkn->m_cTokens]) > ulCount) - { - VEContext veCtxt; - memset(&veCtxt, 0, sizeof(VEContext)); - veCtxt.Token = 0; - veCtxt.uOffset = 0; - REPORT_ERROR3(VLDTR_E_CDRID_OUTOFRANGE, ixTbl, ixCol, rid); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - else if (IsHeapType(pCol->m_Type)) - { - // Verify that the offsets for the Heap type fields are valid offsets - // into the heaps. - switch (pCol->m_Type) - { - case iSTRING: - if (!pMiniMd->m_StringHeap.IsValidIndex(ulRawColVal)) - { - VEContext veCtxt; - memset(&veCtxt, 0, sizeof(VEContext)); - veCtxt.Token = 0; - veCtxt.uOffset = 0; - REPORT_ERROR3(VLDTR_E_STRING_INVALID, ixTbl, ixCol, rid); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - break; - case iGUID: - if (ulRawColVal == 0) - { // GUID value 0 is valid value, though it's invalid GUID heap index - break; - } - if (!pMiniMd->m_GuidHeap.IsValidIndex(ulRawColVal)) - { - VEContext veCtxt; - memset(&veCtxt, 0, sizeof(VEContext)); - veCtxt.Token = 0; - veCtxt.uOffset = 0; - REPORT_ERROR3(VLDTR_E_GUID_INVALID, ixTbl, ixCol, rid); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - break; - case iBLOB: - if (! pMiniMd->m_BlobHeap.IsValidIndex(ulRawColVal)) - { - VEContext veCtxt; - memset(&veCtxt, 0, sizeof(VEContext)); - veCtxt.Token = 0; - veCtxt.uOffset = 0; - REPORT_ERROR3(VLDTR_E_BLOB_INVALID, ixTbl, ixCol, rid); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - break; - default: - _ASSERTE(!"Invalid heap type encountered!"); - } - } - else - { - // Not much checking that can be done on the fixed type in a generic sense. - _ASSERTE (IsFixedType(pCol->m_Type)); - } - hr = hrSave; - } -ErrExit: - ; - END_ENTRYPOINT_NOTHROW; - - return hr; -} // RegMeta::ValidateRecord() - -//***************************************************************************** -// This function validates that the given Method signature is consistent as per -// the compression scheme. -//***************************************************************************** -HRESULT RegMeta::ValidateSigCompression( - mdToken tk, // [IN] Token whose signature needs to be validated. - PCCOR_SIGNATURE pbSig, // [IN] Signature. - ULONG cbSig) // [IN] Size in bytes of the signature. -{ - VEContext veCtxt; // Context record. - ULONG ulCurByte = 0; // Current index into the signature. - ULONG ulSize; // Size of uncompressed data at each point. - HRESULT hr = S_OK; // Value returned. - - memset(&veCtxt, 0, sizeof(VEContext)); - veCtxt.Token = tk; - veCtxt.uOffset = 0; - - // Check for NULL signature. - if (!cbSig) - { - REPORT_ERROR0(VLDTR_E_SIGNULL); - SetVldtrCode(&hr, VLDTR_S_ERR); - goto ErrExit; - } - - // Walk through the signature. At each point make sure there is enough - // room left in the signature based on the encoding in the current byte. - while (cbSig - ulCurByte) - { - _ASSERTE(ulCurByte <= cbSig); - // Get next chunk of uncompressed data size. - if ((ulSize = CorSigUncompressedDataSize(pbSig)) > (cbSig - ulCurByte)) - { - REPORT_ERROR1(VLDTR_E_SIGNODATA, ulCurByte+1); - SetVldtrCode(&hr, VLDTR_S_ERR); - goto ErrExit; - } - // Go past this chunk. - ulCurByte += ulSize; - CorSigUncompressData(pbSig); - } -ErrExit: - - return hr; -} // RegMeta::ValidateSigCompression() - -//***************************************************************************** -// This function validates one argument given an offset into the signature -// where the argument begins. This function assumes that the signature is well -// formed as far as the compression scheme is concerned. -//***************************************************************************** -//@GENERICS: todo: reject uninstantiated generic types used as types. -#ifdef _PREFAST_ -#pragma warning(push) -#pragma warning(disable:21000) // Suppress PREFast warning about overly large function -#endif -HRESULT RegMeta::ValidateOneArg( - mdToken tk, // [IN] Token whose signature is being processed. - PCCOR_SIGNATURE &pbSig, // [IN] Pointer to the beginning of argument. - ULONG cbSig, // [IN] Size in bytes of the full signature. - ULONG *pulCurByte, // [IN/OUT] Current offset into the signature.. - ULONG *pulNSentinels, // [IN/OUT] Number of sentinels - BOOL bNoVoidAllowed) // [IN] Flag indicating whether "void" is disallowed for this arg -{ - ULONG ulElementType; // Current element type being processed. - ULONG ulElemSize; // Size of the element type. - mdToken token; // Embedded token. - ULONG ulArgCnt; // Argument count for function pointer. - ULONG ulRank; // Rank of the array. - ULONG ulSizes; // Count of sized dimensions of the array. - ULONG ulLbnds; // Count of lower bounds of the array. - ULONG ulTkSize; // Token size. - VEContext veCtxt; // Context record. - HRESULT hr = S_OK; // Value returned. - HRESULT hrSave = S_OK; // Save state. - BOOL bRepeat = TRUE; // MODOPT and MODREQ belong to the arg after them - BOOL bByRefForbidden = FALSE;// ByRef is not allowed for fields - - BEGIN_ENTRYPOINT_NOTHROW; - - switch(TypeFromToken(tk)) - { - case mdtFieldDef: - bByRefForbidden = TRUE; - break; - case mdtName: - tk = TokenFromRid(RidFromToken(tk),mdtFieldDef); - // Field type can be a FNPTR with a sig containing ByRefs. - // So we change the token type not to be mdtFieldDef and thus allow ByRefs, - // but the token needs to be restored to its original type for reporting - break; - } - - _ASSERTE (pulCurByte); - memset(&veCtxt, 0, sizeof(VEContext)); - veCtxt.Token = tk; - veCtxt.uOffset = 0; - - while(bRepeat) - { - bRepeat = FALSE; - // Validate that the argument is not missing. - _ASSERTE(*pulCurByte <= cbSig); - if (cbSig == *pulCurByte) - { - hr = VLDTR_E_SIG_MISSARG; - goto ErrExit; - } - - // Get the element type. - *pulCurByte += (ulElemSize = CorSigUncompressedDataSize(pbSig)); - ulElementType = CorSigUncompressData(pbSig); - - // Walk past all the modifier types. - while (ulElementType & ELEMENT_TYPE_MODIFIER) - { - _ASSERTE(*pulCurByte <= cbSig); - if(ulElementType == ELEMENT_TYPE_SENTINEL) - { - if(pulNSentinels) *pulNSentinels+=1; - if(TypeFromToken(tk) == mdtMethodDef) - { - REPORT_ERROR0(VLDTR_E_SIG_SENTINMETHODDEF); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - if (cbSig == *pulCurByte) - { - REPORT_ERROR0(VLDTR_E_SIG_LASTSENTINEL); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - goto ErrExit; - } - } - if (cbSig == *pulCurByte) - { - REPORT_ERROR2(VLDTR_E_SIG_MISSELTYPE, ulElementType, *pulCurByte + 1); - SetVldtrCode(&hr, hrSave); - goto ErrExit; - } - *pulCurByte += (ulElemSize = CorSigUncompressedDataSize(pbSig)); - ulElementType = CorSigUncompressData(pbSig); - } - - switch (ulElementType) - { - case ELEMENT_TYPE_VOID: - if(bNoVoidAllowed) - { - IfBreakGo(m_pVEHandler->VEHandler(VLDTR_E_SIG_BADVOID, veCtxt, 0)); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - case ELEMENT_TYPE_BOOLEAN: - case ELEMENT_TYPE_CHAR: - case ELEMENT_TYPE_I1: - case ELEMENT_TYPE_U1: - case ELEMENT_TYPE_I2: - case ELEMENT_TYPE_U2: - case ELEMENT_TYPE_I4: - case ELEMENT_TYPE_U4: - case ELEMENT_TYPE_I8: - case ELEMENT_TYPE_U8: - case ELEMENT_TYPE_R4: - case ELEMENT_TYPE_R8: - case ELEMENT_TYPE_STRING: - case ELEMENT_TYPE_OBJECT: - case ELEMENT_TYPE_TYPEDBYREF: - case ELEMENT_TYPE_U: - case ELEMENT_TYPE_I: - break; - case ELEMENT_TYPE_BYREF: //fallthru - if(bByRefForbidden) - { - IfBreakGo(m_pVEHandler->VEHandler(VLDTR_E_SIG_BYREFINFIELD, veCtxt, 0)); - SetVldtrCode(&hr, hrSave); - } - case ELEMENT_TYPE_PTR: - // Validate the referenced type. - IfFailGo(ValidateOneArg(tk, pbSig, cbSig, pulCurByte,pulNSentinels,FALSE)); - if (hr != S_OK) - SetVldtrCode(&hrSave, hr); - break; - case ELEMENT_TYPE_PINNED: - case ELEMENT_TYPE_SZARRAY: - // Validate the referenced type. - IfFailGo(ValidateOneArg(tk, pbSig, cbSig, pulCurByte,pulNSentinels,TRUE)); - if (hr != S_OK) - SetVldtrCode(&hrSave, hr); - break; - case ELEMENT_TYPE_VALUETYPE: //fallthru - case ELEMENT_TYPE_CLASS: - case ELEMENT_TYPE_CMOD_OPT: - case ELEMENT_TYPE_CMOD_REQD: - // See if the token is missing. - _ASSERTE(*pulCurByte <= cbSig); - if (cbSig == *pulCurByte) - { - REPORT_ERROR1(VLDTR_E_SIG_MISSTKN, ulElementType); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - break; - } - // See if the token is a valid token. - ulTkSize = CorSigUncompressedDataSize(pbSig); - token = CorSigUncompressToken(pbSig); - if (!IsValidToken(token)) - { - REPORT_ERROR2(VLDTR_E_SIG_TKNBAD, token, *pulCurByte); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - *pulCurByte += ulTkSize; - break; - } - *pulCurByte += ulTkSize; - if ((ulElementType == ELEMENT_TYPE_CLASS) || (ulElementType == ELEMENT_TYPE_VALUETYPE)) - { - // Check for long-form encoding - CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); - LPCSTR szName = ""; // token's Name. - LPCSTR szNameSpace = ""; // token's NameSpace. - - - // Check for TypeDef or TypeRef - // To prevent cycles in metadata, token must not be a TypeSpec. - if ((TypeFromToken(token) != mdtTypeRef) && (TypeFromToken(token) != mdtTypeDef)) - { - REPORT_ERROR2(VLDTR_E_SIG_BADTOKTYPE, token, *pulCurByte); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - if (TypeFromToken(token) == mdtTypeRef) - { - TypeRefRec *pTokenRec; - IfFailGo(pMiniMd->GetTypeRefRecord(RidFromToken(token), &pTokenRec)); - mdToken tkResScope = pMiniMd->getResolutionScopeOfTypeRef(pTokenRec); - if (RidFromToken(tkResScope) && (TypeFromToken(tkResScope) == mdtAssemblyRef)) - { - AssemblyRefRec * pARRec; - IfFailGo(pMiniMd->GetAssemblyRefRecord(RidFromToken(tkResScope), &pARRec)); - LPCSTR szAssemblyRefName; - IfFailGo(pMiniMd->getNameOfAssemblyRef(pARRec, &szAssemblyRefName)); - if((0 == SString::_stricmp("mscorlib", szAssemblyRefName)) || (0 == SString::_stricmp("System.Runtime", szAssemblyRefName))) - { - IfFailGo(pMiniMd->getNamespaceOfTypeRef(pTokenRec, &szNameSpace)); - IfFailGo(pMiniMd->getNameOfTypeRef(pTokenRec, &szName)); - } - } - } - else if (TypeFromToken(token) == mdtTypeDef) - { - TypeDefRec *pTokenRec; - IfFailGo(pMiniMd->GetTypeDefRecord(RidFromToken(token), &pTokenRec)); - if(g_fValidatingMscorlib) // otherwise don't even bother checking the name - { - IfFailGo(pMiniMd->getNameOfTypeDef(pTokenRec, &szName)); - IfFailGo(pMiniMd->getNamespaceOfTypeDef(pTokenRec, &szNameSpace)); - } - // while at it, check if token is indeed a class (valuetype) - BOOL bValueType = FALSE; - if(!IsTdInterface(pTokenRec->GetFlags())) - { - mdToken tkExtends = pMiniMd->getExtendsOfTypeDef(pTokenRec); - if(RidFromToken(tkExtends)) - { - LPCSTR szExtName = ""; // parent's Name. - LPCSTR szExtNameSpace = ""; // parent's NameSpace. - if(TypeFromToken(tkExtends)==mdtTypeRef) - { - TypeRefRec *pExtRec; - IfFailGo(pMiniMd->GetTypeRefRecord(RidFromToken(tkExtends), &pExtRec)); - mdToken tkResScope = pMiniMd->getResolutionScopeOfTypeRef(pExtRec); - if(RidFromToken(tkResScope) && (TypeFromToken(tkResScope)==mdtAssemblyRef)) - { - AssemblyRefRec *pARRec; - IfFailGo(pMiniMd->GetAssemblyRefRecord(RidFromToken(tkResScope), &pARRec)); - LPCSTR szAssemblyRefName; - IfFailGo(pMiniMd->getNameOfAssemblyRef(pARRec, &szAssemblyRefName)); - if((0 == SString::_stricmp("mscorlib", szAssemblyRefName)) || (0 == SString::_stricmp("System.Runtime", szAssemblyRefName))) - { - IfFailGo(pMiniMd->getNamespaceOfTypeRef(pExtRec, &szExtNameSpace)); - IfFailGo(pMiniMd->getNameOfTypeRef(pExtRec, &szExtName)); - } - } - } - else if(TypeFromToken(tkExtends)==mdtTypeDef) - { - if(g_fValidatingMscorlib) // otherwise don't even bother checking the name - { - TypeDefRec *pExtRec; - IfFailGo(pMiniMd->GetTypeDefRecord(RidFromToken(tkExtends), &pExtRec)); - IfFailGo(pMiniMd->getNameOfTypeDef(pExtRec, &szExtName)); - IfFailGo(pMiniMd->getNamespaceOfTypeDef(pExtRec, &szExtNameSpace)); - } - } - if(0 == strcmp(szExtNameSpace,BASE_NAMESPACE)) - { - if(0==strcmp(szExtName,BASE_ENUM_CLASSNAME)) bValueType = TRUE; - else if(0==strcmp(szExtName,BASE_VTYPE_CLASSNAME)) - { - bValueType = (strcmp(szNameSpace,BASE_NAMESPACE) || - strcmp(szName,BASE_ENUM_CLASSNAME)); - } - } - } - } - if(bValueType != (ulElementType == ELEMENT_TYPE_VALUETYPE)) - { - REPORT_ERROR2(VLDTR_E_SIG_TOKTYPEMISMATCH, token, *pulCurByte); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - } - if(0 == strcmp(szNameSpace,BASE_NAMESPACE)) - { - for(unsigned jjj = 0; jjj < g_NumSigLongForms; jjj++) - { - if(0 == strcmp(szName,g_SigLongFormName[jjj])) - { - REPORT_ERROR2(VLDTR_E_SIG_LONGFORM, token, *pulCurByte); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - break; - } - } - } - } - else // i.e. if(ELEMENT_TYPE_CMOD_OPT || ELEMENT_TYPE_CMOD_REQD) - bRepeat = TRUE; // go on validating, we're not done with this arg - break; - - case ELEMENT_TYPE_FNPTR: - // Validate that calling convention is present. - _ASSERTE(*pulCurByte <= cbSig); - if (cbSig == *pulCurByte) - { - REPORT_ERROR1(VLDTR_E_SIG_MISSFPTR, *pulCurByte + 1); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - break; - } - // Consume calling convention. - *pulCurByte += CorSigUncompressedDataSize(pbSig); - CorSigUncompressData(pbSig); - - // Validate that argument count is present. - _ASSERTE(*pulCurByte <= cbSig); - if (cbSig == *pulCurByte) - { - REPORT_ERROR1(VLDTR_E_SIG_MISSFPTRARGCNT, *pulCurByte + 1); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - break; - } - // Consume argument count. - *pulCurByte += CorSigUncompressedDataSize(pbSig); - ulArgCnt = CorSigUncompressData(pbSig); - - // Checking the signature, ByRefs OK - if(bByRefForbidden) - tk = TokenFromRid(RidFromToken(tk),mdtName); - - // Validate and consume return type. - IfFailGo(ValidateOneArg(tk, pbSig, cbSig, pulCurByte,NULL,FALSE)); - if (hr != S_OK) - { - SetVldtrCode(&hrSave, VLDTR_S_ERR); - break; - } - - // Validate and consume the arguments. - while(ulArgCnt--) - { - IfFailGo(ValidateOneArg(tk, pbSig, cbSig, pulCurByte,NULL,TRUE)); - if (hr != S_OK) - { - SetVldtrCode(&hrSave, VLDTR_S_ERR); - break; - } - } - break; - - case ELEMENT_TYPE_ARRAY: - // Validate and consume the base type. - IfFailGo(ValidateOneArg(tk, pbSig, cbSig, pulCurByte,pulNSentinels,TRUE)); - - // Validate that the rank is present. - _ASSERTE(*pulCurByte <= cbSig); - if (cbSig == *pulCurByte) - { - REPORT_ERROR1(VLDTR_E_SIG_MISSRANK, *pulCurByte + 1); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - break; - } - // Consume the rank. - *pulCurByte += CorSigUncompressedDataSize(pbSig); - ulRank = CorSigUncompressData(pbSig); - - // Process the sizes. - if (ulRank) - { - // Validate that the count of sized-dimensions is specified. - _ASSERTE(*pulCurByte <= cbSig); - if (cbSig == *pulCurByte) - { - REPORT_ERROR1(VLDTR_E_SIG_MISSNSIZE, *pulCurByte + 1); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - break; - } - // Consume the count of sized dimensions. - *pulCurByte += CorSigUncompressedDataSize(pbSig); - ulSizes = CorSigUncompressData(pbSig); - - // Loop over the sizes. - while (ulSizes--) - { - // Validate the current size. - _ASSERTE(*pulCurByte <= cbSig); - if (cbSig == *pulCurByte) - { - REPORT_ERROR1(VLDTR_E_SIG_MISSSIZE, *pulCurByte + 1); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - break; - } - // Consume the current size. - *pulCurByte += CorSigUncompressedDataSize(pbSig); - CorSigUncompressData(pbSig); - } - - // Validate that the count of lower bounds is specified. - _ASSERTE(*pulCurByte <= cbSig); - if (cbSig == *pulCurByte) - { - REPORT_ERROR1(VLDTR_E_SIG_MISSNLBND, *pulCurByte + 1); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - break; - } - // Consume the count of lower bound. - *pulCurByte += CorSigUncompressedDataSize(pbSig); - ulLbnds = CorSigUncompressData(pbSig); - - // Loop over the lower bounds. - while (ulLbnds--) - { - // Validate the current lower bound. - _ASSERTE(*pulCurByte <= cbSig); - if (cbSig == *pulCurByte) - { - REPORT_ERROR1(VLDTR_E_SIG_MISSLBND, *pulCurByte + 1); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - break; - } - // Consume the current size. - *pulCurByte += CorSigUncompressedDataSize(pbSig); - CorSigUncompressData(pbSig); - } - } - break; - - case ELEMENT_TYPE_VAR: - case ELEMENT_TYPE_MVAR: - // Consume index. - *pulCurByte += CorSigUncompressedDataSize(pbSig); - CorSigUncompressData(pbSig); - break; - - case ELEMENT_TYPE_GENERICINST: - { - PCCOR_SIGNATURE pbGenericTypeSig = pbSig; - BOOL fCheckArity = FALSE; - ULONG ulGenericArity = 0; - - // Validate and consume the type constructor - IfFailGo(ValidateOneArg(tk, pbSig, cbSig, pulCurByte, NULL, TRUE)); - - // Extract its arity - { - CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); - switch(CorSigUncompressElementType(pbGenericTypeSig)) - { - case ELEMENT_TYPE_VALUETYPE: - case ELEMENT_TYPE_CLASS: - { - mdToken tkGenericType = CorSigUncompressToken(pbGenericTypeSig); - if (TypeFromToken(tkGenericType) == mdtTypeDef) - { - HENUMInternal hEnumTyPars; - hr = pMiniMd->FindGenericParamHelper(tkGenericType, &hEnumTyPars); - if (SUCCEEDED(hr)) - { - IfFailGo(HENUMInternal::GetCount(&hEnumTyPars,&ulGenericArity)); - HENUMInternal::ClearEnum(&hEnumTyPars); - fCheckArity = TRUE; - } - ; - } - // for a mdtTypeRef, don't check anything until load time - break; - } - default: - break; - } - - } - - // Consume argument count. - if (cbSig == *pulCurByte) - { - REPORT_ERROR1(VLDTR_E_SIG_MISSARITY, *pulCurByte + 1); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - break; - } - - *pulCurByte += CorSigUncompressedDataSize(pbSig); - ulArgCnt = CorSigUncompressData(pbSig); - - if (ulArgCnt == 0) - { - REPORT_ERROR1(VLDTR_E_SIG_ARITYZERO,*pulCurByte); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - if (fCheckArity && ulArgCnt != ulGenericArity) - { - REPORT_ERROR3(VLDTR_E_SIG_ARITYMISMATCH,ulGenericArity,ulArgCnt,*pulCurByte); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - // Validate and consume the arguments. - while(ulArgCnt--) - { - PCCOR_SIGNATURE pbTypeArg = pbSig; - ULONG ulTypeArgByte = *pulCurByte; - IfFailGo(ValidateOneArg(tk, pbSig, cbSig, pulCurByte, NULL, TRUE)); - if (hr != S_OK) - { - SetVldtrCode(&hrSave, VLDTR_S_ERR); - break; - } - - // reject byref-like args - switch (CorSigUncompressData(pbTypeArg)) - { - case ELEMENT_TYPE_TYPEDBYREF: - case ELEMENT_TYPE_BYREF: - { - REPORT_ERROR1(VLDTR_E_SIG_BYREFINST, ulTypeArgByte); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - break; - } - default: - break; - } - } - - break; - } - - - case ELEMENT_TYPE_SENTINEL: // this case never works because all modifiers are skipped before switch - if(TypeFromToken(tk) == mdtMethodDef) - { - REPORT_ERROR0(VLDTR_E_SIG_SENTINMETHODDEF); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - break; - default: - REPORT_ERROR2(VLDTR_E_SIG_BADELTYPE, ulElementType, *pulCurByte - ulElemSize); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - break; - } // switch (ulElementType) - } // end while(bRepeat) - hr = hrSave; -ErrExit: - ; - END_ENTRYPOINT_NOTHROW; - - return hr; -} // RegMeta::ValidateOneArg() -#ifdef _PREFAST_ -#pragma warning(pop) -#endif - -//***************************************************************************** -// This function validates the given Method signature. This function works -// with Method signature for both the MemberRef and MethodDef. -//***************************************************************************** -HRESULT RegMeta::ValidateMethodSig( - mdToken tk, // [IN] Token whose signature needs to be validated. - PCCOR_SIGNATURE pbSig, // [IN] Signature. - ULONG cbSig, // [IN] Size in bytes of the signature. - DWORD dwFlags) // [IN] Method flags. -{ - ULONG ulCurByte = 0; // Current index into the signature. - ULONG ulCallConv; // Calling convention. - ULONG ulArgCount; // Count of arguments. - ULONG ulTyArgCount; // Count of type arguments. - ULONG i; // Looping index. - VEContext veCtxt; // Context record. - HRESULT hr = S_OK; // Value returned. - HRESULT hrSave = S_OK; // Save state. - ULONG ulNSentinels = 0; - - BEGIN_ENTRYPOINT_NOTHROW; - - _ASSERTE(TypeFromToken(tk) == mdtMethodDef || - TypeFromToken(tk) == mdtMemberRef); - - memset(&veCtxt, 0, sizeof(VEContext)); - veCtxt.Token = tk; - veCtxt.uOffset = 0; - - // Validate the signature is well-formed with respect to the compression - // scheme. If this fails, no further validation needs to be done. - if ((hr = ValidateSigCompression(tk, pbSig, cbSig)) != S_OK) - goto ErrExit; - - // Validate the calling convention. - ulCurByte += CorSigUncompressedDataSize(pbSig); - ulCallConv = CorSigUncompressData(pbSig); - - i = ulCallConv & IMAGE_CEE_CS_CALLCONV_MASK; - if ((i != IMAGE_CEE_CS_CALLCONV_DEFAULT)&&( i != IMAGE_CEE_CS_CALLCONV_VARARG) - || (ulCallConv & IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS)) - { - REPORT_ERROR1(VLDTR_E_MD_BADCALLINGCONV, ulCallConv); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - if (TypeFromToken(tk) == mdtMethodDef) // MemberRefs have no flags available - { - // If HASTHIS is set on the calling convention, the method should not be static. - if ((ulCallConv & IMAGE_CEE_CS_CALLCONV_HASTHIS) && - IsMdStatic(dwFlags)) - { - REPORT_ERROR1(VLDTR_E_MD_THISSTATIC, ulCallConv); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - // If HASTHIS is not set on the calling convention, the method should be static. - if (!(ulCallConv & IMAGE_CEE_CS_CALLCONV_HASTHIS) && - !IsMdStatic(dwFlags)) - { - REPORT_ERROR1(VLDTR_E_MD_NOTTHISNOTSTATIC, ulCallConv); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - - // Get the type argument count. - if (ulCallConv & IMAGE_CEE_CS_CALLCONV_GENERIC) - { - if (i != IMAGE_CEE_CS_CALLCONV_DEFAULT) - { - REPORT_ERROR1(VLDTR_E_MD_GENERIC_BADCALLCONV, ulCallConv); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - if (cbSig == ulCurByte) - { - REPORT_ERROR1(VLDTR_E_MD_MISSARITY, ulCurByte+1); - SetVldtrCode(&hr, hrSave); - goto ErrExit; - } - - ulCurByte += CorSigUncompressedDataSize(pbSig); - ulTyArgCount = CorSigUncompressData(pbSig); - - if (ulTyArgCount == 0) - { - REPORT_ERROR1(VLDTR_E_MD_ARITYZERO, ulCurByte); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - // If this is a def, check the arity against the number of generic params - if (TypeFromToken(tk) == mdtMethodDef) - { - CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); - ULONG ulGenericParamCount; - HENUMInternal hEnumTyPars; - hr = pMiniMd->FindGenericParamHelper(tk, &hEnumTyPars); - if (SUCCEEDED(hr)) - { - IfFailGo(HENUMInternal::GetCount(&hEnumTyPars,&ulGenericParamCount)); - HENUMInternal::ClearEnum(&hEnumTyPars); - if (ulTyArgCount != ulGenericParamCount) - { - REPORT_ERROR2(VLDTR_E_MD_GPMISMATCH,ulTyArgCount,ulGenericParamCount); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - } - } - } - - - // Is there any sig left for arguments? - _ASSERTE(ulCurByte <= cbSig); - if (cbSig == ulCurByte) - { - REPORT_ERROR1(VLDTR_E_MD_NOARGCNT, ulCurByte+1); - SetVldtrCode(&hr, hrSave); - goto ErrExit; - } - - // Get the argument count. - ulCurByte += CorSigUncompressedDataSize(pbSig); - ulArgCount = CorSigUncompressData(pbSig); - - // Validate the return type and the arguments. -// for (i = 0; i < (ulArgCount + 1); i++) - for(i=1; ulCurByte < cbSig; i++) - { - hr = ValidateOneArg(tk, pbSig, cbSig, &ulCurByte,&ulNSentinels,(i > 1)); - if (hr != S_OK) - { - if(hr == VLDTR_E_SIG_MISSARG) - { - REPORT_ERROR1(VLDTR_E_SIG_MISSARG, i); - } - SetVldtrCode(&hr, hrSave); - hrSave = hr; - break; - } - } - if((ulNSentinels != 0) && (!isCallConv(ulCallConv, IMAGE_CEE_CS_CALLCONV_VARARG ))) - { - REPORT_ERROR0(VLDTR_E_SIG_SENTMUSTVARARG); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - if(ulNSentinels > 1) - { - REPORT_ERROR0(VLDTR_E_SIG_MULTSENTINELS); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - hr = hrSave; -ErrExit: - ; - END_ENTRYPOINT_NOTHROW; - - return hr; -} // RegMeta::ValidateMethodSig() - -//***************************************************************************** -// This function validates the given Field signature. This function works -// with Field signature for both the MemberRef and FieldDef. -//***************************************************************************** -HRESULT RegMeta::ValidateFieldSig( - mdToken tk, // [IN] Token whose signature needs to be validated. - PCCOR_SIGNATURE pbSig, // [IN] Signature. - ULONG cbSig) // [IN] Size in bytes of the signature. -{ - ULONG ulCurByte = 0; // Current index into the signature. - ULONG ulCallConv; // Calling convention. - VEContext veCtxt; // Context record. - HRESULT hr = S_OK; // Value returned. - HRESULT hrSave = S_OK; // Save state. - - BEGIN_ENTRYPOINT_NOTHROW; - - _ASSERTE(TypeFromToken(tk) == mdtFieldDef || - TypeFromToken(tk) == mdtMemberRef); - - memset(&veCtxt, 0, sizeof(VEContext)); - veCtxt.Token = tk; - veCtxt.uOffset = 0; - - // Validate the calling convention. - ulCurByte += CorSigUncompressedDataSize(pbSig); - ulCallConv = CorSigUncompressData(pbSig); - if (!isCallConv(ulCallConv, IMAGE_CEE_CS_CALLCONV_FIELD )) - { - REPORT_ERROR1(VLDTR_E_FD_BADCALLINGCONV, ulCallConv); - SetVldtrCode(&hrSave, VLDTR_S_ERR); - } - - // Validate the field. - IfFailGo(ValidateOneArg(tk, pbSig, cbSig, &ulCurByte,NULL,TRUE)); - SetVldtrCode(&hrSave, hr); - - hr = hrSave; -ErrExit: - ; - END_ENTRYPOINT_NOTHROW; - - return hr; -} // RegMeta::ValidateFieldSig() - -//***************************************************************************** -// This is a utility function to allocate a one-dimensional zero-based safe -// array of variants. -//***************************************************************************** -static HRESULT _AllocSafeVariantArrayVector( // Return status. - VARIANT *rVar, // [IN] Variant array. - int cElem, // [IN] Size of the array. - SAFEARRAY **ppArray) // [OUT] Double pointer to SAFEARRAY. -{ - HRESULT hr = S_OK; - LONG i; - - _ASSERTE(rVar && cElem && ppArray); - - IfNullGo(*ppArray = SafeArrayCreateVector(VT_VARIANT, 0, cElem)); - for (i = 0; i < cElem; i++) - IfFailGo(SafeArrayPutElement(*ppArray, &i, &rVar[i])); -ErrExit: - return hr; -} // _AllocSafeVariantArrayVector() - -//***************************************************************************** -// Helper function for reporting error with no arguments -//***************************************************************************** -HRESULT RegMeta::_ValidateErrorHelper( - HRESULT VECode, - VEContext Context) -{ - HRESULT hr = S_OK; - - // - // MDValidator does not zero out the Context. Fix it here. This fix relies - // on the fact that MDValidator just uses the token and offset field of the - // context. - // - - if (Context.Token != 0) { - Context.flags = VER_ERR_TOKEN; - } - - IfBreakGo(m_pVEHandler->VEHandler(VECode, Context, NULL)); -ErrExit: - - return hr; -} // _ValidateErrorHelper() - -//***************************************************************************** -// Helper function for reporting error with 1 argument -//***************************************************************************** -HRESULT RegMeta::_ValidateErrorHelper( - HRESULT VECode, - VEContext Context, - ULONG ulVal1) -{ - HRESULT hr = S_OK; - SAFEARRAY *psa = 0; // The SAFEARRAY. - VARIANT rVar[1]; // The VARIANT array - - if (Context.Token != 0) { - Context.flags = VER_ERR_TOKEN; - } - - V_VT(&rVar[0]) = VT_UI4; - V_UI4(&rVar[0]) = ulVal1; - IfFailGo(_AllocSafeVariantArrayVector(rVar, 1, &psa)); - IfBreakGo(m_pVEHandler->VEHandler(VECode, Context, psa)); - -ErrExit: - if (psa) - { - HRESULT hrSave = SafeArrayDestroy(psa); - if (FAILED(hrSave)) - hr = hrSave; - } - return hr; -} // _ValidateErrorHelper() - -//***************************************************************************** -// Helper function for reporting error with 2 arguments -//***************************************************************************** -HRESULT RegMeta::_ValidateErrorHelper( - HRESULT VECode, - VEContext Context, - ULONG ulVal1, - ULONG ulVal2) -{ - HRESULT hr = S_OK; - SAFEARRAY *psa = 0; // The SAFEARRAY. - VARIANT rVar[2]; // The VARIANT array - - if (Context.Token != 0) { - Context.flags = VER_ERR_TOKEN; - } - - V_VT(&rVar[0]) = VT_UI4; - V_UI4(&rVar[0]) = ulVal1; - V_VT(&rVar[1]) = VT_UI4; - V_UI4(&rVar[1]) = ulVal2; - - IfFailGo(_AllocSafeVariantArrayVector(rVar, 2, &psa)); - IfBreakGo(m_pVEHandler->VEHandler(VECode, Context, psa)); - -ErrExit: - if (psa) - { - HRESULT hrSave = SafeArrayDestroy(psa); - if (FAILED(hrSave)) - hr = hrSave; - } - return hr; -} // _ValidateErrorHelper() - -//***************************************************************************** -// Helper function for reporting error with 3 arguments -//***************************************************************************** -HRESULT RegMeta::_ValidateErrorHelper( - HRESULT VECode, - VEContext Context, - ULONG ulVal1, - ULONG ulVal2, - ULONG ulVal3) -{ - HRESULT hr = S_OK; - SAFEARRAY *psa = 0; // The SAFEARRAY. - VARIANT rVar[3]; // The VARIANT array - - if (Context.Token != 0) { - Context.flags = VER_ERR_TOKEN; - } - - V_VT(&rVar[0]) = VT_UI4; - V_UI4(&rVar[0]) = ulVal1; - V_VT(&rVar[1]) = VT_UI4; - V_UI4(&rVar[1]) = ulVal2; - V_VT(&rVar[2]) = VT_UI4; - V_UI4(&rVar[2]) = ulVal3; - - IfFailGo(_AllocSafeVariantArrayVector(rVar, 3, &psa)); - IfBreakGo(m_pVEHandler->VEHandler(VECode, Context, psa)); - -ErrExit: - if (psa) - { - HRESULT hrSave = SafeArrayDestroy(psa); - if (FAILED(hrSave)) - hr = hrSave; - } - return hr; -} - -//***************************************************************************** -// Helper function to see if there is a duplicate record for ClassLayout. -//***************************************************************************** -static HRESULT _FindClassLayout( - CMiniMdRW *pMiniMd, // [IN] the minimd to lookup - mdTypeDef tkParent, // [IN] the parent that ClassLayout is associated with - RID *pclRid, // [OUT] rid for the ClassLayout. - RID rid) // [IN] rid to be ignored. -{ - HRESULT hr; - ULONG cClassLayoutRecs; - ClassLayoutRec *pRecord; - mdTypeDef tkParTmp; - ULONG i; - - _ASSERTE(pMiniMd && pclRid && rid); - _ASSERTE(TypeFromToken(tkParent) == mdtTypeDef && RidFromToken(tkParent)); - - cClassLayoutRecs = pMiniMd->getCountClassLayouts(); - - for (i = 1; i <= cClassLayoutRecs; i++) - { - // Ignore the rid to be ignored! - if (rid == i) - continue; - - IfFailRet(pMiniMd->GetClassLayoutRecord(i, &pRecord)); - tkParTmp = pMiniMd->getParentOfClassLayout(pRecord); - if (tkParTmp == tkParent) - { - *pclRid = i; - return S_OK; - } - } - return CLDB_E_RECORD_NOTFOUND; -} // _FindClassLayout() - -//***************************************************************************** -// Helper function to see if there is a duplicate for FieldLayout. -//***************************************************************************** -static HRESULT _FindFieldLayout( - CMiniMdRW *pMiniMd, // [IN] the minimd to lookup - mdFieldDef tkParent, // [IN] the parent that FieldLayout is associated with - RID *pflRid, // [OUT] rid for the FieldLayout record. - RID rid) // [IN] rid to be ignored. -{ - HRESULT hr; - ULONG cFieldLayoutRecs; - FieldLayoutRec *pRecord; - mdFieldDef tkField; - ULONG i; - - _ASSERTE(pMiniMd && pflRid && rid); - _ASSERTE(TypeFromToken(tkParent) == mdtFieldDef && RidFromToken(tkParent)); - - cFieldLayoutRecs = pMiniMd->getCountFieldLayouts(); - - for (i = 1; i <= cFieldLayoutRecs; i++) - { - // Ignore the rid to be ignored! - if (rid == i) - continue; - - IfFailRet(pMiniMd->GetFieldLayoutRecord(i, &pRecord)); - tkField = pMiniMd->getFieldOfFieldLayout(pRecord); - if (tkField == tkParent) - { - *pflRid = i; - return S_OK; - } - } - return CLDB_E_RECORD_NOTFOUND; -} // _FindFieldLayout() - -//***************************************************************************** -//***************************************************************************** -HRESULT -MDSigComparer::CompareMethodSignature() -{ - HRESULT hr = S_OK; - - EX_TRY - { - hr = _CompareMethodSignature(); - } - EX_CATCH - { - hr = E_FAIL; - } - EX_END_CATCH(SwallowAllExceptions) - - return hr; -} - -//***************************************************************************** -//***************************************************************************** -HRESULT -MDSigComparer::_CompareMethodSignature() -{ - HRESULT hr; - - // Test equivalency of method signature header - ULONG cArgs; - IfFailRet(_CompareMethodSignatureHeader(cArgs)); - - // Iterate for cArgs + 1 to include the return type - for (ULONG i = 0; i < cArgs + 1; i++) - { - IfFailRet(_CompareExactlyOne()); - } - - return S_OK; -} - -//***************************************************************************** -//***************************************************************************** -HRESULT -MDSigComparer::_CompareExactlyOne() -{ - HRESULT hr; - - CorElementType typ1, typ2; - IfFailRet(m_sig1.GetElemType(&typ1)); - IfFailRet(m_sig2.GetElemType(&typ2)); - - if (typ1 != typ2) - { - return E_FAIL; - } - - CorElementType typ = typ1; - if (!CorIsPrimitiveType((CorElementType)typ)) - { - switch (typ) - { - default: - { - // _ASSERT(!"Illegal or unimplement type in COM+ sig."); - return META_E_BAD_SIGNATURE; - break; - } - case ELEMENT_TYPE_VAR: - case ELEMENT_TYPE_MVAR: - { - IfFailRet(_CompareData(NULL)); // Skip variable number - break; - } - case ELEMENT_TYPE_OBJECT: - case ELEMENT_TYPE_STRING: - case ELEMENT_TYPE_TYPEDBYREF: - { - break; - } - - case ELEMENT_TYPE_BYREF: // fallthru - case ELEMENT_TYPE_PTR: - case ELEMENT_TYPE_PINNED: - case ELEMENT_TYPE_SZARRAY: - { - IfFailRet(_CompareExactlyOne()); // Compare referenced type - break; - } - - case ELEMENT_TYPE_VALUETYPE: // fallthru - case ELEMENT_TYPE_CLASS: - { - mdToken tok1, tok2; - IfFailRet(m_sig1.GetToken(&tok1)); - IfFailRet(m_sig2.GetToken(&tok2)); - IfFailRet(m_comparer.CompareToken(tok1, tok2)); - break; - } - - case ELEMENT_TYPE_FNPTR: - { - IfFailRet(_CompareMethodSignature()); - break; - } - - case ELEMENT_TYPE_ARRAY: - { - IfFailRet(_CompareExactlyOne()); // Compare element type - - ULONG rank; - IfFailRet(_CompareData(&rank)); // Compare & get rank - - if (rank) - { - ULONG nsizes; - IfFailRet(_CompareData(&nsizes)); // Compare & get # of sizes - while (nsizes--) - { - IfFailRet(_CompareData(NULL)); // Compare size - } - - ULONG nlbounds; - IfFailRet(_CompareData(&nlbounds)); // Compare & get # of lower bounds - while (nlbounds--) - { - IfFailRet(_CompareData(NULL)); // Compare lower bounds - } - } - - break; - } - - case ELEMENT_TYPE_SENTINEL: - { - // Should be unreachable since GetElem strips it - break; - } - - case ELEMENT_TYPE_INTERNAL: - { - // Shouldn't ever get this since it is internal to the runtime, - // but just in case we know how to compare and skip these. - PVOID val1 = *((PVOID *)m_sig1.m_ptr); - PVOID val2 = *((PVOID *)m_sig2.m_ptr); - - if (val1 != val2) - { - return E_FAIL; - } - - m_sig1.SkipBytes(sizeof(void*)); - m_sig2.SkipBytes(sizeof(void*)); - break; - } - - case ELEMENT_TYPE_GENERICINST: - { - IfFailRet(_CompareExactlyOne()); // Compare generic type - ULONG argCnt; - IfFailRet(_CompareData(&argCnt)); // Compare & get number of parameters - _ASSERTE(argCnt > 0); - while (argCnt--) - { - IfFailRet(_CompareExactlyOne()); // Compare the parameters - } - break; - } - } - } - - return S_OK; -} - -//***************************************************************************** -//***************************************************************************** -HRESULT -MDSigComparer::_CompareData( - ULONG *pulData) -{ - ULONG cbCompressedData1, cbCompressedData2; - ULONG ulData1, ulData2; - - cbCompressedData1 = CorSigUncompressData(m_sig1.m_ptr, &ulData1); - cbCompressedData2 = CorSigUncompressData(m_sig2.m_ptr, &ulData2); - - if ((cbCompressedData1 == ((ULONG)(-1))) || - (cbCompressedData2 == ((ULONG)(-1))) || - (cbCompressedData1 != cbCompressedData2) || - (ulData1 != ulData2)) - { - return E_FAIL; - } - - m_sig1.SkipBytes(cbCompressedData1); - m_sig2.SkipBytes(cbCompressedData2); - - // Out data - if (pulData) - *pulData = ulData1; - - return S_OK; -} - -//***************************************************************************** -//***************************************************************************** -HRESULT -MDSigComparer::_CompareMethodSignatureHeader( - ULONG &cArgs) -{ - HRESULT hr; - - // Get calling convention information, but only use it to get type param information. - ULONG uCallConv1, uCallConv2; - IfFailRet(m_sig1.GetData(&uCallConv1)); - IfFailRet(m_sig2.GetData(&uCallConv2)); - - // Check type parameter information - ULONG uTypeParamCount1 = 0; - ULONG uTypeParamCount2 = 0; - - if (uCallConv1 & IMAGE_CEE_CS_CALLCONV_GENERIC) - IfFailRet(m_sig1.GetData(&uTypeParamCount1)); - - if (uCallConv2 & IMAGE_CEE_CS_CALLCONV_GENERIC) - IfFailRet(m_sig2.GetData(&uTypeParamCount2)); - - if (uTypeParamCount1 != uTypeParamCount2) - { - return E_FAIL; - } - - // Get arg count - ULONG cArgs1, cArgs2; - IfFailRet(m_sig1.GetData(&cArgs1)); - IfFailRet(m_sig2.GetData(&cArgs2)); - - if (cArgs1 != cArgs2) - { - return E_FAIL; - } - - // Out parameter - cArgs = cArgs1; - - return S_OK; -} - -//***************************************************************************** -//***************************************************************************** - - -HRESULT UnifiedAssemblySigComparer::_CompareAssemblies(mdToken tkAsmRef1,mdToken tkAsmRef2, BOOL* pfEquivalent) -{ - - HRESULT hr; - void const * pvPublicKey1; - ULONG cbPublicKey1; - ULONG cchName1; - ASSEMBLYMETADATA amd1; - void const * pvHashValue; - ULONG cbHashValue; - DWORD dwFlags1; - - void const * pvPublicKey2; - ULONG cbPublicKey2; - ULONG cchName2; - ASSEMBLYMETADATA amd2; - DWORD dwFlags2; - - - ZeroMemory(&amd1, sizeof(amd1)); - ZeroMemory(&amd2, sizeof(amd2)); - - IfFailRet(m_pRegMeta->GetAssemblyRefProps(tkAsmRef1, - NULL, - NULL, - NULL, - 0, - &cchName1, - &amd1, - NULL, - NULL, - NULL)); - - StackSString ssName1; - StackSString ssLocale1; - amd1.szLocale = ssLocale1.OpenUnicodeBuffer(amd1.cbLocale); - - IfFailRet(m_pRegMeta->GetAssemblyRefProps(tkAsmRef1, - &pvPublicKey1, - &cbPublicKey1, - ssName1.OpenUnicodeBuffer(cchName1), - cchName1, - &cchName1, - &amd1, - &pvHashValue, - &cbHashValue, - &dwFlags1)); - - ssName1.CloseBuffer(); - ssLocale1.CloseBuffer(); - - IfFailRet(m_pRegMeta->GetAssemblyRefProps(tkAsmRef2, - NULL, - NULL, - NULL, - 0, - &cchName2, - &amd2, - NULL, - NULL, - NULL)); - - StackSString ssName2; - StackSString ssLocale2; - amd2.szLocale = ssLocale2.OpenUnicodeBuffer(amd2.cbLocale); - - IfFailRet(m_pRegMeta->GetAssemblyRefProps(tkAsmRef2, - &pvPublicKey2, - &cbPublicKey2, - ssName2.OpenUnicodeBuffer(cchName2), - cchName2, - &cchName2, - &amd2, - &pvHashValue, - &cbHashValue, - &dwFlags2)); - - ssName2.CloseBuffer(); - ssLocale2.CloseBuffer(); - - StackSString sMscorlib(W("mscorlib")); - - - if(ssName1.CompareCaseInsensitive(sMscorlib)==0 && - ssName2.CompareCaseInsensitive(sMscorlib)==0 ) - { - *pfEquivalent=TRUE; - return S_OK; - } - - *pfEquivalent=FALSE; - - if (ssName1.CompareCaseInsensitive(ssName2)!=0) - return S_OK; - if (ssLocale1.CompareCaseInsensitive(ssLocale2)!=0) - return S_OK; - if(cbPublicKey1!=cbPublicKey2) - return S_OK; - if(memcmp(pvPublicKey1,pvPublicKey2,cbPublicKey1)!=0) - return S_OK; - if(dwFlags1!=dwFlags2) - return S_OK; - if(amd1.usMajorVersion!=amd2.usMajorVersion) - return S_OK; - if(amd1.usMinorVersion!=amd2.usMinorVersion) - return S_OK; - if(amd1.usBuildNumber!=amd2.usBuildNumber) - return S_OK; - if(amd1.usRevisionNumber!=amd2.usRevisionNumber) - return S_OK; - - *pfEquivalent=TRUE; - return S_OK; - -}; - -//***************************************************************************** -//***************************************************************************** -HRESULT -UnifiedAssemblySigComparer::_CreateTypeNameFromTypeRef( - mdToken tkTypeRef, - SString &ssName, - mdToken &tkParent) -{ - HRESULT hr; - - // Get the parent token as well as the name, and return. - ULONG cchTypeRef; - IfFailRet(m_pRegMeta->GetTypeRefProps(tkTypeRef, NULL, NULL, 0, &cchTypeRef)); - IfFailRet(m_pRegMeta->GetTypeRefProps(tkTypeRef, &tkParent, ssName.OpenUnicodeBuffer(cchTypeRef), cchTypeRef, NULL)); - ssName.CloseBuffer(); - - return S_OK; -} - -//***************************************************************************** -//***************************************************************************** -HRESULT -UnifiedAssemblySigComparer::_CreateFullyQualifiedTypeNameFromTypeRef( - mdToken tkTypeRef, - SString &ssFullName, - mdToken &tkParent) -{ - HRESULT hr; - - StackSString ssBuf; - StackSString ssName; - mdToken tok = tkTypeRef; - BOOL fFirstLoop = TRUE; - - // Loop stops at first non-typeref parent token. - do - { - // Get the name for this token, as well as the parent token value. - IfFailRet(_CreateTypeNameFromTypeRef(tok, ssName, tok)); - - // If this is the first time through the loop, just assign values. - if (fFirstLoop) - { - ssFullName = ssName; - fFirstLoop = FALSE; - } - // If this isn't the first time through, make nested type name - else - { - ns::MakeNestedTypeName(ssBuf, ssName, ssFullName); - ssFullName = ssBuf; - } - } while (TypeFromToken(tok) == mdtTypeRef); - - // Assign non-typeref token parent - tkParent = tok; - - return S_OK; -} - - - -//***************************************************************************** -//***************************************************************************** -HRESULT -UnifiedAssemblySigComparer::CompareToken( - const mdToken &tok1, - const mdToken &tok2) -{ - HRESULT hr; - - // Check binary equality - if (tok1 == tok2) - { - return S_OK; - } - - // Currently only want to do extra checking on TypeRefs - if (TypeFromToken(tok1) != mdtTypeRef || TypeFromToken(tok2) != mdtTypeRef) - { - return E_FAIL; - } - - // Get the fully qualified type names as well as the non-typeref parents. - mdToken tkParent1, tkParent2; - StackSString ssName1, ssName2; - - IfFailRet(_CreateFullyQualifiedTypeNameFromTypeRef(tok1, ssName1, tkParent1)); - IfFailRet(_CreateFullyQualifiedTypeNameFromTypeRef(tok2, ssName2, tkParent2)); - - // Currently only want to do extra checking if the parent tokens are AssemblyRefs - if (TypeFromToken(tkParent1) != mdtAssemblyRef || TypeFromToken(tkParent2) != mdtAssemblyRef) - { - return E_FAIL; - } - - // If the type names are not equal, no need to check the assembly refs for unification since - // we know the types couldn't possibly match. - if (!ssName1.Equals(ssName2)) - { - return E_FAIL; - } - BOOL fEquivalent; - - // no redirects supported - IfFailRet(_CompareAssemblies(tkParent1,tkParent2,&fEquivalent)); - - if (!fEquivalent) - { - return E_FAIL; - } - - return S_OK; -} - - -//***************************************************************************** -// Helper function to validate a locale. -//***************************************************************************** -static const char* const g_szValidLocale_V1[] = { -"ar","ar-SA","ar-IQ","ar-EG","ar-LY","ar-DZ","ar-MA","ar-TN","ar-OM","ar-YE","ar-SY","ar-JO","ar-LB","ar-KW","ar-AE","ar-BH","ar-QA", -"bg","bg-BG", -"ca","ca-ES", -"zh-CHS","zh-TW","zh-CN","zh-HK","zh-SG","zh-MO","zh-CHT", -"cs","cs-CZ", -"da","da-DK", -"de","de-DE","de-CH","de-AT","de-LU","de-LI", -"el","el-GR", -"en","en-US","en-GB","en-AU","en-CA","en-NZ","en-IE","en-ZA","en-JM","en-CB","en-BZ","en-TT","en-ZW","en-PH", -"es","es-ES-Ts","es-MX","es-ES","es-GT","es-CR","es-PA","es-DO","es-VE","es-CO","es-PE","es-AR","es-EC","es-CL", -"es-UY","es-PY","es-BO","es-SV","es-HN","es-NI","es-PR", -"fi","fi-FI", -"fr","fr-FR","fr-BE","fr-CA","fr-CH","fr-LU","fr-MC", -"he","he-IL", -"hu","hu-HU", -"is","is-IS", -"it","it-IT","it-CH", -"ja","ja-JP", -"ko","ko-KR", -"nl","nl-NL","nl-BE", -"no", -"nb-NO", -"nn-NO", -"pl","pl-PL", -"pt","pt-BR","pt-PT", -"ro","ro-RO", -"ru","ru-RU", -"hr","hr-HR", -"sk","sk-SK", -"sq","sq-AL", -"sv","sv-SE","sv-FI", -"th","th-TH", -"tr","tr-TR", -"ur","ur-PK", -"id","id-ID", -"uk","uk-UA", -"be","be-BY", -"sl","sl-SI", -"et","et-EE", -"lv","lv-LV", -"lt","lt-LT", -"fa","fa-IR", -"vi","vi-VN", -"hy","hy-AM", -"az", -"eu","eu-ES", -"mk","mk-MK", -"af","af-ZA", -"ka","ka-GE", -"fo","fo-FO", -"hi","hi-IN", -"ms","ms-MY","ms-BN", -"kk","kk-KZ", -"ky","ky-KZ", -"sw","sw-KE", -"uz", -"tt","tt-RU", -"pa","pa-IN", -"gu","gu-IN", -"ta","ta-IN", -"te","te-IN", -"kn","kn-IN", -"mr","mr-IN", -"sa","sa-IN", -"mn","mn-MN", -"gl","gl-ES", -"kok","kok-IN", -"syr","syr-SY", -"div" -}; - -static const char* const g_szValidLocale_V2[] = { - "bn", "bn-IN", - "bs-Latn-BA", "bs-Cyrl-BA", - "hr-BA", - "fil", "fil-PH", - "fy", "fy-NL", - "iu-Latn-CA", - "ga", "ga-IE", - "ky-KG", - "lb", "lb-LU", - "ml", "ml-IN", - "mt", "mt-MT", - "mi", "mi-NZ", - "arn", "arn-CL", - "moh", "moh-CA", - "ne", "ne-NP", - "ps", "ps-AF", - "quz", "quz-BO", "quz-EC", "quz-PE", - "rm", "rm-CH", - "smn", "smn-FI", - "smj" , "smj-SE", "smj-NO", - "se", "se-NO", "se-SE", "se-FI", - "sms", "sms-FI", - "sma", "sma-NO", "sma-SE", - "sr-Latn-BA", "sr-Cyrl-BA", - "nso", "nso-ZA" -}; - -// Pre-vista specific cultures (renamed on Vista) -static const char* const g_szValidLocale_PreVista[] = { - "div-MV", - "sr-SP-Latn", "sr-SP-Cyrl", - "az-AZ-Latn", "az-AZ-Cyrl", - "uz-UZ-Latn", "uz-UZ-Cyrl", -}; - -// Vista only specific cultures (renamed and freshly introduced) -static const char * const g_szValidLocale_Vista[] = { - "dv-MV", - "sr-Latn-CS", "sr-Cyrl-CS", - "az-Latn-AZ", "az-Cyrl-AZ", - "uz-Latn-UZ", "uz-Cyrl-UZ", - "zh-Hant", "zh-Hans", - "gsw", "gsw-FR", - "am", "am-ET", - "as", "as-IN", - "ba", "ba-RU", - "br", "br-FR", - "en-IN", - "kl", "kl-GL", - "iu-Cans-CA", - "km", "km-KH", - "lo", "lo-LA", - "dsb", "dsb-DE", - "mn-Mong-CN", - "oc", "oc-FR", - "or", "or-IN" -}; - -static BOOL FindInArray(LPCUTF8 szLocale, const char * const *cultureArr, const int nCultures) -{ - for (int i = 0; i < nCultures; i++) - { - if(!SString::_stricmp(szLocale, cultureArr[i])) - return TRUE; - } - return FALSE; -} - -#define LENGTH_OF(x) (sizeof(x) / sizeof(x[0])) - -// For Everett assemblies, only the preVista cultures are valid even if running on Vista. -static BOOL _IsValidLocale(LPCUTF8 szLocale, - BOOL fIsV2Assembly) -{ - if (szLocale && *szLocale) - { - // Locales valid for Everett and Whidbey - if (FindInArray(szLocale, g_szValidLocale_V1, LENGTH_OF(g_szValidLocale_V1))) - return TRUE; - - // Locales valid for Whidbey assemblies only - if (fIsV2Assembly && - FindInArray(szLocale, g_szValidLocale_V2, LENGTH_OF(g_szValidLocale_V2))) - return TRUE; - - // Finally search OS specific cultures - if (fIsV2Assembly) - return FindInArray(szLocale, g_szValidLocale_Vista, LENGTH_OF(g_szValidLocale_Vista)); - else - return FindInArray(szLocale, g_szValidLocale_PreVista, LENGTH_OF(g_szValidLocale_PreVista)); - } - - return TRUE; -} - -#endif //FEATURE_METADATA_VALIDATOR diff --git a/src/md/compiler/regmeta.cpp b/src/md/compiler/regmeta.cpp index f591a6e01b..170893e054 100644 --- a/src/md/compiler/regmeta.cpp +++ b/src/md/compiler/regmeta.cpp @@ -67,7 +67,6 @@ RegMeta::RegMeta() : m_trLanguageType(0), m_SetAPICaller(EXTERNAL_CALLER), m_ModuleType(ValidatorModuleTypeInvalid), - m_pVEHandler(0), m_bKeepKnownCa(false), m_pCorProfileData(NULL), m_ReorderingOptions(NoReordering) @@ -156,9 +155,6 @@ RegMeta::~RegMeta() delete pCur; } - if (m_pVEHandler) - m_pVEHandler->Release(); - // If This RegMeta spun up the runtime (probably to process security // attributes), shut it down now. if (m_fStartedEE) diff --git a/src/md/compiler/regmeta.h b/src/md/compiler/regmeta.h index 04456d8548..0c6124653d 100644 --- a/src/md/compiler/regmeta.h +++ b/src/md/compiler/regmeta.h @@ -22,7 +22,6 @@ #include "rwutil.h" #include "mdperf.h" -#include <ivehandler.h> #include "sigparser.h" @@ -157,10 +156,6 @@ class RegMeta : , public IMetaDataAssemblyEmit #endif -#ifdef FEATURE_METADATA_VALIDATOR - , public IMetaDataValidate -#endif - #ifdef FEATURE_METADATA_EMIT_ALL , public IMetaDataFilter #endif @@ -1195,18 +1190,6 @@ public: #endif //FEATURE_METADATA_EMIT -#ifdef FEATURE_METADATA_VALIDATOR -//***************************************************************************** -// IMetaDataValidator -//***************************************************************************** - - STDMETHODIMP ValidatorInit( - DWORD dwModuleType, // [IN] Specifies whether the module is a PE file or an obj. - IUnknown * pUnk); // [IN] Validation error handler. - - STDMETHODIMP ValidateMetaData(); -#endif //FEATURE_METADATA_VALIDATOR - #ifdef FEATURE_METADATA_EMIT_ALL //***************************************************************************** // IMetaDataFilter @@ -2040,7 +2023,6 @@ private: SetAPICallerType m_SetAPICaller; CorValidatorModuleType m_ModuleType; - IVEHandler *m_pVEHandler; CCustAttrHash m_caHash; // Hashed list of custom attribute types seen. bool m_bKeepKnownCa; // Should all known CA's be kept? @@ -2055,28 +2037,6 @@ private: // There is an equivalent state in MiniMD, and both must be // TRUE in order to delete safely. #endif - - HRESULT _ValidateErrorHelper( - HRESULT VECode, - VEContext Context); - - HRESULT _ValidateErrorHelper( - HRESULT VECode, - VEContext Context, - ULONG ulVal1); - - HRESULT _ValidateErrorHelper( - HRESULT VECode, - VEContext Context, - ULONG ulVal1, - ULONG ulVal2); - - HRESULT _ValidateErrorHelper( - HRESULT VECode, - VEContext Context, - ULONG ulVal1, - ULONG ulVal2, - ULONG ulVal3); private: // Returns pointer to zeros of size (cbSize). |