// 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. // =========================================================================== // File: MDInternalRO.CPP // // Notes: // // // =========================================================================== #include "stdafx.h" #include "mdinternalro.h" #include "metamodelro.h" #include "liteweightstgdb.h" #include "corhlpr.h" #include "../compiler/regmeta.h" #include "caparser.h" #ifdef FEATURE_METADATA_INTERNAL_APIS __checkReturn HRESULT _FillMDDefaultValue( BYTE bType, void const *pValue, ULONG cbValue, MDDefaultValue *pMDDefaultValue); #ifndef DACCESS_COMPILE __checkReturn HRESULT TranslateSigHelper( // S_OK or error. IMDInternalImport *pImport, // [IN] import scope. IMDInternalImport *pAssemImport, // [IN] import assembly scope. const void *pbHashValue, // [IN] hash value for the import assembly. ULONG cbHashValue, // [IN] count of bytes in the hash value. PCCOR_SIGNATURE pbSigBlob, // [IN] signature in the importing scope ULONG cbSigBlob, // [IN] count of bytes of signature IMetaDataAssemblyEmit *pAssemEmit, // [IN] assembly emit scope. IMetaDataEmit *emit, // [IN] emit interface CQuickBytes *pqkSigEmit, // [OUT] buffer to hold translated signature ULONG *pcbSig); // [OUT] count of bytes in the translated signature #endif //!DACCESS_COMPILE __checkReturn HRESULT GetInternalWithRWFormat( LPVOID pData, ULONG cbData, DWORD flags, // [IN] MDInternal_OpenForRead or MDInternal_OpenForENC REFIID riid, // [in] The interface desired. void **ppIUnk); // [out] Return interface on success. // forward declaration __checkReturn HRESULT MDApplyEditAndContinue( // S_OK or error. IMDInternalImport **ppIMD, // [in, out] The metadata to be updated. IMDInternalImportENC *pDeltaMD); // [in] The delta metadata. //***************************************************************************** // Constructor //***************************************************************************** MDInternalRO::MDInternalRO() : m_pMethodSemanticsMap(0), m_cRefs(1) { } // MDInternalRO::MDInternalRO //***************************************************************************** // Destructor //***************************************************************************** MDInternalRO::~MDInternalRO() { m_LiteWeightStgdb.Uninit(); if (m_pMethodSemanticsMap) delete[] m_pMethodSemanticsMap; m_pMethodSemanticsMap = 0; } // MDInternalRO::~MDInternalRO //***************************************************************************** // IUnknown //***************************************************************************** ULONG MDInternalRO::AddRef() { return InterlockedIncrement(&m_cRefs); } // MDInternalRO::AddRef ULONG MDInternalRO::Release() { ULONG cRef = InterlockedDecrement(&m_cRefs); if (cRef == 0) delete this; return cRef; } // MDInternalRO::Release __checkReturn HRESULT MDInternalRO::QueryInterface(REFIID riid, void **ppUnk) { *ppUnk = 0; if (riid == IID_IUnknown) *ppUnk = this; // ! QI for IID_IUnknown must return MDInternalRO. ConvertRO2RW() has dependency on this. else if (riid == IID_IMDInternalImport) *ppUnk = (IMDInternalImport *)this; else if (riid == IID_IMDCommon) *ppUnk = (IMDCommon *)this; else return E_NOINTERFACE; AddRef(); return S_OK; } // MDInternalRO::QueryInterface //***************************************************************************** // Initialize //***************************************************************************** __checkReturn HRESULT MDInternalRO::Init( LPVOID pData, // points to meta data section in memory ULONG cbData) // count of bytes in pData { m_tdModule = COR_GLOBAL_PARENT_TOKEN; extern HRESULT _CallInitOnMemHelper(CLiteWeightStgdb *pStgdb, ULONG cbData, LPCVOID pData); return _CallInitOnMemHelper(&m_LiteWeightStgdb, cbData, (BYTE*) pData); } // MDInternalRO::Init #ifndef DACCESS_COMPILE //***************************************************************************** // Given a scope, determine whether imported from a typelib. //***************************************************************************** __checkReturn HRESULT MDInternalRO::TranslateSigWithScope( IMDInternalImport* pAssemImport, // [IN] import assembly scope. const void* pbHashValue, // [IN] hash value for the import assembly. ULONG cbHashValue, // [IN] count of bytes in the hash value. PCCOR_SIGNATURE pbSigBlob, // [IN] signature in the importing scope ULONG cbSigBlob, // [IN] count of bytes of signature IMetaDataAssemblyEmit* pAssemEmit, // [IN] assembly emit scope. IMetaDataEmit* emit, // [IN] emit interface CQuickBytes* pqkSigEmit, // [OUT] buffer to hold translated signature ULONG* pcbSig) // [OUT] count of bytes in the translated signature { return TranslateSigHelper( this, pAssemImport, pbHashValue, cbHashValue, pbSigBlob, cbSigBlob, pAssemEmit, emit, pqkSigEmit, pcbSig); } // MDInternalRO::TranslateSigWithScope #endif // DACCESS_COMPILE __checkReturn HRESULT MDInternalRO::GetTypeDefRefTokenInTypeSpec(// return S_FALSE if enclosing type does not have a token mdTypeSpec tkTypeSpec, // [IN] TypeSpec token to look at mdToken *tkEnclosedToken) // [OUT] The enclosed type token { return m_LiteWeightStgdb.m_MiniMd.GetTypeDefRefTokenInTypeSpec(tkTypeSpec, tkEnclosedToken); } // MDInternalRO::GetTypeDefRefTokenInTypeSpec #ifndef DACCESS_COMPILE //***************************************************************************** // Given a scope, return the number of tokens in a given table //***************************************************************************** ULONG MDInternalRO::GetCountWithTokenKind( // return hresult DWORD tkKind) // [IN] pass in the kind of token. { ULONG ulCount = m_LiteWeightStgdb.m_MiniMd.CommonGetRowCount(tkKind); if (tkKind == mdtTypeDef) { // Remove global typedef from the count of typedefs (and handle the case where there is no global typedef) if (ulCount > 0) ulCount--; } return ulCount; } // MDInternalRO::GetCountWithTokenKind #endif //!DACCESS_COMPILE //******************************************************************************* // Enumerator helpers //******************************************************************************* //***************************************************************************** // enumerator init for typedef //***************************************************************************** __checkReturn HRESULT MDInternalRO::EnumTypeDefInit( // return hresult HENUMInternal *phEnum) // [OUT] buffer to fill for enumerator data { HRESULT hr = NOERROR; _ASSERTE(phEnum); memset(phEnum, 0, sizeof(HENUMInternal)); phEnum->m_tkKind = mdtTypeDef; phEnum->m_EnumType = MDSimpleEnum; phEnum->m_ulCount = m_LiteWeightStgdb.m_MiniMd.getCountTypeDefs(); // Skip over the global model typedef // // phEnum->u.m_ulCur : the current rid that is not yet enumerated // phEnum->u.m_ulStart : the first rid that will be returned by enumerator // phEnum->u.m_ulEnd : the last rid that will be returned by enumerator phEnum->u.m_ulStart = phEnum->u.m_ulCur = 2; phEnum->u.m_ulEnd = phEnum->m_ulCount + 1; if (phEnum->m_ulCount > 0) phEnum->m_ulCount --; return hr; } // MDInternalRO::EnumTypeDefInit //***************************************************************************** // get the number of typedef in a scope //***************************************************************************** ULONG MDInternalRO::EnumTypeDefGetCount( HENUMInternal *phEnum) // [IN] the enumerator to retrieve information { _ASSERTE(phEnum->m_tkKind == mdtTypeDef); return phEnum->m_ulCount; } // MDInternalRO::EnumTypeDefGetCount //***************************************************************************** // enumerator for typedef //***************************************************************************** bool MDInternalRO::EnumTypeDefNext( // return hresult HENUMInternal *phEnum, // [IN] input enum mdTypeDef *ptd) // [OUT] return token { _ASSERTE(phEnum && ptd); if (phEnum->u.m_ulCur >= phEnum->u.m_ulEnd) return false; *ptd = phEnum->u.m_ulCur++; RidToToken(*ptd, mdtTypeDef); return true; } // MDInternalRO::EnumTypeDefNext //***************************************** // Reset the enumerator to the beginning. //***************************************** void MDInternalRO::EnumTypeDefReset( HENUMInternal *phEnum) // [IN] the enumerator to be reset { _ASSERTE(phEnum); _ASSERTE( phEnum->m_EnumType == MDSimpleEnum ); // not using CRCURSOR phEnum->u.m_ulCur = phEnum->u.m_ulStart; } // MDInternalRO::EnumTypeDefReset //***************************************** // Close the enumerator. Only for read/write mode that we need to close the cursor. // Hopefully with readonly mode, it will be a no-op //***************************************** void MDInternalRO::EnumTypeDefClose( HENUMInternal *phEnum) // [IN] the enumerator to be closed { _ASSERTE( phEnum->m_EnumType == MDSimpleEnum ); } // MDInternalRO::EnumTypeDefClose //***************************************************************************** // Enumerator init for MethodImpl. The second HENUMInternal* parameter is // only used for the R/W version of the MetaData. //***************************************************************************** __checkReturn HRESULT MDInternalRO::EnumMethodImplInit( // return hresult mdTypeDef td, // [IN] TypeDef over which to scope the enumeration. HENUMInternal *phEnumBody, // [OUT] buffer to fill for enumerator data for MethodBody tokens. HENUMInternal *phEnumDecl) // [OUT] buffer to fill for enumerator data for MethodDecl tokens. { return EnumInit(TBL_MethodImpl << 24, td, phEnumBody); } // MDInternalRO::EnumMethodImplInit //***************************************************************************** // get the number of MethodImpls in a scope //***************************************************************************** ULONG MDInternalRO::EnumMethodImplGetCount( HENUMInternal *phEnumBody, // [IN] MethodBody enumerator. HENUMInternal *phEnumDecl) // [IN] MethodDecl enumerator. { _ASSERTE(phEnumBody && ((phEnumBody->m_tkKind >> 24) == TBL_MethodImpl)); return phEnumBody->m_ulCount; } // MDInternalRO::EnumMethodImplGetCount //***************************************************************************** // enumerator for MethodImpl. //***************************************************************************** __checkReturn HRESULT MDInternalRO::EnumMethodImplNext( // return hresult HENUMInternal *phEnumBody, // [IN] input enum for MethodBody HENUMInternal *phEnumDecl, // [IN] input enum for MethodDecl mdToken *ptkBody, // [OUT] return token for MethodBody mdToken *ptkDecl) // [OUT] return token for MethodDecl { HRESULT hr; MethodImplRec *pRecord; _ASSERTE(phEnumBody && ((phEnumBody->m_tkKind >> 24) == TBL_MethodImpl)); _ASSERTE(ptkBody && ptkDecl); if (phEnumBody->u.m_ulCur >= phEnumBody->u.m_ulEnd) { return S_FALSE; } IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodImplRecord(phEnumBody->u.m_ulCur, &pRecord)); *ptkBody = m_LiteWeightStgdb.m_MiniMd.getMethodBodyOfMethodImpl(pRecord); *ptkDecl = m_LiteWeightStgdb.m_MiniMd.getMethodDeclarationOfMethodImpl(pRecord); phEnumBody->u.m_ulCur++; return S_OK; } // MDInternalRO::EnumMethodImplNext //***************************************** // Reset the enumerator to the beginning. //***************************************** void MDInternalRO::EnumMethodImplReset( HENUMInternal *phEnumBody, // [IN] MethodBody enumerator. HENUMInternal *phEnumDecl) // [IN] MethodDecl enumerator. { _ASSERTE(phEnumBody && ((phEnumBody->m_tkKind >> 24) == TBL_MethodImpl)); _ASSERTE(phEnumBody->m_EnumType == MDSimpleEnum); phEnumBody->u.m_ulCur = phEnumBody->u.m_ulStart; } // MDInternalRO::EnumMethodImplReset //***************************************** // Close the enumerator. //***************************************** void MDInternalRO::EnumMethodImplClose( HENUMInternal *phEnumBody, // [IN] MethodBody enumerator. HENUMInternal *phEnumDecl) // [IN] MethodDecl enumerator. { _ASSERTE(phEnumBody && ((phEnumBody->m_tkKind >> 24) == TBL_MethodImpl)); _ASSERTE(phEnumBody->m_EnumType == MDSimpleEnum); } // MDInternalRO::EnumMethodImplClose //****************************************************************************** // enumerator for global functions //****************************************************************************** __checkReturn HRESULT MDInternalRO::EnumGlobalFunctionsInit( // return hresult HENUMInternal *phEnum) // [OUT] buffer to fill for enumerator data { return EnumInit(mdtMethodDef, m_tdModule, phEnum); } //****************************************************************************** // enumerator for global Fields //****************************************************************************** __checkReturn HRESULT MDInternalRO::EnumGlobalFieldsInit( // return hresult HENUMInternal *phEnum) // [OUT] buffer to fill for enumerator data { return EnumInit(mdtFieldDef, m_tdModule, phEnum); } //***************************************** // Enumerator initializer //***************************************** __checkReturn HRESULT MDInternalRO::EnumInit( // return S_FALSE if record not found DWORD tkKind, // [IN] which table to work on mdToken tkParent, // [IN] token to scope the search HENUMInternal *phEnum) // [OUT] the enumerator to fill { HRESULT hr = S_OK; ULONG ulMax = 0; // Vars for query. _ASSERTE(phEnum); HENUMInternal::ZeroEnum(phEnum); // cache the tkKind and the scope phEnum->m_tkKind = TypeFromToken(tkKind); TypeDefRec *pRec; phEnum->m_EnumType = MDSimpleEnum; switch (TypeFromToken(tkKind)) { case mdtFieldDef: IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetTypeDefRecord(RidFromToken(tkParent), &pRec)); phEnum->u.m_ulStart = m_LiteWeightStgdb.m_MiniMd.getFieldListOfTypeDef(pRec); IfFailGo(m_LiteWeightStgdb.m_MiniMd.getEndFieldListOfTypeDef(RidFromToken(tkParent), &(phEnum->u.m_ulEnd))); break; case mdtMethodDef: IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetTypeDefRecord(RidFromToken(tkParent), &pRec)); phEnum->u.m_ulStart = m_LiteWeightStgdb.m_MiniMd.getMethodListOfTypeDef(pRec); IfFailGo(m_LiteWeightStgdb.m_MiniMd.getEndMethodListOfTypeDef(RidFromToken(tkParent), &(phEnum->u.m_ulEnd))); break; case mdtGenericParam: _ASSERTE(TypeFromToken(tkParent) == mdtTypeDef || TypeFromToken(tkParent) == mdtMethodDef); if (TypeFromToken(tkParent) != mdtTypeDef && TypeFromToken(tkParent) != mdtMethodDef) IfFailGo(CLDB_E_FILE_CORRUPT); if (TypeFromToken(tkParent) == mdtTypeDef) { IfFailGo(m_LiteWeightStgdb.m_MiniMd.getGenericParamsForTypeDef( RidFromToken(tkParent), &phEnum->u.m_ulEnd, &(phEnum->u.m_ulStart))); } else { IfFailGo(m_LiteWeightStgdb.m_MiniMd.getGenericParamsForMethodDef( RidFromToken(tkParent), &phEnum->u.m_ulEnd, &(phEnum->u.m_ulStart))); } break; case mdtGenericParamConstraint: IfFailGo(m_LiteWeightStgdb.m_MiniMd.getGenericParamConstraintsForGenericParam( RidFromToken(tkParent), &phEnum->u.m_ulEnd, &phEnum->u.m_ulStart)); break; case mdtInterfaceImpl: IfFailGo(m_LiteWeightStgdb.m_MiniMd.getInterfaceImplsForTypeDef(RidFromToken(tkParent), &phEnum->u.m_ulEnd, &phEnum->u.m_ulStart)); break; case mdtProperty: RID ridPropertyMap; PropertyMapRec *pPropertyMapRec; // get the starting/ending rid of properties of this typedef IfFailGo(m_LiteWeightStgdb.m_MiniMd.FindPropertyMapFor(RidFromToken(tkParent), &ridPropertyMap)); if (!InvalidRid(ridPropertyMap)) { IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetPropertyMapRecord(ridPropertyMap, &pPropertyMapRec)); phEnum->u.m_ulStart = m_LiteWeightStgdb.m_MiniMd.getPropertyListOfPropertyMap(pPropertyMapRec); IfFailGo(m_LiteWeightStgdb.m_MiniMd.getEndPropertyListOfPropertyMap(ridPropertyMap, &(phEnum->u.m_ulEnd))); ulMax = m_LiteWeightStgdb.m_MiniMd.getCountPropertys() + 1; if(phEnum->u.m_ulStart == 0) phEnum->u.m_ulStart = 1; if(phEnum->u.m_ulEnd > ulMax) phEnum->u.m_ulEnd = ulMax; if(phEnum->u.m_ulStart > phEnum->u.m_ulEnd) phEnum->u.m_ulStart = phEnum->u.m_ulEnd; } break; case mdtEvent: RID ridEventMap; EventMapRec *pEventMapRec; // get the starting/ending rid of events of this typedef IfFailGo(m_LiteWeightStgdb.m_MiniMd.FindEventMapFor(RidFromToken(tkParent), &ridEventMap)); if (!InvalidRid(ridEventMap)) { IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetEventMapRecord(ridEventMap, &pEventMapRec)); phEnum->u.m_ulStart = m_LiteWeightStgdb.m_MiniMd.getEventListOfEventMap(pEventMapRec); IfFailGo(m_LiteWeightStgdb.m_MiniMd.getEndEventListOfEventMap(ridEventMap, &(phEnum->u.m_ulEnd))); ulMax = m_LiteWeightStgdb.m_MiniMd.getCountEvents() + 1; if(phEnum->u.m_ulStart == 0) phEnum->u.m_ulStart = 1; if(phEnum->u.m_ulEnd > ulMax) phEnum->u.m_ulEnd = ulMax; if(phEnum->u.m_ulStart > phEnum->u.m_ulEnd) phEnum->u.m_ulStart = phEnum->u.m_ulEnd; } break; case mdtParamDef: _ASSERTE(TypeFromToken(tkParent) == mdtMethodDef); MethodRec *pMethodRec; IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetMethodRecord(RidFromToken(tkParent), &pMethodRec)); // figure out the start rid and end rid of the parameter list of this methoddef phEnum->u.m_ulStart = m_LiteWeightStgdb.m_MiniMd.getParamListOfMethod(pMethodRec); IfFailGo(m_LiteWeightStgdb.m_MiniMd.getEndParamListOfMethod(RidFromToken(tkParent), &(phEnum->u.m_ulEnd))); break; case mdtCustomAttribute: IfFailGo(m_LiteWeightStgdb.m_MiniMd.getCustomAttributeForToken(tkParent, &phEnum->u.m_ulEnd, &phEnum->u.m_ulStart)); break; case mdtAssemblyRef: _ASSERTE(IsNilToken(tkParent)); phEnum->u.m_ulStart = 1; phEnum->u.m_ulEnd = m_LiteWeightStgdb.m_MiniMd.getCountAssemblyRefs() + 1; break; case mdtFile: _ASSERTE(IsNilToken(tkParent)); phEnum->u.m_ulStart = 1; phEnum->u.m_ulEnd = m_LiteWeightStgdb.m_MiniMd.getCountFiles() + 1; break; case mdtExportedType: _ASSERTE(IsNilToken(tkParent)); phEnum->u.m_ulStart = 1; phEnum->u.m_ulEnd = m_LiteWeightStgdb.m_MiniMd.getCountExportedTypes() + 1; break; case mdtManifestResource: _ASSERTE(IsNilToken(tkParent)); phEnum->u.m_ulStart = 1; phEnum->u.m_ulEnd = m_LiteWeightStgdb.m_MiniMd.getCountManifestResources() + 1; break; case mdtModuleRef: _ASSERTE(IsNilToken(tkParent)); phEnum->u.m_ulStart = 1; phEnum->u.m_ulEnd = m_LiteWeightStgdb.m_MiniMd.getCountModuleRefs() + 1; break; case (TBL_MethodImpl << 24): _ASSERTE(! IsNilToken(tkParent)); IfFailGo(m_LiteWeightStgdb.m_MiniMd.getMethodImplsForClass( RidFromToken(tkParent), &phEnum->u.m_ulEnd, &phEnum->u.m_ulStart)); break; default: _ASSERTE(!"ENUM INIT not implemented for the compressed format!"); IfFailGo(E_NOTIMPL); break; } // If the count is negative, the metadata is corrupted somehow. if (phEnum->u.m_ulEnd < phEnum->u.m_ulStart) IfFailGo(CLDB_E_FILE_CORRUPT); phEnum->m_ulCount = phEnum->u.m_ulEnd - phEnum->u.m_ulStart; phEnum->u.m_ulCur = phEnum->u.m_ulStart; ErrExit: // we are done return hr; } //***************************************** // Enumerator initializer //***************************************** __checkReturn HRESULT MDInternalRO::EnumAllInit( // return S_FALSE if record not found DWORD tkKind, // [IN] which table to work on HENUMInternal *phEnum) // [OUT] the enumerator to fill { HRESULT hr = S_OK; // Vars for query. _ASSERTE(phEnum); memset(phEnum, 0, sizeof(HENUMInternal)); // cache the tkKind and the scope phEnum->m_tkKind = TypeFromToken(tkKind); phEnum->m_EnumType = MDSimpleEnum; switch (TypeFromToken(tkKind)) { case mdtTypeRef: phEnum->m_ulCount = m_LiteWeightStgdb.m_MiniMd.getCountTypeRefs(); break; case mdtMemberRef: phEnum->m_ulCount = m_LiteWeightStgdb.m_MiniMd.getCountMemberRefs(); break; case mdtSignature: phEnum->m_ulCount = m_LiteWeightStgdb.m_MiniMd.getCountStandAloneSigs(); break; case mdtMethodDef: phEnum->m_ulCount = m_LiteWeightStgdb.m_MiniMd.getCountMethods(); break; case mdtMethodSpec: phEnum->m_ulCount = m_LiteWeightStgdb.m_MiniMd.getCountMethodSpecs(); break; case mdtFieldDef: phEnum->m_ulCount = m_LiteWeightStgdb.m_MiniMd.getCountFields(); break; case mdtTypeSpec: phEnum->m_ulCount = m_LiteWeightStgdb.m_MiniMd.getCountTypeSpecs(); break; case mdtAssemblyRef: phEnum->m_ulCount = m_LiteWeightStgdb.m_MiniMd.getCountAssemblyRefs(); break; case mdtModuleRef: phEnum->m_ulCount = m_LiteWeightStgdb.m_MiniMd.getCountModuleRefs(); break; case mdtTypeDef: phEnum->m_ulCount = m_LiteWeightStgdb.m_MiniMd.getCountTypeDefs(); break; case mdtFile: phEnum->m_ulCount = m_LiteWeightStgdb.m_MiniMd.getCountFiles(); break; default: _ASSERTE(!"Bad token kind!"); break; } phEnum->u.m_ulStart = phEnum->u.m_ulCur = 1; phEnum->u.m_ulEnd = phEnum->m_ulCount + 1; // we are done return hr; } // MDInternalRO::EnumAllInit //***************************************** // get the count //***************************************** ULONG MDInternalRO::EnumGetCount( HENUMInternal *phEnum) // [IN] the enumerator to retrieve information { _ASSERTE(phEnum); return phEnum->m_ulCount; } //***************************************** // Get next value contained in the enumerator //***************************************** bool MDInternalRO::EnumNext( HENUMInternal *phEnum, // [IN] the enumerator to retrieve information mdToken *ptk) // [OUT] token to scope the search { _ASSERTE(phEnum && ptk); if (phEnum->u.m_ulCur >= phEnum->u.m_ulEnd) return false; if ( phEnum->m_EnumType == MDSimpleEnum ) { *ptk = phEnum->u.m_ulCur | phEnum->m_tkKind; phEnum->u.m_ulCur++; } else { TOKENLIST *pdalist = (TOKENLIST *)&(phEnum->m_cursor); _ASSERTE( phEnum->m_EnumType == MDDynamicArrayEnum ); *ptk = *( pdalist->Get(phEnum->u.m_ulCur++) ); } return true; } // MDInternalRO::EnumNext //***************************************** // Reset the enumerator to the beginning. //***************************************** void MDInternalRO::EnumReset( HENUMInternal *phEnum) // [IN] the enumerator to be reset { _ASSERTE(phEnum); _ASSERTE( phEnum->m_EnumType == MDSimpleEnum || phEnum->m_EnumType == MDDynamicArrayEnum); phEnum->u.m_ulCur = phEnum->u.m_ulStart; } // MDInternalRO::EnumReset //***************************************** // Close the enumerator. Only for read/write mode that we need to close the cursor. // Hopefully with readonly mode, it will be a no-op //***************************************** void MDInternalRO::EnumClose( HENUMInternal *phEnum) // [IN] the enumerator to be closed { _ASSERTE( phEnum->m_EnumType == MDSimpleEnum || phEnum->m_EnumType == MDDynamicArrayEnum || phEnum->m_EnumType == MDCustomEnum ); if (phEnum->m_EnumType == MDDynamicArrayEnum) HENUMInternal::ClearEnum(phEnum); } // MDInternalRO::EnumClose //--------------------------------------------------------------------------------------- // // Initialize enumerator of PermissionSets. // // Return Value: // CLDB_E_RECORD_NOTFOUND ... If record not found. // S_OK and empty enumeration ... If tkParent is nil token and Action is dclActionNil. // __checkReturn HRESULT MDInternalRO::EnumPermissionSetsInit( mdToken tkParent, // [IN] Token to scope the search. CorDeclSecurity Action, // [IN] Action to scope the search. HENUMInternal *phEnum) // [OUT] Enumerator to fill. { HRESULT hr = S_OK; _ASSERTE(phEnum != NULL); HENUMInternal::ZeroEnum(phEnum); // cache the tkKind phEnum->m_tkKind = mdtPermission; DeclSecurityRec *pDecl; RID ridCur; RID ridEnd; phEnum->m_EnumType = MDSimpleEnum; IfFailGo(m_LiteWeightStgdb.m_MiniMd.getDeclSecurityForToken(tkParent, &ridEnd, &ridCur)); if (Action != dclActionNil) { for (; ridCur < ridEnd; ridCur++) { IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetDeclSecurityRecord(ridCur, &pDecl)); if (Action == m_LiteWeightStgdb.m_MiniMd.getActionOfDeclSecurity(pDecl)) { // found a match phEnum->u.m_ulStart = phEnum->u.m_ulCur = ridCur; phEnum->u.m_ulEnd = ridCur + 1; phEnum->m_ulCount = 1; goto ErrExit; } } hr = CLDB_E_RECORD_NOTFOUND; } else { phEnum->u.m_ulStart = phEnum->u.m_ulCur = ridCur; phEnum->u.m_ulEnd = ridEnd; phEnum->m_ulCount = ridEnd - ridCur; } ErrExit: return hr; } // MDInternalRO::EnumPermissionSetInit //***************************************** // Enumerator initializer for CustomAttributes //***************************************** __checkReturn HRESULT MDInternalRO::EnumCustomAttributeByNameInit(// return S_FALSE if record not found mdToken tkParent, // [IN] token to scope the search LPCSTR szName, // [IN] CustomAttribute's name to scope the search HENUMInternal *phEnum) // [OUT] the enumerator to fill { return m_LiteWeightStgdb.m_MiniMd.CommonEnumCustomAttributeByName(tkParent, szName, false, phEnum); } // MDInternalRO::EnumCustomAttributeByNameInit //***************************************** // Enumerator for CustomAttributes which doesn't // allocate any memory //***************************************** __checkReturn HRESULT MDInternalRO::SafeAndSlowEnumCustomAttributeByNameInit(// return S_FALSE if record not found mdToken tkParent, // [IN] token to scope the search LPCSTR szName, // [IN] CustomAttribute's name to scope the search HENUMInternal *phEnum) // [OUT] The enumerator { _ASSERTE(phEnum); HRESULT hr; ULONG ridStart, ridEnd; // Loop start and endpoints. // Get the list of custom values for the parent object. IfFailRet(m_LiteWeightStgdb.m_MiniMd.getCustomAttributeForToken(tkParent, &ridEnd, &ridStart)); // If found none, done. if (ridStart == 0) goto NoMatch; phEnum->m_EnumType = MDCustomEnum; phEnum->m_tkKind = mdtCustomAttribute; phEnum->u.m_ulStart = ridStart; phEnum->u.m_ulEnd = ridEnd; phEnum->u.m_ulCur = ridStart; return S_OK; NoMatch: return S_FALSE; } // MDInternalRO::SafeAndSlowEnumCustomAttributeByNameInit __checkReturn HRESULT MDInternalRO::SafeAndSlowEnumCustomAttributeByNameNext(// return S_FALSE if record not found mdToken tkParent, // [IN] token to scope the search LPCSTR szName, // [IN] CustomAttribute's name to scope the search HENUMInternal *phEnum, // [IN] The enumerator mdCustomAttribute *mdAttribute) // [OUT] The custom attribute that was found { _ASSERTE(phEnum); _ASSERTE(phEnum->m_EnumType == MDCustomEnum); _ASSERTE(phEnum->m_tkKind == mdtCustomAttribute); // Look for one with the given name. for (; phEnum->u.m_ulCur < phEnum->u.m_ulEnd; ++phEnum->u.m_ulCur) { if (S_OK == m_LiteWeightStgdb.m_MiniMd.CompareCustomAttribute( tkParent, szName, phEnum->u.m_ulCur)) { // If here, found a match. *mdAttribute = TokenFromRid(phEnum->u.m_ulCur, mdtCustomAttribute); phEnum->u.m_ulCur++; return S_OK; } } // No match... return S_FALSE; } // MDInternalRO::SafeAndSlowEnumCustomAttributeByNameNext //***************************************** // Nagivator helper to navigate back to the parent token given a token. // For example, given a memberdef token, it will return the containing typedef. // // the mapping is as following: // ---given child type---------parent type // mdMethodDef mdTypeDef // mdFieldDef mdTypeDef // mdInterfaceImpl mdTypeDef // mdParam mdMethodDef // mdProperty mdTypeDef // mdEvent mdTypeDef // //***************************************** __checkReturn HRESULT MDInternalRO::GetParentToken( mdToken tkChild, // [IN] given child token mdToken *ptkParent) // [OUT] returning parent { HRESULT hr = NOERROR; _ASSERTE(ptkParent); switch (TypeFromToken(tkChild)) { case mdtTypeDef: hr = GetNestedClassProps(tkChild, ptkParent); // If not found, the *ptkParent has to be left unchanged! (callers depend on that) if (hr == CLDB_E_RECORD_NOTFOUND) { hr = S_OK; } break; case mdtMethodDef: IfFailRet(m_LiteWeightStgdb.m_MiniMd.FindParentOfMethod(RidFromToken(tkChild), (RID *)ptkParent)); RidToToken(*ptkParent, mdtTypeDef); break; case mdtMethodSpec: { MethodSpecRec *pRec; IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodSpecRecord(RidFromToken(tkChild), &pRec)); *ptkParent = m_LiteWeightStgdb.m_MiniMd.getMethodOfMethodSpec(pRec); break; } case mdtFieldDef: IfFailRet(m_LiteWeightStgdb.m_MiniMd.FindParentOfField(RidFromToken(tkChild), (RID *)ptkParent)); RidToToken(*ptkParent, mdtTypeDef); break; case mdtParamDef: IfFailRet(m_LiteWeightStgdb.m_MiniMd.FindParentOfParam(RidFromToken(tkChild), (RID *)ptkParent)); RidToToken(*ptkParent, mdtMethodDef); break; case mdtMemberRef: { MemberRefRec *pRec; IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMemberRefRecord(RidFromToken(tkChild), &pRec)); *ptkParent = m_LiteWeightStgdb.m_MiniMd.getClassOfMemberRef(pRec); break; } case mdtCustomAttribute: { CustomAttributeRec *pRec; IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetCustomAttributeRecord(RidFromToken(tkChild), &pRec)); *ptkParent = m_LiteWeightStgdb.m_MiniMd.getParentOfCustomAttribute(pRec); break; } case mdtEvent: hr = m_LiteWeightStgdb.m_MiniMd.FindParentOfEventHelper(tkChild, ptkParent); break; case mdtProperty: hr = m_LiteWeightStgdb.m_MiniMd.FindParentOfPropertyHelper(tkChild, ptkParent); break; default: _ASSERTE(!"NYI: for compressed format!"); break; } return hr; } // MDInternalRO::GetParentToken //***************************************************************************** // Get information about a CustomAttribute. //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetCustomAttributeProps( // S_OK or error. mdCustomAttribute at, // The attribute. mdToken *ptkType) // Put attribute type here. { HRESULT hr; _ASSERTE(TypeFromToken(at) == mdtCustomAttribute); // Do a linear search on compressed version as we do not want to // depends on ICR. // CustomAttributeRec *pCustomAttributeRec; IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetCustomAttributeRecord(RidFromToken(at), &pCustomAttributeRec)); *ptkType = m_LiteWeightStgdb.m_MiniMd.getTypeOfCustomAttribute(pCustomAttributeRec); return S_OK; } // MDInternalRO::GetCustomAttributeProps //***************************************************************************** // return custom value //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetCustomAttributeAsBlob( mdCustomAttribute cv, // [IN] given custom attribute token void const **ppBlob, // [OUT] return the pointer to internal blob ULONG *pcbSize) // [OUT] return the size of the blob { HRESULT hr; _ASSERTE(ppBlob && pcbSize && TypeFromToken(cv) == mdtCustomAttribute); CustomAttributeRec *pCustomAttributeRec; IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetCustomAttributeRecord(RidFromToken(cv), &pCustomAttributeRec)); IfFailRet(m_LiteWeightStgdb.m_MiniMd.getValueOfCustomAttribute(pCustomAttributeRec, (const BYTE **)ppBlob, pcbSize)); return S_OK; } // MDInternalRO::GetCustomAttributeAsBlob //***************************************************************************** // Helper function to lookup and retrieve a CustomAttribute. //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetCustomAttributeByName( // S_OK or error. mdToken tkObj, // [IN] Object with Custom Attribute. LPCUTF8 szName, // [IN] Name of desired Custom Attribute. __deref_out_bcount(*pcbData) const void **ppData, // [OUT] Put pointer to data here. __out ULONG *pcbData) // [OUT] Put size of data here. { return m_LiteWeightStgdb.m_MiniMd.CommonGetCustomAttributeByName(tkObj, szName, ppData, pcbData); } // MDInternalRO::GetCustomAttributeByName //***************************************************************************** // return the name of a custom attribute //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetNameOfCustomAttribute( // S_OK or error. mdCustomAttribute mdAttribute, // [IN] The Custom Attribute LPCUTF8 *pszNamespace, // [OUT] Namespace of Custom Attribute. LPCUTF8 *pszName) // [OUT] Name of Custom Attribute. { _ASSERTE(TypeFromToken(mdAttribute) == mdtCustomAttribute); HRESULT hr = m_LiteWeightStgdb.m_MiniMd.CommonGetNameOfCustomAttribute(RidFromToken(mdAttribute), pszNamespace, pszName); return (hr == S_FALSE) ? E_FAIL : hr; } // MDInternalRO::GetNameOfCustomAttribute //***************************************************************************** // return scope properties //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetScopeProps( LPCSTR *pszName, // [OUT] scope name GUID *pmvid) // [OUT] version id { HRESULT hr; ModuleRec *pModuleRec; // there is only one module record IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetModuleRecord(1, &pModuleRec)); if (pmvid != NULL) { IfFailRet(m_LiteWeightStgdb.m_MiniMd.getMvidOfModule(pModuleRec, pmvid)); } if (pszName != NULL) { IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfModule(pModuleRec, pszName)); } return S_OK; } // MDInternalRO::GetScopeProps //***************************************************************************** // Compare two signatures from the same scope. Varags signatures need to be // preprocessed so they only contain the fixed part. //***************************************************************************** BOOL MDInternalRO::CompareSignatures(PCCOR_SIGNATURE pvFirstSigBlob, // First signature DWORD cbFirstSigBlob, // PCCOR_SIGNATURE pvSecondSigBlob, // Second signature DWORD cbSecondSigBlob, // void * SigArguments) // No additional arguments required { if (cbFirstSigBlob != cbSecondSigBlob || memcmp(pvFirstSigBlob, pvSecondSigBlob, cbSecondSigBlob)) return FALSE; else return TRUE; } //***************************************************************************** // Find a given member in a TypeDef (typically a class). //***************************************************************************** __checkReturn HRESULT MDInternalRO::FindMethodDef( // S_OK or error. mdTypeDef classdef, // The owning class of the member. LPCSTR szName, // Name of the member in utf8. PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of COM+ signature ULONG cbSigBlob, // [IN] count of bytes in the signature blob mdMethodDef *pmethoddef) // Put MemberDef token here. { return FindMethodDefUsingCompare(classdef, szName, pvSigBlob, cbSigBlob, CompareSignatures, NULL, pmethoddef); } //***************************************************************************** // Find a given member in a TypeDef (typically a class). //***************************************************************************** __checkReturn HRESULT MDInternalRO::FindMethodDefUsingCompare( // S_OK or error. mdTypeDef classdef, // The owning class of the member. LPCSTR szName, // Name of the member in utf8. PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of COM+ signature ULONG cbSigBlob, // [IN] count of bytes in the signature blob PSIGCOMPARE SigCompare, // [IN] Signature comparison routine void* pSigArgs, // [IN] Additional arguments passed to signature compare mdMethodDef *pmethoddef) // Put MemberDef token here. { HRESULT hr = NOERROR; PCCOR_SIGNATURE pvSigTemp = pvSigBlob; CQuickBytes qbSig; _ASSERTE(szName && pmethoddef); // initialize the output parameter *pmethoddef = mdMethodDefNil; // check to see if this is a vararg signature if ( isCallConv(CorSigUncompressCallingConv(pvSigTemp), IMAGE_CEE_CS_CALLCONV_VARARG) ) { // Get the fix part of VARARG signature IfFailGo( _GetFixedSigOfVarArg(pvSigBlob, cbSigBlob, &qbSig, &cbSigBlob) ); pvSigBlob = (PCCOR_SIGNATURE) qbSig.Ptr(); } // Do a linear search on compressed version // RID ridMax; MethodRec *pMethodRec; LPCUTF8 szCurMethodName; void const *pvCurMethodSig; ULONG cbSig; TypeDefRec *pRec; RID ridStart; // get the typedef record IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetTypeDefRecord(RidFromToken(classdef), &pRec)); // get the range of methoddef rids given the classdef ridStart = m_LiteWeightStgdb.m_MiniMd.getMethodListOfTypeDef(pRec); IfFailGo(m_LiteWeightStgdb.m_MiniMd.getEndMethodListOfTypeDef(RidFromToken(classdef), &ridMax)); // loop through each methoddef for (; ridStart < ridMax; ridStart++) { IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetMethodRecord(ridStart, &pMethodRec)); IfFailGo(m_LiteWeightStgdb.m_MiniMd.getNameOfMethod(pMethodRec, &szCurMethodName)); if (strcmp(szCurMethodName, szName) == 0) { // name match, now check the signature if specified. if (cbSigBlob && SigCompare) { IfFailGo(m_LiteWeightStgdb.m_MiniMd.getSignatureOfMethod(pMethodRec, (PCCOR_SIGNATURE *)&pvCurMethodSig, &cbSig)); // Signature comparison is required // Note that if pvSigBlob is vararg, we already preprocess it so that // it only contains the fix part. Therefore, it still should be an exact // match!!!. // if(SigCompare((PCCOR_SIGNATURE) pvCurMethodSig, cbSig, pvSigBlob, cbSigBlob, pSigArgs) == FALSE) continue; } // Ignore PrivateScope methods. if (IsMdPrivateScope(m_LiteWeightStgdb.m_MiniMd.getFlagsOfMethod(pMethodRec))) continue; // found the match *pmethoddef = TokenFromRid(ridStart, mdtMethodDef); goto ErrExit; } } hr = CLDB_E_RECORD_NOTFOUND; ErrExit: return hr; } //***************************************************************************** // Find a given param of a Method. //***************************************************************************** __checkReturn HRESULT MDInternalRO::FindParamOfMethod(// S_OK or error. mdMethodDef md, // [IN] The owning method of the param. ULONG iSeq, // [IN] The sequence # of the param. mdParamDef *pparamdef) // [OUT] Put ParamDef token here. { HRESULT hr; ParamRec *pParamRec; RID ridStart, ridEnd; _ASSERTE(TypeFromToken(md) == mdtMethodDef && pparamdef); // get the methoddef record MethodRec *pMethodRec; IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodRecord(RidFromToken(md), &pMethodRec)); // figure out the start rid and end rid of the parameter list of this methoddef ridStart = m_LiteWeightStgdb.m_MiniMd.getParamListOfMethod(pMethodRec); IfFailRet(m_LiteWeightStgdb.m_MiniMd.getEndParamListOfMethod(RidFromToken(md), &ridEnd)); // Ensure that the paramList is valid. If the count is negative, the metadata // is corrupted somehow. Thus, return CLDB_E_FILE_CORRUPT. if (ridEnd < ridStart) return CLDB_E_FILE_CORRUPT; // loop through each param //@consider: parameters are sorted by sequence. Maybe a binary search? // for (; ridStart < ridEnd; ridStart++) { IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetParamRecord(ridStart, &pParamRec)); if (iSeq == m_LiteWeightStgdb.m_MiniMd.getSequenceOfParam(pParamRec)) { // parameter has the sequence number matches what we are looking for *pparamdef = TokenFromRid(ridStart, mdtParamDef); return S_OK; } } return CLDB_E_RECORD_NOTFOUND; } //***************************************************************************** // return a pointer which points to meta data's internal string // return the the type name in utf8 //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetNameOfTypeDef( // return hresult mdTypeDef classdef, // given typedef LPCSTR* pszname, // pointer to an internal UTF8 string LPCSTR* psznamespace) // pointer to the namespace. { HRESULT hr; if (pszname != NULL) { *pszname = NULL; } if (psznamespace != NULL) { *psznamespace = NULL; } if (TypeFromToken(classdef) == mdtTypeDef) { TypeDefRec *pTypeDefRec; IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetTypeDefRecord(RidFromToken(classdef), &pTypeDefRec)); if (pszname != NULL) { IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfTypeDef(pTypeDefRec, pszname)); } if (psznamespace != NULL) { IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNamespaceOfTypeDef(pTypeDefRec, psznamespace)); } return S_OK; } _ASSERTE(!"Invalid argument(s) of GetNameOfTypeDef"); return CLDB_E_INTERNALERROR; } // MDInternalRO::GetNameOfTypeDef __checkReturn HRESULT MDInternalRO::GetIsDualOfTypeDef(// return hresult mdTypeDef classdef, // given classdef ULONG *pDual) // [OUT] return dual flag here. { ULONG iFace=0; // Iface type. HRESULT hr; // A result. hr = GetIfaceTypeOfTypeDef(classdef, &iFace); if (hr == S_OK) *pDual = (iFace == ifDual); else *pDual = 1; return hr; } // MDInternalRO::GetIsDualOfTypeDef __checkReturn HRESULT MDInternalRO::GetIfaceTypeOfTypeDef( mdTypeDef classdef, // [IN] given classdef. ULONG *pIface) // [OUT] 0=dual, 1=vtable, 2=dispinterface { HRESULT hr; // A result. const BYTE *pVal; // The custom value. ULONG cbVal; // Size of the custom value. ULONG ItfType = DEFAULT_COM_INTERFACE_TYPE; // Set the interface type to the default. // If the value is not present, the class is assumed dual. hr = GetCustomAttributeByName(classdef, INTEROP_INTERFACETYPE_TYPE, (const void**)&pVal, &cbVal); if (hr == S_OK) { CustomAttributeParser cap(pVal, cbVal); BYTE u1; if (SUCCEEDED(cap.SkipProlog()) && SUCCEEDED(cap.GetU1(&u1))) { ItfType = u1; } if (ItfType >= ifLast) ItfType = DEFAULT_COM_INTERFACE_TYPE; } // Set the return value. *pIface = ItfType; return hr; } // MDInternalRO::GetIfaceTypeOfTypeDef //***************************************************************************** // Given a methoddef, return a pointer to methoddef's name //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetNameOfMethodDef( mdMethodDef md, LPCSTR *pszMethodName) { HRESULT hr; MethodRec *pMethodRec; *pszMethodName = NULL; IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodRecord(RidFromToken(md), &pMethodRec)); IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfMethod(pMethodRec, pszMethodName)); return S_OK; } // MDInternalRO::GetNameOfMethodDef //***************************************************************************** // Given a methoddef, return a pointer to methoddef's signature and methoddef's name //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetNameAndSigOfMethodDef( mdMethodDef methoddef, // [IN] given memberdef PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to a blob value of COM+ signature ULONG *pcbSigBlob, // [OUT] count of bytes in the signature blob LPCSTR *pszMethodName) { HRESULT hr; // Output parameter should not be NULL _ASSERTE(ppvSigBlob && pcbSigBlob); _ASSERTE(TypeFromToken(methoddef) == mdtMethodDef); MethodRec *pMethodRec; *pszMethodName = NULL; *ppvSigBlob = NULL; *pcbSigBlob = 0; IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodRecord(RidFromToken(methoddef), &pMethodRec)); IfFailRet(m_LiteWeightStgdb.m_MiniMd.getSignatureOfMethod(pMethodRec, (PCCOR_SIGNATURE *)ppvSigBlob, pcbSigBlob)); return GetNameOfMethodDef(methoddef, pszMethodName); } // MDInternalRO::GetNameAndSigOfMethodDef //***************************************************************************** // Given a FieldDef, return a pointer to FieldDef's name in UTF8 //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetNameOfFieldDef( // return hresult mdFieldDef fd, // given field LPCSTR *pszFieldName) { HRESULT hr; FieldRec *pFieldRec; *pszFieldName = NULL; IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetFieldRecord(RidFromToken(fd), &pFieldRec)); IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfField(pFieldRec, pszFieldName)); return S_OK; } // MDInternalRO::GetNameOfFieldDef //***************************************************************************** // Given a classdef, return the name and namespace of the typeref //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetNameOfTypeRef( // return TypeDef's name mdTypeRef classref, // [IN] given typeref LPCSTR *psznamespace, // [OUT] return typeref name LPCSTR *pszname) // [OUT] return typeref namespace { _ASSERTE(TypeFromToken(classref) == mdtTypeRef); HRESULT hr; TypeRefRec *pTypeRefRec; *psznamespace = NULL; *pszname = NULL; IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetTypeRefRecord(RidFromToken(classref), &pTypeRefRec)); IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNamespaceOfTypeRef(pTypeRefRec, psznamespace)); IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfTypeRef(pTypeRefRec, pszname)); return S_OK; } //***************************************************************************** // return the resolutionscope of typeref //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetResolutionScopeOfTypeRef( mdTypeRef classref, // given classref mdToken *ptkResolutionScope) { _ASSERTE(TypeFromToken(classref) == mdtTypeRef && RidFromToken(classref)); HRESULT hr; TypeRefRec *pTypeRefRec; *ptkResolutionScope = mdTokenNil; IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetTypeRefRecord(RidFromToken(classref), &pTypeRefRec)); *ptkResolutionScope = m_LiteWeightStgdb.m_MiniMd.getResolutionScopeOfTypeRef(pTypeRefRec); return S_OK; } // MDInternalRO::GetResolutionScopeOfTypeRef //***************************************************************************** // Given a name, find the corresponding TypeRef. //***************************************************************************** __checkReturn HRESULT MDInternalRO::FindTypeRefByName( // S_OK or error. LPCSTR szNamespace, // [IN] Namespace for the TypeRef. LPCSTR szName, // [IN] Name of the TypeRef. mdToken tkResolutionScope, // [IN] Resolution Scope fo the TypeRef. mdTypeRef *ptk) // [OUT] TypeRef token returned. { HRESULT hr = NOERROR; _ASSERTE(ptk); // initialize the output parameter *ptk = mdTypeRefNil; // Treat no namespace as empty string. if (!szNamespace) szNamespace = ""; // Do a linear search on compressed version as we do not want to // depends on ICR. // ULONG cTypeRefRecs = m_LiteWeightStgdb.m_MiniMd.getCountTypeRefs(); TypeRefRec *pTypeRefRec; LPCUTF8 szNamespaceTmp; LPCUTF8 szNameTmp; mdToken tkRes; for (ULONG i = 1; i <= cTypeRefRecs; i++) { IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetTypeRefRecord(i, &pTypeRefRec)); tkRes = m_LiteWeightStgdb.m_MiniMd.getResolutionScopeOfTypeRef(pTypeRefRec); if (IsNilToken(tkRes)) { if (!IsNilToken(tkResolutionScope)) continue; } else if (tkRes != tkResolutionScope) continue; IfFailGo(m_LiteWeightStgdb.m_MiniMd.getNamespaceOfTypeRef(pTypeRefRec, &szNamespaceTmp)); if (strcmp(szNamespace, szNamespaceTmp)) continue; IfFailGo(m_LiteWeightStgdb.m_MiniMd.getNameOfTypeRef(pTypeRefRec, &szNameTmp)); if (!strcmp(szNameTmp, szName)) { *ptk = TokenFromRid(i, mdtTypeRef); goto ErrExit; } } // cannot find the typedef hr = CLDB_E_RECORD_NOTFOUND; ErrExit: return hr; } //***************************************************************************** // return flags for a given class //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetTypeDefProps( mdTypeDef td, // given classdef DWORD *pdwAttr, // return flags on class mdToken *ptkExtends) // [OUT] Put base class TypeDef/TypeRef here. { HRESULT hr; TypeDefRec *pTypeDefRec; IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetTypeDefRecord(RidFromToken(td), &pTypeDefRec)); if (ptkExtends) { *ptkExtends = m_LiteWeightStgdb.m_MiniMd.getExtendsOfTypeDef(pTypeDefRec); } if (pdwAttr) { *pdwAttr = m_LiteWeightStgdb.m_MiniMd.getFlagsOfTypeDef(pTypeDefRec); } return S_OK; } //***************************************************************************** // return guid pointer to MetaData internal guid pool given a given class //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetItemGuid( // return hresult mdToken tkObj, // given item CLSID *pGuid) { HRESULT hr; // A result. const BYTE *pBlob = NULL; // Blob with dispid. ULONG cbBlob; // Length of blob. int ix; // Loop control. // Get the GUID, if any. hr = GetCustomAttributeByName(tkObj, INTEROP_GUID_TYPE, (const void**)&pBlob, &cbBlob); if (hr != S_FALSE) { // Should be in format. Total length == 41 // <0x0001><0x24>01234567-0123-0123-0123-001122334455<0x0000> if ((cbBlob != 41) || (GET_UNALIGNED_VAL16(pBlob) != 1)) IfFailGo(E_INVALIDARG); WCHAR wzBlob[40]; // Wide char format of guid. for (ix=1; ix<=36; ++ix) wzBlob[ix] = pBlob[ix+2]; wzBlob[0] = '{'; wzBlob[37] = '}'; wzBlob[38] = 0; hr = IIDFromString(wzBlob, pGuid); } else *pGuid = GUID_NULL; ErrExit: return hr; } // MDInternalRO::GetItemGuid //***************************************************************************** // // get enclosing class of NestedClass //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetNestedClassProps( // S_OK or error mdTypeDef tkNestedClass, // [IN] NestedClass token. mdTypeDef *ptkEnclosingClass) // [OUT] EnclosingClass token. { HRESULT hr; _ASSERTE(TypeFromToken(tkNestedClass) == mdtTypeDef && ptkEnclosingClass); RID rid; IfFailRet(m_LiteWeightStgdb.m_MiniMd.FindNestedClassFor(RidFromToken(tkNestedClass), &rid)); if (InvalidRid(rid)) { return CLDB_E_RECORD_NOTFOUND; } else { NestedClassRec *pRecord; IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetNestedClassRecord(rid, &pRecord)); *ptkEnclosingClass = m_LiteWeightStgdb.m_MiniMd.getEnclosingClassOfNestedClass(pRecord); return S_OK; } } //******************************************************************************* // Get count of Nested classes given the enclosing class. //******************************************************************************* __checkReturn HRESULT MDInternalRO::GetCountNestedClasses( // return count of Nested classes. mdTypeDef tkEnclosingClass, // [IN]Enclosing class. ULONG *pcNestedClassesCount) { HRESULT hr; ULONG ulCount; ULONG ulRetCount = 0; NestedClassRec *pRecord; _ASSERTE(TypeFromToken(tkEnclosingClass) == mdtTypeDef && !IsNilToken(tkEnclosingClass)); *pcNestedClassesCount = 0; ulCount = m_LiteWeightStgdb.m_MiniMd.getCountNestedClasss(); for (ULONG i = 1; i <= ulCount; i++) { IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetNestedClassRecord(i, &pRecord)); if (tkEnclosingClass == m_LiteWeightStgdb.m_MiniMd.getEnclosingClassOfNestedClass(pRecord)) ulRetCount++; } *pcNestedClassesCount = ulRetCount; return S_OK; } // MDInternalRO::GetCountNestedClasses //******************************************************************************* // Return array of Nested classes given the enclosing class. //******************************************************************************* __checkReturn HRESULT MDInternalRO::GetNestedClasses( // Return actual count. mdTypeDef tkEnclosingClass, // [IN] Enclosing class. mdTypeDef *rNestedClasses, // [OUT] Array of nested class tokens. ULONG ulNestedClasses, // [IN] Size of array. ULONG *pcNestedClasses) { HRESULT hr; ULONG ulCount; ULONG ulRetCount = 0; NestedClassRec *pRecord; _ASSERTE(TypeFromToken(tkEnclosingClass) == mdtTypeDef && !IsNilToken(tkEnclosingClass)); *pcNestedClasses = 0; ulCount = m_LiteWeightStgdb.m_MiniMd.getCountNestedClasss(); for (ULONG i = 1; i <= ulCount; i++) { IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetNestedClassRecord(i, &pRecord)); if (tkEnclosingClass == m_LiteWeightStgdb.m_MiniMd.getEnclosingClassOfNestedClass(pRecord)) { if (ovadd_le(ulRetCount, 1, ulNestedClasses)) // ulRetCount is 0 based. rNestedClasses[ulRetCount] = m_LiteWeightStgdb.m_MiniMd.getNestedClassOfNestedClass(pRecord); ulRetCount++; } } *pcNestedClasses = ulRetCount; return S_OK; } // MDInternalRO::GetNestedClasses //******************************************************************************* // return the ModuleRef properties //******************************************************************************* __checkReturn HRESULT MDInternalRO::GetModuleRefProps( // return hresult mdModuleRef mur, // [IN] moduleref token LPCSTR *pszName) // [OUT] buffer to fill with the moduleref name { _ASSERTE(TypeFromToken(mur) == mdtModuleRef); _ASSERTE(pszName); HRESULT hr; // Is it a valid token? if (!IsValidToken(mur)) { *pszName = NULL; // Not every caller checks returned HRESULT, allow to fail fast in that case return COR_E_BADIMAGEFORMAT; // Invalid Token } ModuleRefRec *pModuleRefRec; IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetModuleRefRecord(RidFromToken(mur), &pModuleRefRec)); IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfModuleRef(pModuleRefRec, pszName)); return S_OK; } //***************************************************************************** // Given a scope and a methoddef, return a pointer to methoddef's signature //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetSigOfMethodDef( mdMethodDef methoddef, // given a methoddef ULONG *pcbSigBlob, // [OUT] count of bytes in the signature blob PCCOR_SIGNATURE *ppSig) { // Output parameter should not be NULL _ASSERTE(pcbSigBlob); _ASSERTE(TypeFromToken(methoddef) == mdtMethodDef); HRESULT hr; MethodRec *pMethodRec; *ppSig = NULL; *pcbSigBlob = 0; IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodRecord(RidFromToken(methoddef), &pMethodRec)); IfFailRet(m_LiteWeightStgdb.m_MiniMd.getSignatureOfMethod(pMethodRec, ppSig, pcbSigBlob)); return S_OK; } // MDInternalRO::GetSigOfMethodDef //***************************************************************************** // Given a scope and a fielddef, return a pointer to fielddef's signature //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetSigOfFieldDef( mdFieldDef fielddef, // given a methoddef ULONG *pcbSigBlob, // [OUT] count of bytes in the signature blob PCCOR_SIGNATURE *ppSig) { _ASSERTE(pcbSigBlob); _ASSERTE(TypeFromToken(fielddef) == mdtFieldDef); HRESULT hr; FieldRec *pFieldRec; *ppSig = NULL; *pcbSigBlob = 0; IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetFieldRecord(RidFromToken(fielddef), &pFieldRec)); IfFailRet(m_LiteWeightStgdb.m_MiniMd.getSignatureOfField(pFieldRec, ppSig, pcbSigBlob)); return S_OK; } // MDInternalRO::GetSigOfFieldDef //***************************************************************************** // Get signature for the token (FieldDef, MethodDef, Signature, or TypeSpec). //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetSigFromToken( mdToken tk, ULONG * pcbSig, PCCOR_SIGNATURE * ppSig) { HRESULT hr; *ppSig = NULL; *pcbSig = 0; switch (TypeFromToken(tk)) { case mdtSignature: { StandAloneSigRec * pRec; IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetStandAloneSigRecord(RidFromToken(tk), &pRec)); IfFailRet(m_LiteWeightStgdb.m_MiniMd.getSignatureOfStandAloneSig(pRec, ppSig, pcbSig)); return S_OK; } case mdtTypeSpec: { TypeSpecRec * pRec; IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetTypeSpecRecord(RidFromToken(tk), &pRec)); IfFailRet(m_LiteWeightStgdb.m_MiniMd.getSignatureOfTypeSpec(pRec, ppSig, pcbSig)); return S_OK; } case mdtMethodDef: { IfFailRet(GetSigOfMethodDef(tk, pcbSig, ppSig)); return S_OK; } case mdtFieldDef: { IfFailRet(GetSigOfFieldDef(tk, pcbSig, ppSig)); return S_OK; } } // not a known token type. *pcbSig = 0; return META_E_INVALID_TOKEN_TYPE; } // MDInternalRO::GetSigFromToken //***************************************************************************** // Given methoddef, return the flags //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetMethodDefProps( mdMethodDef md, DWORD *pdwFlags) // return mdPublic, mdAbstract, etc { HRESULT hr; MethodRec *pMethodRec; *pdwFlags = (DWORD)-1; IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodRecord(RidFromToken(md), &pMethodRec)); *pdwFlags = m_LiteWeightStgdb.m_MiniMd.getFlagsOfMethod(pMethodRec); return S_OK; } // MDInternalRO::GetMethodDefProps //***************************************************************************** // Given a scope and a methoddef/methodimpl, return RVA and impl flags //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetMethodImplProps( mdMethodDef tk, // [IN] MethodDef ULONG *pulCodeRVA, // [OUT] CodeRVA DWORD *pdwImplFlags) // [OUT] Impl. Flags { HRESULT hr; _ASSERTE(TypeFromToken(tk) == mdtMethodDef); MethodRec *pMethodRec; IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodRecord(RidFromToken(tk), &pMethodRec)); if (pulCodeRVA) { *pulCodeRVA = m_LiteWeightStgdb.m_MiniMd.getRVAOfMethod(pMethodRec); } if (pdwImplFlags) { *pdwImplFlags = m_LiteWeightStgdb.m_MiniMd.getImplFlagsOfMethod(pMethodRec); } return S_OK; } // MDInternalRO::GetMethodImplProps //***************************************************************************** // return the field RVA //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetFieldRVA( mdToken fd, // [IN] FieldDef ULONG *pulCodeRVA) // [OUT] CodeRVA { HRESULT hr; _ASSERTE(TypeFromToken(fd) == mdtFieldDef); _ASSERTE(pulCodeRVA); RID iRecord; IfFailRet(m_LiteWeightStgdb.m_MiniMd.FindFieldRVAFor(RidFromToken(fd), &iRecord)); if (InvalidRid(iRecord)) { if (pulCodeRVA) *pulCodeRVA = 0; return CLDB_E_RECORD_NOTFOUND; } FieldRVARec *pFieldRVARec; IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetFieldRVARecord(iRecord, &pFieldRVARec)); *pulCodeRVA = m_LiteWeightStgdb.m_MiniMd.getRVAOfFieldRVA(pFieldRVARec); return NOERROR; } //***************************************************************************** // Given a fielddef, return the flags. Such as fdPublic, fdStatic, etc //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetFieldDefProps( mdFieldDef fd, // given memberdef DWORD *pdwFlags) // [OUT] return fdPublic, fdPrive, etc flags { HRESULT hr; _ASSERTE(TypeFromToken(fd) == mdtFieldDef); FieldRec *pFieldRec; *pdwFlags = (DWORD)-1; IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetFieldRecord(RidFromToken(fd), &pFieldRec)); *pdwFlags = m_LiteWeightStgdb.m_MiniMd.getFlagsOfField(pFieldRec); return S_OK; } // MDInternalRO::GetFieldDefProps //***************************************************************************** // return default value of a token(could be paramdef, fielddef, or property) //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetDefaultValue( // return hresult mdToken tk, // [IN] given FieldDef, ParamDef, or Property MDDefaultValue *pMDDefaultValue) // [OUT] default value { _ASSERTE(pMDDefaultValue); HRESULT hr; BYTE bType; const VOID *pValue; ULONG cbValue; RID rid; IfFailRet(m_LiteWeightStgdb.m_MiniMd.FindConstantFor(RidFromToken(tk), TypeFromToken(tk), &rid)); if (InvalidRid(rid)) { pMDDefaultValue->m_bType = ELEMENT_TYPE_VOID; return S_OK; } ConstantRec *pConstantRec; IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetConstantRecord(rid, &pConstantRec)); // get the type of constant value bType = m_LiteWeightStgdb.m_MiniMd.getTypeOfConstant(pConstantRec); // get the value blob IfFailRet(m_LiteWeightStgdb.m_MiniMd.getValueOfConstant(pConstantRec, reinterpret_cast(&pValue), &cbValue)); // convert it to our internal default value representation hr = _FillMDDefaultValue(bType, pValue, cbValue, pMDDefaultValue); return hr; } // MDInternalRO::GetDefaultValue //***************************************************************************** // Given a scope and a methoddef/fielddef, return the dispid //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetDispIdOfMemberDef( // return hresult mdToken tk, // given methoddef or fielddef ULONG *pDispid) // Put the dispid here. { #ifdef FEATURE_COMINTEROP HRESULT hr; // A result. const BYTE *pBlob; // Blob with dispid. ULONG cbBlob; // Length of blob. UINT32 dispid; // temporary for dispid. // Get the DISPID, if any. _ASSERTE(pDispid); *pDispid = DISPID_UNKNOWN; hr = GetCustomAttributeByName(tk, INTEROP_DISPID_TYPE, (const void**)&pBlob, &cbBlob); if (hr == S_OK) { CustomAttributeParser cap(pBlob, cbBlob); IfFailGo(cap.SkipProlog()); IfFailGo(cap.GetU4(&dispid)); *pDispid = dispid; } ErrExit: return hr; #else // FEATURE_COMINTEROP _ASSERTE(false); return E_NOTIMPL; #endif // FEATURE_COMINTEROP } // MDInternalRO::GetDispIdOfMemberDef //***************************************************************************** // Given interfaceimpl, return the TypeRef/TypeDef and flags //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetTypeOfInterfaceImpl( // return hresult mdInterfaceImpl iiImpl, // given a interfaceimpl mdToken *ptkType) { HRESULT hr; _ASSERTE(TypeFromToken(iiImpl) == mdtInterfaceImpl); *ptkType = mdTypeDefNil; InterfaceImplRec *pIIRec; IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetInterfaceImplRecord(RidFromToken(iiImpl), &pIIRec)); *ptkType = m_LiteWeightStgdb.m_MiniMd.getInterfaceOfInterfaceImpl(pIIRec); return S_OK; } // MDInternalRO::GetTypeOfInterfaceImpl //***************************************************************************** // This routine gets the properties for the given MethodSpec token. //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetMethodSpecProps( // S_OK or error. mdMethodSpec mi, // [IN] The method instantiation mdToken *tkParent, // [OUT] MethodDef or MemberRef PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to the blob value of meta data ULONG *pcbSigBlob) // [OUT] actual size of signature blob { HRESULT hr = NOERROR; MethodSpecRec *pMethodSpecRec; LOG((LOGMD, "MD RegMeta::GetMethodSpecProps(0x%08x, 0x%08x, 0x%08x, 0x%08x)\n", mi, tkParent, ppvSigBlob, pcbSigBlob)); _ASSERTE(TypeFromToken(mi) == mdtMethodSpec); IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodSpecRecord(RidFromToken(mi), &pMethodSpecRec)); if (tkParent) *tkParent = m_LiteWeightStgdb.m_MiniMd.getMethodOfMethodSpec(pMethodSpecRec); if (ppvSigBlob || pcbSigBlob) { // caller wants signature information PCCOR_SIGNATURE pvSigTmp; ULONG cbSig; IfFailRet(m_LiteWeightStgdb.m_MiniMd.getInstantiationOfMethodSpec(pMethodSpecRec, &pvSigTmp, &cbSig)); if ( ppvSigBlob ) *ppvSigBlob = pvSigTmp; if ( pcbSigBlob) *pcbSigBlob = cbSig; } return hr; } // MDInternalRO::GetMethodSpecProps //***************************************************************************** // Given a classname, return the typedef //***************************************************************************** __checkReturn HRESULT MDInternalRO::FindTypeDef( LPCSTR szTypeDefNamespace, // [IN] Namespace for the TypeDef. LPCSTR szTypeDefName, // [IN] Name of the TypeDef. mdToken tkEnclosingClass, // [IN] TypeDef/TypeRef of enclosing class. mdTypeDef * ptkTypeDef) // [OUT] return typedef { HRESULT hr = S_OK; _ASSERTE((szTypeDefName != NULL) && (ptkTypeDef != NULL)); _ASSERTE((TypeFromToken(tkEnclosingClass) == mdtTypeRef) || (TypeFromToken(tkEnclosingClass) == mdtTypeDef) || IsNilToken(tkEnclosingClass)); // initialize the output parameter *ptkTypeDef = mdTypeDefNil; // Treat no namespace as empty string. if (szTypeDefNamespace == NULL) szTypeDefNamespace = ""; // Do a linear search ULONG cTypeDefRecs = m_LiteWeightStgdb.m_MiniMd.getCountTypeDefs(); TypeDefRec * pTypeDefRec; LPCUTF8 szName; LPCUTF8 szNamespace; DWORD dwFlags; // Get TypeDef of the tkEnclosingClass passed in if (TypeFromToken(tkEnclosingClass) == mdtTypeRef) { TypeRefRec * pTypeRefRec; mdToken tkResolutionScope; IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetTypeRefRecord(RidFromToken(tkEnclosingClass), &pTypeRefRec)); tkResolutionScope = m_LiteWeightStgdb.m_MiniMd.getResolutionScopeOfTypeRef(pTypeRefRec); IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNamespaceOfTypeRef(pTypeRefRec, &szNamespace)); IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfTypeRef(pTypeRefRec, &szName)); // Update tkEnclosingClass to TypeDef IfFailRet(FindTypeDef( szNamespace, szName, (TypeFromToken(tkResolutionScope) == mdtTypeRef) ? tkResolutionScope : mdTokenNil, &tkEnclosingClass)); _ASSERTE(TypeFromToken(tkEnclosingClass) == mdtTypeDef); } // Search for the TypeDef for (ULONG i = 1; i <= cTypeDefRecs; i++) { IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetTypeDefRecord(i, &pTypeDefRec)); dwFlags = m_LiteWeightStgdb.m_MiniMd.getFlagsOfTypeDef(pTypeDefRec); if (!IsTdNested(dwFlags) && !IsNilToken(tkEnclosingClass)) { // If the class is not Nested and EnclosingClass passed in is not nil continue; } else if (IsTdNested(dwFlags) && IsNilToken(tkEnclosingClass)) { // If the class is nested and EnclosingClass passed is nil continue; } else if (!IsNilToken(tkEnclosingClass)) { _ASSERTE(TypeFromToken(tkEnclosingClass) == mdtTypeDef); RID iNestedClassRec; NestedClassRec * pNestedClassRec; mdTypeDef tkEnclosingClassTmp; IfFailRet(m_LiteWeightStgdb.m_MiniMd.FindNestedClassFor(i, &iNestedClassRec)); if (InvalidRid(iNestedClassRec)) continue; IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetNestedClassRecord(iNestedClassRec, &pNestedClassRec)); tkEnclosingClassTmp = m_LiteWeightStgdb.m_MiniMd.getEnclosingClassOfNestedClass(pNestedClassRec); if (tkEnclosingClass != tkEnclosingClassTmp) continue; } IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfTypeDef(pTypeDefRec, &szName)); if (strcmp(szTypeDefName, szName) == 0) { IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNamespaceOfTypeDef(pTypeDefRec, &szNamespace)); if (strcmp(szTypeDefNamespace, szNamespace) == 0) { *ptkTypeDef = TokenFromRid(i, mdtTypeDef); return S_OK; } } } // Cannot find the TypeDef by name return CLDB_E_RECORD_NOTFOUND; } // MDInternalRO::FindTypeDef //***************************************************************************** // Given a memberref, return a pointer to memberref's name and signature //***************************************************************************** // Warning: Even when the return value is ok, *ppvSigBlob could be NULL if // the metadata is corrupted! (e.g. if CPackedLen::GetLength returned -1). // TODO: consider returning a HRESULT to make errors evident to the caller. //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetNameAndSigOfMemberRef( // meberref's name mdMemberRef memberref, // given a memberref PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to a blob value of COM+ signature ULONG *pcbSigBlob, // [OUT] count of bytes in the signature blob LPCSTR *pszMemberRefName) { _ASSERTE(TypeFromToken(memberref) == mdtMemberRef); HRESULT hr; MemberRefRec *pMemberRefRec; *pszMemberRefName = NULL; if (ppvSigBlob != NULL) { _ASSERTE(pcbSigBlob != NULL); *ppvSigBlob = NULL; *pcbSigBlob = 0; } IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMemberRefRecord(RidFromToken(memberref), &pMemberRefRec)); if (ppvSigBlob != NULL) { IfFailRet(m_LiteWeightStgdb.m_MiniMd.getSignatureOfMemberRef(pMemberRefRec, ppvSigBlob, pcbSigBlob)); } IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfMemberRef(pMemberRefRec, pszMemberRefName)); return S_OK; } // MDInternalRO::GetNameAndSigOfMemberRef //***************************************************************************** // Given a memberref, return parent token. It can be a TypeRef, ModuleRef, or a MethodDef //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetParentOfMemberRef( mdMemberRef memberref, // given a typedef mdToken *ptkParent) // return the parent token { HRESULT hr; _ASSERTE(TypeFromToken(memberref) == mdtMemberRef); MemberRefRec *pMemberRefRec; *ptkParent = mdTokenNil; IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMemberRefRecord(RidFromToken(memberref), &pMemberRefRec)); *ptkParent = m_LiteWeightStgdb.m_MiniMd.getClassOfMemberRef(pMemberRefRec); return S_OK; } // MDInternalRO::GetParentOfMemberRef //***************************************************************************** // return properties of a paramdef //*****************************************************************************/ __checkReturn HRESULT MDInternalRO::GetParamDefProps ( mdParamDef paramdef, // given a paramdef USHORT *pusSequence, // [OUT] slot number for this parameter DWORD *pdwAttr, // [OUT] flags LPCSTR *pszName) // [OUT] return the name of the parameter { _ASSERTE(TypeFromToken(paramdef) == mdtParamDef); HRESULT hr; ParamRec *pParamRec; *pszName = NULL; IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetParamRecord(RidFromToken(paramdef), &pParamRec)); if (pdwAttr != NULL) { *pdwAttr = m_LiteWeightStgdb.m_MiniMd.getFlagsOfParam(pParamRec); } if (pusSequence != NULL) { *pusSequence = m_LiteWeightStgdb.m_MiniMd.getSequenceOfParam(pParamRec); } IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfParam(pParamRec, pszName)); return S_OK; } // MDInternalRO::GetParamDefProps //***************************************************************************** // Get property info for the method. //***************************************************************************** int MDInternalRO::CMethodSemanticsMapSearcher::Compare( const CMethodSemanticsMap *psFirst, const CMethodSemanticsMap *psSecond) { if (psFirst->m_mdMethod < psSecond->m_mdMethod) return -1; if (psFirst->m_mdMethod > psSecond->m_mdMethod) return 1; return 0; } // MDInternalRO::CMethodSemanticsMapSearcher::Compare #ifndef DACCESS_COMPILE int MDInternalRO::CMethodSemanticsMapSorter::Compare( CMethodSemanticsMap *psFirst, CMethodSemanticsMap *psSecond) { if (psFirst->m_mdMethod < psSecond->m_mdMethod) return -1; if (psFirst->m_mdMethod > psSecond->m_mdMethod) return 1; return 0; } // MDInternalRO::CMethodSemanticsMapSorter::Compare __checkReturn HRESULT MDInternalRO::GetPropertyInfoForMethodDef( // Result. mdMethodDef md, // [IN] memberdef mdProperty *ppd, // [OUT] put property token here LPCSTR *pName, // [OUT] put pointer to name here ULONG *pSemantic) // [OUT] put semantic here { HRESULT hr; MethodSemanticsRec *pSemantics; // A MethodSemantics record. MethodSemanticsRec *pFound=0; // A MethodSemantics record that is a property for the desired function. RID ridCur; // loop control. RID ridMax; // Count of entries in table. USHORT usSemantics = 0; // A method's semantics. mdToken tk; // A method def. ridMax = m_LiteWeightStgdb.m_MiniMd.getCountMethodSemantics(); // Lazy initialization of m_pMethodSemanticsMap if ((ridMax > 10) && (m_pMethodSemanticsMap == NULL)) { NewHolder pMethodSemanticsMap = new (nothrow) CMethodSemanticsMap[ridMax]; if (pMethodSemanticsMap != NULL) { // Fill the table in MethodSemantics order. for (ridCur = 1; ridCur <= ridMax; ridCur++) { IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodSemanticsRecord(ridCur, &pSemantics)); tk = m_LiteWeightStgdb.m_MiniMd.getMethodOfMethodSemantics(pSemantics); pMethodSemanticsMap[ridCur-1].m_mdMethod = tk; pMethodSemanticsMap[ridCur-1].m_ridSemantics = ridCur; } // Sort to MethodDef order. CMethodSemanticsMapSorter sorter(pMethodSemanticsMap, ridMax); sorter.Sort(); if (InterlockedCompareExchangeT( &m_pMethodSemanticsMap, pMethodSemanticsMap, NULL) == NULL) { // The exchange did happen, supress of the allocated map pMethodSemanticsMap.SuppressRelease(); } } } // Use m_pMethodSemanticsMap if it has been built. if (m_pMethodSemanticsMap != NULL) { CMethodSemanticsMapSearcher searcher(m_pMethodSemanticsMap, ridMax); CMethodSemanticsMap target; const CMethodSemanticsMap * pMatchedMethod; target.m_mdMethod = md; pMatchedMethod = searcher.Find(&target); // Was there at least one match? if (pMatchedMethod != NULL) { _ASSERTE(pMatchedMethod >= m_pMethodSemanticsMap); _ASSERTE(pMatchedMethod < m_pMethodSemanticsMap+ridMax); _ASSERTE(pMatchedMethod->m_mdMethod == md); ridCur = pMatchedMethod->m_ridSemantics; IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodSemanticsRecord(ridCur, &pSemantics)); usSemantics = m_LiteWeightStgdb.m_MiniMd.getSemanticOfMethodSemantics(pSemantics); // If the semantics record is a getter or setter for the method, that's what we want. if (usSemantics == msGetter || usSemantics == msSetter) pFound = pSemantics; else { // The semantics record was neither getter or setter. Because there can be // multiple semantics records for a given method, look for other semantics // records that match this record. const CMethodSemanticsMap *pScan; const CMethodSemanticsMap *pLo=m_pMethodSemanticsMap; const CMethodSemanticsMap *pHi=pLo+ridMax-1; for (pScan = pMatchedMethod-1; pScan >= pLo; --pScan) { if (pScan->m_mdMethod == md) { ridCur = pScan->m_ridSemantics; IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodSemanticsRecord(ridCur, &pSemantics)); usSemantics = m_LiteWeightStgdb.m_MiniMd.getSemanticOfMethodSemantics(pSemantics); if (usSemantics == msGetter || usSemantics == msSetter) { pFound = pSemantics; break; } } else break; } if (pFound == 0) { // Not found looking down, try looking up. for (pScan = pMatchedMethod+1; pScan <= pHi; ++pScan) { if (pScan->m_mdMethod == md) { ridCur = pScan->m_ridSemantics; IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodSemanticsRecord(ridCur, &pSemantics)); usSemantics = m_LiteWeightStgdb.m_MiniMd.getSemanticOfMethodSemantics(pSemantics); if (usSemantics == msGetter || usSemantics == msSetter) { pFound = pSemantics; break; } } else break; } } } } } else { // Scan entire table. for (ridCur = 1; ridCur <= ridMax; ridCur++) { IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodSemanticsRecord(ridCur, &pSemantics)); if (md == m_LiteWeightStgdb.m_MiniMd.getMethodOfMethodSemantics(pSemantics)) { // The method matched, is this a property? usSemantics = m_LiteWeightStgdb.m_MiniMd.getSemanticOfMethodSemantics(pSemantics); if (usSemantics == msGetter || usSemantics == msSetter) { // found a match. pFound = pSemantics; break; } } } } // Did the search find anything? if (pFound) { // found a match. Fill out the output parameters PropertyRec *pProperty; mdProperty prop; prop = m_LiteWeightStgdb.m_MiniMd.getAssociationOfMethodSemantics(pFound); if (ppd) *ppd = prop; IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetPropertyRecord(RidFromToken(prop), &pProperty)); if (pName != NULL) { IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfProperty(pProperty, pName)); } if (pSemantic) *pSemantic = usSemantics; return S_OK; } return S_FALSE; } // MDInternalRO::GetPropertyInfoForMethodDef #endif //!DACCESS_COMPILE //***************************************************************************** // return the pack size of a class //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetClassPackSize( mdTypeDef td, // [IN] give typedef DWORD *pdwPackSize) // [OUT] { HRESULT hr = NOERROR; _ASSERTE(TypeFromToken(td) == mdtTypeDef && pdwPackSize); ClassLayoutRec *pRec; RID ridClassLayout; IfFailGo(m_LiteWeightStgdb.m_MiniMd.FindClassLayoutFor(RidFromToken(td), &ridClassLayout)); if (InvalidRid(ridClassLayout)) { hr = CLDB_E_RECORD_NOTFOUND; goto ErrExit; } IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetClassLayoutRecord(RidFromToken(ridClassLayout), &pRec)); *pdwPackSize = m_LiteWeightStgdb.m_MiniMd.getPackingSizeOfClassLayout(pRec); ErrExit: return hr; } // MDInternalRO::GetClassPackSize //***************************************************************************** // return the total size of a value class //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetClassTotalSize( // return error if a class does not have total size info mdTypeDef td, // [IN] give typedef ULONG *pulClassSize) // [OUT] return the total size of the class { _ASSERTE(TypeFromToken(td) == mdtTypeDef && pulClassSize); ClassLayoutRec *pRec; HRESULT hr = NOERROR; RID ridClassLayout; IfFailGo(m_LiteWeightStgdb.m_MiniMd.FindClassLayoutFor(RidFromToken(td), &ridClassLayout)); if (InvalidRid(ridClassLayout)) { hr = CLDB_E_RECORD_NOTFOUND; goto ErrExit; } IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetClassLayoutRecord(RidFromToken(ridClassLayout), &pRec)); *pulClassSize = m_LiteWeightStgdb.m_MiniMd.getClassSizeOfClassLayout(pRec); ErrExit: return hr; } // MDInternalRO::GetClassTotalSize //***************************************************************************** // init the layout enumerator of a class //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetClassLayoutInit( mdTypeDef td, // [IN] give typedef MD_CLASS_LAYOUT *pmdLayout) // [OUT] set up the status of query here { HRESULT hr = NOERROR; _ASSERTE(TypeFromToken(td) == mdtTypeDef); // initialize the output parameter _ASSERTE(pmdLayout); memset(pmdLayout, 0, sizeof(MD_CLASS_LAYOUT)); TypeDefRec *pTypeDefRec; // record for this typedef in TypeDef Table IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetTypeDefRecord(RidFromToken(td), &pTypeDefRec)); // find the starting and end field for this typedef pmdLayout->m_ridFieldCur = m_LiteWeightStgdb.m_MiniMd.getFieldListOfTypeDef(pTypeDefRec); IfFailRet(m_LiteWeightStgdb.m_MiniMd.getEndFieldListOfTypeDef(RidFromToken(td), &(pmdLayout->m_ridFieldEnd))); return hr; } // MDInternalRO::GetClassLayoutInit //***************************************************************************** // return the field offset for a given field //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetFieldOffset( mdFieldDef fd, // [IN] fielddef ULONG *pulOffset) // [OUT] FieldOffset { HRESULT hr = S_OK; FieldLayoutRec *pRec; _ASSERTE(pulOffset); RID iLayout; IfFailGo(m_LiteWeightStgdb.m_MiniMd.FindFieldLayoutFor(RidFromToken(fd), &iLayout)); if (InvalidRid(iLayout)) { hr = S_FALSE; goto ErrExit; } IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetFieldLayoutRecord(iLayout, &pRec)); *pulOffset = m_LiteWeightStgdb.m_MiniMd.getOffSetOfFieldLayout(pRec); _ASSERTE(*pulOffset != ULONG_MAX); ErrExit: return hr; } //***************************************************************************** // enum the next the field layout //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetClassLayoutNext( MD_CLASS_LAYOUT *pLayout, // [IN|OUT] set up the status of query here mdFieldDef *pfd, // [OUT] field def ULONG *pulOffset) // [OUT] field offset or sequence { HRESULT hr = S_OK; _ASSERTE(pfd && pulOffset && pLayout); RID iLayout2; FieldLayoutRec *pRec; // Make sure no one is messing with pLayout->m_ridFieldLayoutCur, since this doesn't // mean anything if we are using FieldLayout table. while (pLayout->m_ridFieldCur < pLayout->m_ridFieldEnd) { IfFailGo(m_LiteWeightStgdb.m_MiniMd.FindFieldLayoutFor(pLayout->m_ridFieldCur, &iLayout2)); pLayout->m_ridFieldCur++; if (!InvalidRid(iLayout2)) { IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetFieldLayoutRecord(iLayout2, &pRec)); *pulOffset = m_LiteWeightStgdb.m_MiniMd.getOffSetOfFieldLayout(pRec); _ASSERTE(*pulOffset != ULONG_MAX); *pfd = TokenFromRid(pLayout->m_ridFieldCur - 1, mdtFieldDef); goto ErrExit; } } *pfd = mdFieldDefNil; hr = S_FALSE; // fall through ErrExit: return hr; } // MDInternalRO::GetClassLayoutNext //***************************************************************************** // return the field's native type signature //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetFieldMarshal( // return error if no native type associate with the token mdToken tk, // [IN] given fielddef or paramdef PCCOR_SIGNATURE *pSigNativeType, // [OUT] the native type signature ULONG *pcbNativeType) // [OUT] the count of bytes of *ppvNativeType { // output parameters have to be supplied _ASSERTE(pcbNativeType); RID rid; FieldMarshalRec *pFieldMarshalRec; HRESULT hr = NOERROR; // find the row containing the marshal definition for tk IfFailGo(m_LiteWeightStgdb.m_MiniMd.FindFieldMarshalFor(RidFromToken(tk), TypeFromToken(tk), &rid)); if (InvalidRid(rid)) { *pSigNativeType = NULL; *pcbNativeType = 0; hr = CLDB_E_RECORD_NOTFOUND; goto ErrExit; } IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetFieldMarshalRecord(rid, &pFieldMarshalRec)); // get the native type IfFailGo(m_LiteWeightStgdb.m_MiniMd.getNativeTypeOfFieldMarshal(pFieldMarshalRec, pSigNativeType, pcbNativeType)); ErrExit: return hr; } // MDInternalRO::GetFieldMarshal //***************************************** // property APIs //***************************************** //***************************************************************************** // Find property by name //***************************************************************************** __checkReturn HRESULT MDInternalRO::FindProperty( mdTypeDef td, // [IN] given a typdef LPCSTR szPropName, // [IN] property name mdProperty *pProp) // [OUT] return property token { HRESULT hr = NOERROR; // output parameters have to be supplied _ASSERTE(TypeFromToken(td) == mdtTypeDef && pProp); PropertyMapRec *pRec; PropertyRec *pProperty; RID ridPropertyMap; RID ridCur; RID ridEnd; LPCUTF8 szName; IfFailGo(m_LiteWeightStgdb.m_MiniMd.FindPropertyMapFor(RidFromToken(td), &ridPropertyMap)); if (InvalidRid(ridPropertyMap)) { // not found! hr = CLDB_E_RECORD_NOTFOUND; goto ErrExit; } IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetPropertyMapRecord(ridPropertyMap, &pRec)); // get the starting/ending rid of properties of this typedef ridCur = m_LiteWeightStgdb.m_MiniMd.getPropertyListOfPropertyMap(pRec); IfFailGo(m_LiteWeightStgdb.m_MiniMd.getEndPropertyListOfPropertyMap(ridPropertyMap, &ridEnd)); for (; ridCur < ridEnd; ridCur ++) { IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetPropertyRecord(ridCur, &pProperty)); IfFailGo(m_LiteWeightStgdb.m_MiniMd.getNameOfProperty(pProperty, &szName)); if (strcmp(szName, szPropName) ==0) { // Found the match. Set the output parameter and we are done. *pProp = TokenFromRid(ridCur, mdtProperty); goto ErrExit; } } // not found hr = CLDB_E_RECORD_NOTFOUND; ErrExit: return hr; } // MDInternalRO::FindProperty //***************************************************************************** // return the properties of a property //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetPropertyProps( mdProperty prop, // [IN] property token LPCSTR *pszProperty, // [OUT] property name DWORD *pdwPropFlags, // [OUT] property flags. PCCOR_SIGNATURE *ppvSig, // [OUT] property type. pointing to meta data internal blob ULONG *pcbSig) // [OUT] count of bytes in *ppvSig { // output parameters have to be supplied _ASSERTE(TypeFromToken(prop) == mdtProperty); HRESULT hr; PropertyRec *pProperty; ULONG cbSig; IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetPropertyRecord(RidFromToken(prop), &pProperty)); // get name of the property if (pszProperty != NULL) { IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfProperty(pProperty, pszProperty)); } // get the flags of property if (pdwPropFlags) *pdwPropFlags = m_LiteWeightStgdb.m_MiniMd.getPropFlagsOfProperty(pProperty); // get the type of the property if (ppvSig != NULL) { IfFailRet(m_LiteWeightStgdb.m_MiniMd.getTypeOfProperty(pProperty, ppvSig, &cbSig)); if (pcbSig != NULL) { *pcbSig = cbSig; } } return S_OK; } // MDInternalRO::GetPropertyProps //********************************** // // Event APIs // //********************************** //***************************************************************************** // return an event by given the name //***************************************************************************** __checkReturn HRESULT MDInternalRO::FindEvent( mdTypeDef td, // [IN] given a typdef LPCSTR szEventName, // [IN] event name mdEvent *pEvent) // [OUT] return event token { HRESULT hr = NOERROR; // output parameters have to be supplied _ASSERTE(TypeFromToken(td) == mdtTypeDef && pEvent); EventMapRec *pRec; EventRec *pEventRec; RID ridEventMap; RID ridCur; RID ridEnd; LPCUTF8 szName; IfFailGo(m_LiteWeightStgdb.m_MiniMd.FindEventMapFor(RidFromToken(td), &ridEventMap)); if (InvalidRid(ridEventMap)) { // not found! hr = CLDB_E_RECORD_NOTFOUND; goto ErrExit; } IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetEventMapRecord(ridEventMap, &pRec)); // get the starting/ending rid of properties of this typedef ridCur = m_LiteWeightStgdb.m_MiniMd.getEventListOfEventMap(pRec); IfFailGo(m_LiteWeightStgdb.m_MiniMd.getEndEventListOfEventMap(ridEventMap, &ridEnd)); for (; ridCur < ridEnd; ridCur ++) { IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetEventRecord(ridCur, &pEventRec)); IfFailGo(m_LiteWeightStgdb.m_MiniMd.getNameOfEvent(pEventRec, &szName)); if (strcmp(szName, szEventName) ==0) { // Found the match. Set the output parameter and we are done. *pEvent = TokenFromRid(ridCur, mdtEvent); goto ErrExit; } } // not found hr = CLDB_E_RECORD_NOTFOUND; ErrExit: return hr; } // MDInternalRO::FindEvent //***************************************************************************** // return the properties of an event //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetEventProps( // S_OK, S_FALSE, or error. mdEvent ev, // [IN] event token LPCSTR *pszEvent, // [OUT] Event name DWORD *pdwEventFlags, // [OUT] Event flags. mdToken *ptkEventType) // [OUT] EventType class { // output parameters have to be supplied _ASSERTE(TypeFromToken(ev) == mdtEvent); HRESULT hr; EventRec *pEvent; IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetEventRecord(RidFromToken(ev), &pEvent)); if (pszEvent != NULL) { IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfEvent(pEvent, pszEvent)); } if (pdwEventFlags) *pdwEventFlags = m_LiteWeightStgdb.m_MiniMd.getEventFlagsOfEvent(pEvent); if (ptkEventType) *ptkEventType = m_LiteWeightStgdb.m_MiniMd.getEventTypeOfEvent(pEvent); return S_OK; } // MDInternalRO::GetEventProps //***************************************************************************** // return the properties of a generic param //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetGenericParamProps( // S_OK or error. mdGenericParam rd, // [IN] The type parameter ULONG* pulSequence, // [OUT] Parameter sequence number DWORD* pdwAttr, // [OUT] Type parameter flags (for future use) mdToken *ptOwner, // [OUT] The owner (TypeDef or MethodDef) DWORD *reserved, // [OUT] The kind (TypeDef/Ref/Spec, for future use) LPCSTR *szName) // [OUT] The name { HRESULT hr = NOERROR; GenericParamRec * pGenericParamRec = NULL; // See if this version of the metadata can do Generics if (!m_LiteWeightStgdb.m_MiniMd.SupportsGenerics()) IfFailGo(CLDB_E_INCOMPATIBLE); _ASSERTE(TypeFromToken(rd) == mdtGenericParam); if (TypeFromToken(rd) != mdtGenericParam) { IfFailGo(CLDB_E_FILE_CORRUPT); } IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetGenericParamRecord(RidFromToken(rd), &pGenericParamRec)); if (pulSequence) *pulSequence = m_LiteWeightStgdb.m_MiniMd.getNumberOfGenericParam(pGenericParamRec); if (pdwAttr) *pdwAttr = m_LiteWeightStgdb.m_MiniMd.getFlagsOfGenericParam(pGenericParamRec); if (ptOwner) *ptOwner = m_LiteWeightStgdb.m_MiniMd.getOwnerOfGenericParam(pGenericParamRec); if (szName != NULL) { IfFailGo(m_LiteWeightStgdb.m_MiniMd.getNameOfGenericParam(pGenericParamRec, szName)); } ErrExit: return hr; } // MDInternalRO::GetGenericParamProps //***************************************************************************** // This routine gets the properties for the given GenericParamConstraint token. //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetGenericParamConstraintProps( // S_OK or error. mdGenericParamConstraint rd, // [IN] The constraint token mdGenericParam *ptGenericParam, // [OUT] GenericParam that is constrained mdToken *ptkConstraintType) // [OUT] TypeDef/Ref/Spec constraint { HRESULT hr = NOERROR; GenericParamConstraintRec *pGPCRec; RID ridRD = RidFromToken(rd); // See if this version of the metadata can do Generics if (!m_LiteWeightStgdb.m_MiniMd.SupportsGenerics()) IfFailGo(CLDB_E_INCOMPATIBLE); if((TypeFromToken(rd) == mdtGenericParamConstraint) && (ridRD != 0)) { IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetGenericParamConstraintRecord(ridRD, &pGPCRec)); if (ptGenericParam) *ptGenericParam = TokenFromRid(m_LiteWeightStgdb.m_MiniMd.getOwnerOfGenericParamConstraint(pGPCRec),mdtGenericParam); if (ptkConstraintType) *ptkConstraintType = m_LiteWeightStgdb.m_MiniMd.getConstraintOfGenericParamConstraint(pGPCRec); } else hr = META_E_BAD_INPUT_PARAMETER; ErrExit: return hr; } // MDInternalRO::GetGenericParamConstraintProps //***************************************************************************** // Find methoddef of a particular associate with a property or an event //***************************************************************************** __checkReturn HRESULT MDInternalRO::FindAssociate( mdToken evprop, // [IN] given a property or event token DWORD dwSemantics, // [IN] given a associate semantics(setter, getter, testdefault, reset) mdMethodDef *pmd) // [OUT] return method def token { HRESULT hr = NOERROR; // output parameters have to be supplied _ASSERTE(pmd); _ASSERTE(TypeFromToken(evprop) == mdtEvent || TypeFromToken(evprop) == mdtProperty); MethodSemanticsRec *pSemantics; RID ridCur; RID ridEnd; IfFailGo(m_LiteWeightStgdb.m_MiniMd.getAssociatesForToken(evprop, &ridEnd, &ridCur)); for (; ridCur < ridEnd; ridCur++) { IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetMethodSemanticsRecord(ridCur, &pSemantics)); if (dwSemantics == m_LiteWeightStgdb.m_MiniMd.getSemanticOfMethodSemantics(pSemantics)) { // found a match *pmd = m_LiteWeightStgdb.m_MiniMd.getMethodOfMethodSemantics(pSemantics); goto ErrExit; } } // not found hr = CLDB_E_RECORD_NOTFOUND; ErrExit: return hr; } // MDInternalRO::FindAssociate //***************************************************************************** // get counts of methodsemantics associated with a particular property/event //***************************************************************************** __checkReturn HRESULT MDInternalRO::EnumAssociateInit( mdToken evprop, // [IN] given a property or an event token HENUMInternal *phEnum) // [OUT] cursor to hold the query result { HRESULT hr; _ASSERTE(phEnum); memset(phEnum, 0, sizeof(HENUMInternal)); // There is no token kind!!! phEnum->m_tkKind = ULONG_MAX; // output parameters have to be supplied _ASSERTE(TypeFromToken(evprop) == mdtEvent || TypeFromToken(evprop) == mdtProperty); phEnum->m_EnumType = MDSimpleEnum; IfFailRet(m_LiteWeightStgdb.m_MiniMd.getAssociatesForToken(evprop, &phEnum->u.m_ulEnd, &phEnum->u.m_ulStart)); phEnum->u.m_ulCur = phEnum->u.m_ulStart; phEnum->m_ulCount = phEnum->u.m_ulEnd - phEnum->u.m_ulStart; return S_OK; } // MDInternalRO::EnumAssociateInit //***************************************************************************** // get all methodsemantics associated with a particular property/event //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetAllAssociates( HENUMInternal *phEnum, // [OUT] cursor to hold the query result ASSOCIATE_RECORD *pAssociateRec, // [OUT] struct to fill for output ULONG cAssociateRec) // [IN] size of the buffer { _ASSERTE(phEnum && pAssociateRec); HRESULT hr; MethodSemanticsRec *pSemantics; RID ridCur; _ASSERTE(cAssociateRec == phEnum->m_ulCount); // Convert from row pointers to RIDs. for (ridCur = phEnum->u.m_ulStart; ridCur < phEnum->u.m_ulEnd; ++ridCur) { IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodSemanticsRecord(ridCur, &pSemantics)); pAssociateRec[ridCur-phEnum->u.m_ulStart].m_memberdef = m_LiteWeightStgdb.m_MiniMd.getMethodOfMethodSemantics(pSemantics); pAssociateRec[ridCur-phEnum->u.m_ulStart].m_dwSemantics = m_LiteWeightStgdb.m_MiniMd.getSemanticOfMethodSemantics(pSemantics); } return S_OK; } // MDInternalRO::GetAllAssociates //***************************************************************************** // Get the Action and Permissions blob for a given PermissionSet. //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetPermissionSetProps( mdPermission pm, // [IN] the permission token. DWORD *pdwAction, // [OUT] CorDeclSecurity. void const **ppvPermission, // [OUT] permission blob. ULONG *pcbPermission) // [OUT] count of bytes of pvPermission. { HRESULT hr; _ASSERTE(TypeFromToken(pm) == mdtPermission); _ASSERTE(pdwAction && ppvPermission && pcbPermission); DeclSecurityRec *pPerm; IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetDeclSecurityRecord(RidFromToken(pm), &pPerm)); *pdwAction = m_LiteWeightStgdb.m_MiniMd.getActionOfDeclSecurity(pPerm); IfFailRet(m_LiteWeightStgdb.m_MiniMd.getPermissionSetOfDeclSecurity(pPerm, (const BYTE **)ppvPermission, pcbPermission)); return S_OK; } // MDInternalRO::GetPermissionSetProps //***************************************************************************** // Get the String given the String token. // Return a pointer to the string, or NULL in case of error. //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetUserString( // Offset into the string blob heap. mdString stk, // [IN] the string token. ULONG *pcchStringSize, // [OUT] count of characters in the string. BOOL *pfIs80Plus, // [OUT] specifies where there are extended characters >= 0x80. LPCWSTR *pwszUserString) { HRESULT hr; LPWSTR wszTmp; if (pfIs80Plus != NULL) { *pfIs80Plus = FALSE; } *pwszUserString = NULL; *pcchStringSize = 0; _ASSERTE(pcchStringSize != NULL); MetaData::DataBlob userString; IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetUserString(RidFromToken(stk), &userString)); wszTmp = reinterpret_cast(userString.GetDataPointer()); *pcchStringSize = userString.GetSize() / sizeof(WCHAR); if (userString.IsEmpty()) { *pwszUserString = NULL; return S_OK; } if (pfIs80Plus != NULL) { if (userString.GetSize() % sizeof(WCHAR) == 0) { *pfIs80Plus = TRUE; // no indicator, presume the worst } // Return the user string terminator (contains value fIs80Plus) *pfIs80Plus = *(reinterpret_cast(wszTmp + *pcchStringSize)); } *pwszUserString = wszTmp; return S_OK; } // MDInternalRO::GetUserString //***************************************************************************** // Return contents of Pinvoke given the forwarded member token. //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetPinvokeMap( mdToken tk, // [IN] FieldDef or MethodDef. DWORD *pdwMappingFlags, // [OUT] Flags used for mapping. LPCSTR *pszImportName, // [OUT] Import name. mdModuleRef *pmrImportDLL) // [OUT] ModuleRef token for the target DLL. { HRESULT hr; ImplMapRec *pRecord; RID iRecord; IfFailRet(m_LiteWeightStgdb.m_MiniMd.FindImplMapFor(RidFromToken(tk), TypeFromToken(tk), &iRecord)); if (InvalidRid(iRecord)) { return CLDB_E_RECORD_NOTFOUND; } else { IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetImplMapRecord(iRecord, &pRecord)); } if (pdwMappingFlags) *pdwMappingFlags = m_LiteWeightStgdb.m_MiniMd.getMappingFlagsOfImplMap(pRecord); if (pszImportName != NULL) { IfFailRet(m_LiteWeightStgdb.m_MiniMd.getImportNameOfImplMap(pRecord, pszImportName)); } if (pmrImportDLL) *pmrImportDLL = m_LiteWeightStgdb.m_MiniMd.getImportScopeOfImplMap(pRecord); return S_OK; } // MDInternalRO::GetPinvokeMap //***************************************************************************** // Get the properties for the given Assembly token. //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetAssemblyProps( mdAssembly mda, // [IN] The Assembly for which to get the properties. const void **ppbPublicKey, // [OUT] Pointer to the public key. ULONG *pcbPublicKey, // [OUT] Count of bytes in the public key. ULONG *pulHashAlgId, // [OUT] Hash Algorithm. LPCSTR *pszName, // [OUT] Buffer to fill with name. AssemblyMetaDataInternal *pMetaData,// [OUT] Assembly MetaData. DWORD *pdwAssemblyFlags) // [OUT] Flags. { HRESULT hr; AssemblyRec *pRecord; _ASSERTE(TypeFromToken(mda) == mdtAssembly && RidFromToken(mda)); IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetAssemblyRecord(RidFromToken(mda), &pRecord)); if (ppbPublicKey != NULL) { IfFailRet(m_LiteWeightStgdb.m_MiniMd.getPublicKeyOfAssembly(pRecord, reinterpret_cast(ppbPublicKey), pcbPublicKey)); } if (pulHashAlgId) *pulHashAlgId = m_LiteWeightStgdb.m_MiniMd.getHashAlgIdOfAssembly(pRecord); if (pszName != NULL) { IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfAssembly(pRecord, pszName)); } if (pMetaData) { pMetaData->usMajorVersion = m_LiteWeightStgdb.m_MiniMd.getMajorVersionOfAssembly(pRecord); pMetaData->usMinorVersion = m_LiteWeightStgdb.m_MiniMd.getMinorVersionOfAssembly(pRecord); pMetaData->usBuildNumber = m_LiteWeightStgdb.m_MiniMd.getBuildNumberOfAssembly(pRecord); pMetaData->usRevisionNumber = m_LiteWeightStgdb.m_MiniMd.getRevisionNumberOfAssembly(pRecord); IfFailRet(m_LiteWeightStgdb.m_MiniMd.getLocaleOfAssembly(pRecord, &pMetaData->szLocale)); pMetaData->ulProcessor = 0; pMetaData->ulOS = 0; } if (pdwAssemblyFlags) { *pdwAssemblyFlags = m_LiteWeightStgdb.m_MiniMd.getFlagsOfAssembly(pRecord); #ifdef FEATURE_WINDOWSPHONE // Turn on the afPublicKey if PublicKey blob is not empty DWORD cbPublicKey; const BYTE *pbPublicKey; IfFailRet(m_LiteWeightStgdb.m_MiniMd.getPublicKeyOfAssembly(pRecord, &pbPublicKey, &cbPublicKey)); if (cbPublicKey != 0) *pdwAssemblyFlags |= afPublicKey; #else if (ppbPublicKey) { if (pcbPublicKey && *pcbPublicKey) *pdwAssemblyFlags |= afPublicKey; } else { #ifdef _DEBUG // Assert that afPublicKey is set if PublicKey blob is not empty DWORD cbPublicKey; const BYTE *pPublicKey; IfFailRet(m_LiteWeightStgdb.m_MiniMd.getPublicKeyOfAssembly(pRecord, &pPublicKey, &cbPublicKey)); bool hasPublicKey = cbPublicKey != 0; bool hasPublicKeyFlag = ( *pdwAssemblyFlags & afPublicKey ) != 0; if(REGUTIL::GetConfigDWORD_DontUse_(CLRConfig::INTERNAL_AssertOnBadImageFormat, 0)) _ASSERTE( hasPublicKey == hasPublicKeyFlag ); #endif } #endif // FEATURE_WINDOWSPHONE } return S_OK; } // MDInternalRO::GetAssemblyProps //***************************************************************************** // Get the properties for the given AssemblyRef token. //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetAssemblyRefProps( mdAssemblyRef mdar, // [IN] The AssemblyRef for which to get the properties. const void **ppbPublicKeyOrToken, // [OUT] Pointer to the public key or token. ULONG *pcbPublicKeyOrToken, // [OUT] Count of bytes in the public key or token. LPCSTR *pszName, // [OUT] Buffer to fill with name. AssemblyMetaDataInternal *pMetaData,// [OUT] Assembly MetaData. const void **ppbHashValue, // [OUT] Hash blob. ULONG *pcbHashValue, // [OUT] Count of bytes in the hash blob. DWORD *pdwAssemblyRefFlags) // [OUT] Flags. { HRESULT hr; AssemblyRefRec *pRecord; _ASSERTE(TypeFromToken(mdar) == mdtAssemblyRef && RidFromToken(mdar)); IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetAssemblyRefRecord(RidFromToken(mdar), &pRecord)); if (ppbPublicKeyOrToken != NULL) { IfFailRet(m_LiteWeightStgdb.m_MiniMd.getPublicKeyOrTokenOfAssemblyRef(pRecord, reinterpret_cast(ppbPublicKeyOrToken), pcbPublicKeyOrToken)); } if (pszName != NULL) { IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfAssemblyRef(pRecord, pszName)); } if (pMetaData) { pMetaData->usMajorVersion = m_LiteWeightStgdb.m_MiniMd.getMajorVersionOfAssemblyRef(pRecord); pMetaData->usMinorVersion = m_LiteWeightStgdb.m_MiniMd.getMinorVersionOfAssemblyRef(pRecord); pMetaData->usBuildNumber = m_LiteWeightStgdb.m_MiniMd.getBuildNumberOfAssemblyRef(pRecord); pMetaData->usRevisionNumber = m_LiteWeightStgdb.m_MiniMd.getRevisionNumberOfAssemblyRef(pRecord); IfFailRet(m_LiteWeightStgdb.m_MiniMd.getLocaleOfAssemblyRef(pRecord, &pMetaData->szLocale)); pMetaData->ulProcessor = 0; pMetaData->ulOS = 0; } if (ppbHashValue != NULL) { IfFailRet(m_LiteWeightStgdb.m_MiniMd.getHashValueOfAssemblyRef(pRecord, reinterpret_cast(ppbHashValue), pcbHashValue)); } if (pdwAssemblyRefFlags != NULL) { *pdwAssemblyRefFlags = m_LiteWeightStgdb.m_MiniMd.getFlagsOfAssemblyRef(pRecord); } return S_OK; } // MDInternalRO::GetAssemblyRefProps //***************************************************************************** // Get the properties for the given File token. //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetFileProps( mdFile mdf, // [IN] The File for which to get the properties. LPCSTR *pszName, // [OUT] Buffer to fill with name. const void **ppbHashValue, // [OUT] Pointer to the Hash Value Blob. ULONG *pcbHashValue, // [OUT] Count of bytes in the Hash Value Blob. DWORD *pdwFileFlags) // [OUT] Flags. { HRESULT hr; FileRec *pRecord; _ASSERTE(TypeFromToken(mdf) == mdtFile && RidFromToken(mdf)); IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetFileRecord(RidFromToken(mdf), &pRecord)); if (pszName != NULL) { IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfFile(pRecord, pszName)); } if (ppbHashValue != NULL) { IfFailRet(m_LiteWeightStgdb.m_MiniMd.getHashValueOfFile(pRecord, reinterpret_cast(ppbHashValue), pcbHashValue)); } if (pdwFileFlags != NULL) { *pdwFileFlags = m_LiteWeightStgdb.m_MiniMd.getFlagsOfFile(pRecord); } return S_OK; } // MDInternalRO::GetFileProps //***************************************************************************** // Get the properties for the given ExportedType token. //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetExportedTypeProps( mdExportedType mdct, // [IN] The ExportedType for which to get the properties. LPCSTR *pszNamespace, // [OUT] Buffer to fill with namespace. LPCSTR *pszName, // [OUT] Buffer to fill with name. mdToken *ptkImplementation, // [OUT] mdFile or mdAssemblyRef that provides the ExportedType. mdTypeDef *ptkTypeDef, // [OUT] TypeDef token within the file. DWORD *pdwExportedTypeFlags) // [OUT] Flags. { HRESULT hr; ExportedTypeRec *pRecord; _ASSERTE(TypeFromToken(mdct) == mdtExportedType && RidFromToken(mdct)); IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetExportedTypeRecord(RidFromToken(mdct), &pRecord)); if (pszNamespace != NULL) { IfFailRet(m_LiteWeightStgdb.m_MiniMd.getTypeNamespaceOfExportedType(pRecord, pszNamespace)); } if (pszName != NULL) { IfFailRet(m_LiteWeightStgdb.m_MiniMd.getTypeNameOfExportedType(pRecord, pszName)); } if (ptkImplementation) *ptkImplementation = m_LiteWeightStgdb.m_MiniMd.getImplementationOfExportedType(pRecord); if (ptkTypeDef) *ptkTypeDef = m_LiteWeightStgdb.m_MiniMd.getTypeDefIdOfExportedType(pRecord); if (pdwExportedTypeFlags) *pdwExportedTypeFlags = m_LiteWeightStgdb.m_MiniMd.getFlagsOfExportedType(pRecord); return S_OK; } // MDInternalRO::GetExportedTypeProps //***************************************************************************** // Get the properties for the given Resource token. //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetManifestResourceProps( mdManifestResource mdmr, // [IN] The ManifestResource for which to get the properties. LPCSTR *pszName, // [OUT] Buffer to fill with name. mdToken *ptkImplementation, // [OUT] mdFile or mdAssemblyRef that provides the ExportedType. DWORD *pdwOffset, // [OUT] Offset to the beginning of the resource within the file. DWORD *pdwResourceFlags) // [OUT] Flags. { HRESULT hr; ManifestResourceRec *pRecord; _ASSERTE(TypeFromToken(mdmr) == mdtManifestResource && RidFromToken(mdmr)); IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetManifestResourceRecord(RidFromToken(mdmr), &pRecord)); if (pszName != NULL) { IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfManifestResource(pRecord, pszName)); } if (ptkImplementation) *ptkImplementation = m_LiteWeightStgdb.m_MiniMd.getImplementationOfManifestResource(pRecord); if (pdwOffset) *pdwOffset = m_LiteWeightStgdb.m_MiniMd.getOffsetOfManifestResource(pRecord); if (pdwResourceFlags) *pdwResourceFlags = m_LiteWeightStgdb.m_MiniMd.getFlagsOfManifestResource(pRecord); return S_OK; } // MDInternalRO::GetManifestResourceProps //***************************************************************************** // Find the ExportedType given the name. //***************************************************************************** __checkReturn STDMETHODIMP MDInternalRO::FindExportedTypeByName( // S_OK or error LPCSTR szNamespace, // [IN] Namespace of the ExportedType. LPCSTR szName, // [IN] Name of the ExportedType. mdExportedType tkEnclosingType, // [IN] Token for the Enclosing Type. mdExportedType *pmct) // [OUT] Put ExportedType token here. { IMetaModelCommon *pCommon = static_cast(&m_LiteWeightStgdb.m_MiniMd); return pCommon->CommonFindExportedType(szNamespace, szName, tkEnclosingType, pmct); } // MDInternalRO::FindExportedTypeByName //***************************************************************************** // Find the ManifestResource given the name. //***************************************************************************** __checkReturn STDMETHODIMP MDInternalRO::FindManifestResourceByName( // S_OK or error LPCSTR szName, // [IN] Name of the resource. mdManifestResource *pmmr) // [OUT] Put ManifestResource token here. { _ASSERTE(szName && pmmr); HRESULT hr; ManifestResourceRec *pRecord; ULONG cRecords; // Count of records. LPCUTF8 szNameTmp = 0; // Name obtained from the database. ULONG i; cRecords = m_LiteWeightStgdb.m_MiniMd.getCountManifestResources(); // Search for the ExportedType. for (i = 1; i <= cRecords; i++) { IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetManifestResourceRecord(i, &pRecord)); IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfManifestResource(pRecord, &szNameTmp)); if (! strcmp(szName, szNameTmp)) { *pmmr = TokenFromRid(i, mdtManifestResource); return S_OK; } } return CLDB_E_RECORD_NOTFOUND; } // MDInternalRO::FindManifestResourceByName //***************************************************************************** // Get the Assembly token from the given scope. //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetAssemblyFromScope( // S_OK or error mdAssembly *ptkAssembly) // [OUT] Put token here. { _ASSERTE(ptkAssembly); if (m_LiteWeightStgdb.m_MiniMd.getCountAssemblys()) { *ptkAssembly = TokenFromRid(1, mdtAssembly); return S_OK; } else return CLDB_E_RECORD_NOTFOUND; } // MDInternalRO::GetAssemblyFromScope //******************************************************************************* // return properties regarding a TypeSpec //******************************************************************************* __checkReturn HRESULT MDInternalRO::GetTypeSpecFromToken( // S_OK or error. mdTypeSpec typespec, // [IN] Signature token. PCCOR_SIGNATURE *ppvSig, // [OUT] return pointer to token. ULONG *pcbSig) // [OUT] return size of signature. { HRESULT hr = NOERROR; _ASSERTE(TypeFromToken(typespec) == mdtTypeSpec); _ASSERTE(ppvSig && pcbSig); if (!IsValidToken(typespec)) { *ppvSig = NULL; *pcbSig = 0; return E_INVALIDARG; } TypeSpecRec *pRec; IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetTypeSpecRecord(RidFromToken(typespec), &pRec)); if (pRec == NULL) { *ppvSig = NULL; *pcbSig = 0; return CLDB_E_FILE_CORRUPT; } IfFailRet(m_LiteWeightStgdb.m_MiniMd.getSignatureOfTypeSpec(pRec, ppvSig, pcbSig)); return hr; } // MDInternalRO::GetTypeSpecFromToken //***************************************************************************** // This function gets the "built for" version of a metadata scope. // NOTE: if the scope has never been saved, it will not have a built-for // version, and an empty string will be returned. //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetVersionString( LPCSTR * pVer) // [OUT] Put version string here. { HRESULT hr = NOERROR; if (m_LiteWeightStgdb.m_pvMd != NULL) { // For convenience, get a pointer to the version string. // @todo: get from alternate locations when there is no STOREAGESIGNATURE. *pVer = reinterpret_cast(reinterpret_cast(m_LiteWeightStgdb.m_pvMd)->pVersion); } else { // No string. *pVer = NULL; } return hr; } // MDInternalRO::GetVersionString //***************************************************************************** // convert a text signature to com format //***************************************************************************** __checkReturn HRESULT MDInternalRO::ConvertTextSigToComSig(// Return hresult. BOOL fCreateTrIfNotFound, // create typeref if not found or not LPCSTR pSignature, // class file format signature CQuickBytes *pqbNewSig, // [OUT] place holder for COM+ signature ULONG *pcbCount) // [OUT] the result size of signature { return E_NOTIMPL; } // MDInternalRO::ConvertTextSigToComSig //***************************************************************************** // determine if a token is valid or not //***************************************************************************** BOOL MDInternalRO::IsValidToken( // True or False. mdToken tk) // [IN] Given token. { RID rid = RidFromToken(tk); if (rid == 0) { return FALSE; } switch (TypeFromToken(tk)) { case mdtModule: // can have only one module record return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountModules()); case mdtTypeRef: return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountTypeRefs()); case mdtTypeDef: return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountTypeDefs()); case mdtFieldDef: return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountFields()); case mdtMethodDef: return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountMethods()); case mdtParamDef: return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountParams()); case mdtInterfaceImpl: return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountInterfaceImpls()); case mdtMemberRef: return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountMemberRefs()); case mdtCustomAttribute: return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountCustomAttributes()); case mdtPermission: return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountDeclSecuritys()); case mdtSignature: return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountStandAloneSigs()); case mdtEvent: return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountEvents()); case mdtProperty: return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountPropertys()); case mdtModuleRef: return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountModuleRefs()); case mdtTypeSpec: return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountTypeSpecs()); case mdtAssembly: return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountAssemblys()); case mdtAssemblyRef: return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountAssemblyRefs()); case mdtFile: return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountFiles()); case mdtExportedType: return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountExportedTypes()); case mdtManifestResource: return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountManifestResources()); case mdtMethodSpec: return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountMethodSpecs()); case mdtString: // need to check the user string heap return m_LiteWeightStgdb.m_MiniMd.m_UserStringHeap.IsValidIndex(rid); default: /* Don't Assert here, this will break verifier tests. _ASSERTE(!"Unknown token kind!"); */ return FALSE; } } // MDInternalRO::IsValidToken mdModule MDInternalRO::GetModuleFromScope(void) { return TokenFromRid(1, mdtModule); } // MDInternalRO::GetModuleFromScope //***************************************************************************** // Fill a variant given a MDDefaultValue // This routine will create a bstr if the ELEMENT_TYPE of default value is STRING //***************************************************************************** __checkReturn HRESULT _FillVariant( MDDefaultValue *pMDDefaultValue, VARIANT *pvar) { HRESULT hr = NOERROR; _ASSERTE(pMDDefaultValue); switch (pMDDefaultValue->m_bType) { case ELEMENT_TYPE_BOOLEAN: V_VT(pvar) = VT_BOOL; V_BOOL(pvar) = pMDDefaultValue->m_bValue; break; case ELEMENT_TYPE_I1: V_VT(pvar) = VT_I1; V_I1(pvar) = pMDDefaultValue->m_cValue; break; case ELEMENT_TYPE_U1: V_VT(pvar) = VT_UI1; V_UI1(pvar) = pMDDefaultValue->m_byteValue; break; case ELEMENT_TYPE_I2: V_VT(pvar) = VT_I2; V_I2(pvar) = pMDDefaultValue->m_sValue; break; case ELEMENT_TYPE_U2: case ELEMENT_TYPE_CHAR: // char is stored as UI2 internally V_VT(pvar) = VT_UI2; V_UI2(pvar) = pMDDefaultValue->m_usValue; break; case ELEMENT_TYPE_I4: V_VT(pvar) = VT_I4; V_I4(pvar) = pMDDefaultValue->m_lValue; break; case ELEMENT_TYPE_U4: V_VT(pvar) = VT_UI4; V_UI4(pvar) = pMDDefaultValue->m_ulValue; break; case ELEMENT_TYPE_R4: V_VT(pvar) = VT_R4; V_R4(pvar) = pMDDefaultValue->m_fltValue; break; case ELEMENT_TYPE_R8: V_VT(pvar) = VT_R8; V_R8(pvar) = pMDDefaultValue->m_dblValue; break; case ELEMENT_TYPE_STRING: // allocated bstr here V_BSTR(pvar) = ::SysAllocStringLen(pMDDefaultValue->m_wzValue, pMDDefaultValue->m_cbSize / sizeof(WCHAR)); if (V_BSTR(pvar) == NULL) hr = E_OUTOFMEMORY; V_VT(pvar) = VT_BSTR; break; case ELEMENT_TYPE_CLASS: V_VT(pvar) = VT_UNKNOWN; V_UNKNOWN(pvar) = pMDDefaultValue->m_unkValue; break; case ELEMENT_TYPE_I8: V_VT(pvar) = VT_I8; V_CY(pvar).int64 = pMDDefaultValue->m_llValue; break; case ELEMENT_TYPE_U8: V_VT(pvar) = VT_UI8; V_CY(pvar).int64 = pMDDefaultValue->m_ullValue; break; case ELEMENT_TYPE_VOID: V_VT(pvar) = VT_EMPTY; break; default: _ASSERTE(!"bad constant value type!"); } return hr; } // _FillVariant //***************************************************************************** // Fill a variant given a MDDefaultValue // This routine will create a bstr if the ELEMENT_TYPE of default value is STRING //***************************************************************************** __checkReturn HRESULT _FillMDDefaultValue( BYTE bType, void const *pValue, ULONG cbValue, MDDefaultValue *pMDDefaultValue) { HRESULT hr = NOERROR; pMDDefaultValue->m_bType = bType; pMDDefaultValue->m_cbSize = cbValue; switch (bType) { case ELEMENT_TYPE_BOOLEAN: if (cbValue < 1) { IfFailGo(CLDB_E_FILE_CORRUPT); } pMDDefaultValue->m_bValue = *((BYTE *) pValue); break; case ELEMENT_TYPE_I1: if (cbValue < 1) { IfFailGo(CLDB_E_FILE_CORRUPT); } pMDDefaultValue->m_cValue = *((CHAR *) pValue); break; case ELEMENT_TYPE_U1: if (cbValue < 1) { IfFailGo(CLDB_E_FILE_CORRUPT); } pMDDefaultValue->m_byteValue = *((BYTE *) pValue); break; case ELEMENT_TYPE_I2: if (cbValue < 2) { IfFailGo(CLDB_E_FILE_CORRUPT); } pMDDefaultValue->m_sValue = GET_UNALIGNED_VAL16(pValue); break; case ELEMENT_TYPE_U2: case ELEMENT_TYPE_CHAR: if (cbValue < 2) { IfFailGo(CLDB_E_FILE_CORRUPT); } pMDDefaultValue->m_usValue = GET_UNALIGNED_VAL16(pValue); break; case ELEMENT_TYPE_I4: if (cbValue < 4) { IfFailGo(CLDB_E_FILE_CORRUPT); } pMDDefaultValue->m_lValue = GET_UNALIGNED_VAL32(pValue); break; case ELEMENT_TYPE_U4: if (cbValue < 4) { IfFailGo(CLDB_E_FILE_CORRUPT); } pMDDefaultValue->m_ulValue = GET_UNALIGNED_VAL32(pValue); break; case ELEMENT_TYPE_R4: { if (cbValue < 4) { IfFailGo(CLDB_E_FILE_CORRUPT); } __int32 Value = GET_UNALIGNED_VAL32(pValue); pMDDefaultValue->m_fltValue = (float &)Value; } break; case ELEMENT_TYPE_R8: { if (cbValue < 8) { IfFailGo(CLDB_E_FILE_CORRUPT); } __int64 Value = GET_UNALIGNED_VAL64(pValue); pMDDefaultValue->m_dblValue = (double &) Value; } break; case ELEMENT_TYPE_STRING: if (cbValue == 0) pValue = NULL; #if BIGENDIAN { // We need to allocate and swap the string if we're on a big endian pMDDefaultValue->m_wzValue = new WCHAR[(cbValue + 1) / sizeof (WCHAR)]; _ASSERTE(FALSE); // Nothing ever free's this newly allocated array. Inserting assert so that if we ever actually // use this code path, we'll fix it then. (Don't want to fix something I can't test.) IfNullGo(pMDDefaultValue->m_wzValue); memcpy(const_cast(pMDDefaultValue->m_wzValue), pValue, cbValue); _ASSERTE(cbValue % sizeof(WCHAR) == 0); SwapStringLength(const_cast(pMDDefaultValue->m_wzValue), cbValue / sizeof(WCHAR)); } #else pMDDefaultValue->m_wzValue = (LPWSTR) pValue; #endif break; case ELEMENT_TYPE_CLASS: // // There is only a 4-byte quantity in the MetaData, and it must always // be zero. So, we load an INT32 and zero-extend it to be pointer-sized. // if (cbValue < 4) { IfFailGo(CLDB_E_FILE_CORRUPT); } pMDDefaultValue->m_unkValue = (IUnknown *)(UINT_PTR)GET_UNALIGNED_VAL32(pValue); if (pMDDefaultValue->m_unkValue != NULL) { _ASSERTE(!"Non-NULL objectref's are not supported as default values!"); IfFailGo(CLDB_E_FILE_CORRUPT); } break; case ELEMENT_TYPE_I8: if (cbValue < 8) { IfFailGo(CLDB_E_FILE_CORRUPT); } pMDDefaultValue->m_llValue = GET_UNALIGNED_VAL64(pValue); break; case ELEMENT_TYPE_U8: if (cbValue < 8) { IfFailGo(CLDB_E_FILE_CORRUPT); } pMDDefaultValue->m_ullValue = GET_UNALIGNED_VAL64(pValue); break; case ELEMENT_TYPE_VOID: break; default: _ASSERTE(!"BAD TYPE!"); IfFailGo(CLDB_E_FILE_CORRUPT); break; } ErrExit: return hr; } // _FillMDDefaultValue //***************************************************************************** // Given a scope, return the table size and table ptr for a given index //***************************************************************************** __checkReturn HRESULT MDInternalRO::GetTableInfoWithIndex( // return size ULONG index, // [IN] pass in the index void **pTable, // [OUT] pointer to table at index void **pTableSize) // [OUT] size of table at index { _ASSERTE(!"NYI"); return E_NOTIMPL; } // MDInternalRO::GetTableInfoWithIndex //***************************************************************************** // Given a delta metadata byte stream, apply the changes to the current metadata // object returning the resulting metadata object in ppv //***************************************************************************** __checkReturn HRESULT MDInternalRO::ApplyEditAndContinue( void *pDeltaMD, // [IN] the delta metadata ULONG cbDeltaMD, // [IN] length of pData IMDInternalImport **ppv) // [OUT] the resulting metadata interface { _ASSERTE(pDeltaMD); _ASSERTE(ppv); HRESULT hr = E_FAIL; IMDInternalImportENC *pDeltaMDImport = NULL; IfFailGo(GetInternalWithRWFormat(pDeltaMD, cbDeltaMD, 0, IID_IMDInternalImportENC, (void**)&pDeltaMDImport)); *ppv = this; IfFailGo(MDApplyEditAndContinue(ppv, pDeltaMDImport)); ErrExit: if (pDeltaMDImport) pDeltaMDImport->Release(); return hr; } HRESULT MDInternalRO::GetRvaOffsetData( DWORD *pFirstMethodRvaOffset, // [OUT] Offset (from start of metadata) to the first RVA field in MethodDef table. DWORD *pMethodDefRecordSize, // [OUT] Size of each record in MethodDef table. DWORD *pMethodDefCount, // [OUT] Number of records in MethodDef table. DWORD *pFirstFieldRvaOffset, // [OUT] Offset (from start of metadata) to the first RVA field in FieldRVA table. DWORD *pFieldRvaRecordSize, // [OUT] Size of each record in FieldRVA table. DWORD *pFieldRvaCount) // [OUT] Number of records in FieldRVA table. { HRESULT hr = S_OK; DWORD methodDefCount = *pMethodDefCount = m_LiteWeightStgdb.m_MiniMd.getCountMethods(); if (methodDefCount == 0) *pFirstMethodRvaOffset = *pMethodDefRecordSize = 0; else { MethodRec *pMethodRec; IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetMethodRecord(1, &pMethodRec)); // RVA is the first column of the MethodDef table, so the address of MethodRec is also address of RVA column. if ((const BYTE *)m_LiteWeightStgdb.m_pvMd > (const BYTE *)pMethodRec) { Debug_ReportError("Stream header is not within MetaData block."); IfFailGo(CLDB_E_FILE_CORRUPT); } *pFirstMethodRvaOffset = (DWORD)((const BYTE *)pMethodRec - (const BYTE *)m_LiteWeightStgdb.m_pvMd); *pMethodDefRecordSize = m_LiteWeightStgdb.m_MiniMd._CBREC(Method); } { DWORD fieldRvaCount = *pFieldRvaCount = m_LiteWeightStgdb.m_MiniMd.getCountFieldRVAs(); if (fieldRvaCount == 0) *pFirstFieldRvaOffset = *pFieldRvaRecordSize = 0; else { // orig // FieldRVARec *pFieldRVARec = m_LiteWeightStgdb.m_MiniMd.getFieldRVA(1); FieldRVARec *pFieldRVARec; IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetFieldRVARecord(1, &pFieldRVARec)); //FieldRVARec *pFieldRVARec; //mdToken fakeTok = 1; //RidToToken(&fakeTok, mdtFieldDef); //GetFieldRVA(fakeTok, &pFieldRVARec); // RVA is the first column of the FieldRVA table, so the address of FieldRVARec is also address of RVA column. if ((const BYTE *)m_LiteWeightStgdb.m_pvMd > (const BYTE *)pFieldRVARec) { Debug_ReportError("Stream header is not within MetaData block."); IfFailGo(CLDB_E_FILE_CORRUPT); } *pFirstFieldRvaOffset = (DWORD)((const BYTE *)pFieldRVARec - (const BYTE *)m_LiteWeightStgdb.m_pvMd); *pFieldRvaRecordSize = m_LiteWeightStgdb.m_MiniMd._CBREC(FieldRVA); } } hr = S_OK; ErrExit: return hr; } #endif //FEATURE_METADATA_INTERNAL_APIS