//***************************************************************************** // Enumerate Sym.TypeRef //***************************************************************************** STDMETHODIMP RegMeta::EnumTypeRefs( HCORENUM *phEnum, // Pointer to the enumerator. mdTypeRef rTypeRefs[], // Put TypeRefs here. ULONG cMax, // Max TypeRefs to put. ULONG *pcTypeRefs) // Put # put here. { HRESULT hr = S_OK; BEGIN_ENTRYPOINT_NOTHROW; HENUMInternal **ppmdEnum = reinterpret_cast<HENUMInternal **> (phEnum); ULONG cTotal; HENUMInternal *pEnum = *ppmdEnum; LOG((LOGMD, "RegMeta::EnumTypeRefs(0x%08x, 0x%08x, 0x%08x, 0x%08x)\n", phEnum, rTypeRefs, cMax, pcTypeRefs)); START_MD_PERF(); LOCKREAD(); if ( pEnum == 0 ) { // instantiating a new ENUM CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); cTotal = pMiniMd->getCountTypeRefs(); IfFailGo( HENUMInternal::CreateSimpleEnum( mdtTypeRef, 1, cTotal + 1, &pEnum) ); // set the output parameter *ppmdEnum = pEnum; } // fill the output token buffer hr = HENUMInternal::EnumWithCount(pEnum, cMax, rTypeRefs, pcTypeRefs); ErrExit: HENUMInternal::DestroyEnumIfEmpty(ppmdEnum); STOP_MD_PERF(EnumTypeRefs); END_ENTRYPOINT_NOTHROW; return hr; } // STDMETHODIMP RegMeta::EnumTypeRefs()
//***************************************************************************** // Get information about a CustomAttribute. //***************************************************************************** STDMETHODIMP RegMeta::GetCustomAttributeProps( mdCustomAttribute cv, // The attribute token mdToken *ptkObj, // [OUT, OPTIONAL] Put object token here. mdToken *ptkType, // [OUT, OPTIONAL] Put TypeDef/TypeRef token here. void const **ppBlob, // [OUT, OPTIONAL] Put pointer to data here. ULONG *pcbSize) // [OUT, OPTIONAL] Put size of data here. { HRESULT hr = S_OK; // A result. BEGIN_ENTRYPOINT_NOTHROW; CMiniMdRW *pMiniMd; START_MD_PERF(); LOCKREAD(); _ASSERTE(TypeFromToken(cv) == mdtCustomAttribute); pMiniMd = &(m_pStgdb->m_MiniMd); CustomAttributeRec *pCustomAttributeRec; // The custom value record. IfFailGo(pMiniMd->GetCustomAttributeRecord(RidFromToken(cv), &pCustomAttributeRec)); if (ptkObj) *ptkObj = pMiniMd->getParentOfCustomAttribute(pCustomAttributeRec); if (ptkType) *ptkType = pMiniMd->getTypeOfCustomAttribute(pCustomAttributeRec); if (ppBlob != NULL) { IfFailGo(pMiniMd->getValueOfCustomAttribute(pCustomAttributeRec, (const BYTE **)ppBlob, pcbSize)); } ErrExit: STOP_MD_PERF(GetCustomAttributeProps); END_ENTRYPOINT_NOTHROW; return hr; } // RegMeta::GetCustomAttributeProps
//***************************************************************************** // Apply a delta record to a table, generically. //***************************************************************************** __checkReturn HRESULT CMiniMdRW::ApplyTableDelta( CMiniMdRW &mdDelta, // Interface to MD with the ENC delta. ULONG ixTbl, // Table index to update. RID iRid, // RID of the changed item. int fc) // Function code of update. { HRESULT hr = S_OK; void *pRec; // Record in existing MetaData. void *pDeltaRec; // Record if Delta MetaData. RID newRid; // Rid of new record. // Get the delta record. IfFailGo(mdDelta.GetDeltaRecord(ixTbl, iRid, &pDeltaRec)); // Get the record from the base metadata. if (iRid > m_Schema.m_cRecs[ixTbl]) { // Added record. Each addition is the next one. _ASSERTE(iRid == m_Schema.m_cRecs[ixTbl] + 1); switch (ixTbl) { case TBL_TypeDef: IfFailGo(AddTypeDefRecord(reinterpret_cast<TypeDefRec **>(&pRec), &newRid)); break; case TBL_Method: IfFailGo(AddMethodRecord(reinterpret_cast<MethodRec **>(&pRec), &newRid)); break; case TBL_EventMap: IfFailGo(AddEventMapRecord(reinterpret_cast<EventMapRec **>(&pRec), &newRid)); break; case TBL_PropertyMap: IfFailGo(AddPropertyMapRecord(reinterpret_cast<PropertyMapRec **>(&pRec), &newRid)); break; default: IfFailGo(AddRecord(ixTbl, &pRec, &newRid)); break; } IfNullGo(pRec); _ASSERTE(iRid == newRid); } else { // Updated record. IfFailGo(getRow(ixTbl, iRid, &pRec)); } // Copy the record info. IfFailGo(ApplyRecordDelta(mdDelta, ixTbl, pDeltaRec, pRec)); ErrExit: return hr; } // CMiniMdRW::ApplyTableDelta
//***************************************************************************** // Given a MetaData with ENC changes, apply those changes to this MetaData. //***************************************************************************** __checkReturn HRESULT CMiniMdRW::ApplyHeapDeltas( CMiniMdRW &mdDelta) // Interface to MD with the ENC delta. { if (mdDelta.IsMinimalDelta()) { return ApplyHeapDeltasWithMinimalDelta(mdDelta); } else { return ApplyHeapDeltasWithFullDelta(mdDelta); } }// CMiniMdRW::ApplyHeapDeltas
//***************************************************************************** // Copy the data from one MiniMd to another. //***************************************************************************** __checkReturn HRESULT CMiniMdRW::ApplyRecordDelta( CMiniMdRW &mdDelta, // The delta MetaData. ULONG ixTbl, // The table with the data. void *pDelta, // The delta MetaData record. void *pRecord) // The record to update. { HRESULT hr = S_OK; ULONG mask = m_SuppressedDeltaColumns[ixTbl]; for (ULONG ixCol = 0; ixCol<m_TableDefs[ixTbl].m_cCols; ++ixCol, mask >>= 1) { // Skip certain pointer columns. if (mask & 0x01) continue; ULONG val = mdDelta.GetCol(ixTbl, ixCol, pDelta); IfFailRet(PutCol(ixTbl, ixCol, pRecord, val)); } return hr; } // CMiniMdRW::ApplyRecordDelta
//***************************************************************************** // Implementation of IMetaDataImport::ResolveTypeRef to resolve a typeref across scopes. // // Arguments: // tr - typeref within this scope to resolve // riid - interface on ppIScope to support // ppIScope - out-parameter to get metadata scope for typedef (*ptd) // ptd - out-parameter to get typedef that the ref resolves to. // // Notes: // TypeDefs define a type within a scope. TypeRefs refer to type-defs in other scopes // and allow you to import a type from another scope. This function attempts to determine // which type-def a type-ref points to. // // This resolve (type-ref, this cope) --> (type-def=*ptd, other scope=*ppIScope) // // However, this resolution requires knowing what modules have been loaded, which is not decided // until runtime via loader / fusion policy. Thus this interface can't possibly be correct since // it doesn't have that knowledge. Furthermore, when inspecting metadata from another process // (such as a debugger inspecting the debuggee's metadata), this API can be truly misleading. // // This API usage should be avoided. // //***************************************************************************** STDMETHODIMP RegMeta::ResolveTypeRef( mdTypeRef tr, REFIID riid, IUnknown ** ppIScope, mdTypeDef * ptd) { #ifdef FEATURE_METADATA_IN_VM HRESULT hr; BEGIN_ENTRYPOINT_NOTHROW; TypeRefRec * pTypeRefRec; WCHAR wzNameSpace[_MAX_PATH]; CMiniMdRW * pMiniMd = NULL; LOG((LOGMD, "{%08x} RegMeta::ResolveTypeRef(0x%08x, 0x%08x, 0x%08x, 0x%08x)\n", this, tr, riid, ppIScope, ptd)); START_MD_PERF(); LOCKREAD(); pMiniMd = &(m_pStgdb->m_MiniMd); _ASSERTE((ppIScope != NULL) && (ptd != NULL)); // Init the output values. *ppIScope = NULL; *ptd = 0; if (IsNilToken(tr)) { if (ptd != NULL) { *ptd = mdTypeDefNil; } if (ppIScope != NULL) { *ppIScope = NULL; } STOP_MD_PERF(ResolveTypeRef); hr = E_INVALIDARG; goto ErrExit; } if (TypeFromToken(tr) == mdtTypeDef) { // Shortcut when we receive a TypeDef token *ptd = tr; STOP_MD_PERF(ResolveTypeRef); hr = this->QueryInterface(riid, (void **)ppIScope); goto ErrExit; } // Get the class ref row. _ASSERTE(TypeFromToken(tr) == mdtTypeRef); IfFailGo(pMiniMd->GetTypeRefRecord(RidFromToken(tr), &pTypeRefRec)); IfFailGo(pMiniMd->getNamespaceOfTypeRef(pTypeRefRec, wzNameSpace, lengthof(wzNameSpace), NULL)); if (hr != NOERROR) { _ASSERTE(hr == CLDB_S_TRUNCATION); // Truncate the namespace string wzNameSpace[lengthof(wzNameSpace) - 1] = 0; } //*********************** // before we go off to CORPATH, check the loaded modules! //*********************** if (LOADEDMODULES::ResolveTypeRefWithLoadedModules( tr, this, pMiniMd, riid, ppIScope, ptd) == NOERROR) { // Done!! We found one match among the loaded modules. goto ErrExit; } IfFailGo(META_E_CANNOTRESOLVETYPEREF); ErrExit: STOP_MD_PERF(ResolveTypeRef); END_ENTRYPOINT_NOTHROW; return hr; #else // FEATURE_METADATA_IN_VM return E_NOTIMPL; #endif // FEATURE_METADATA_IN_VM } // RegMeta::ResolveTypeRef
//***************************************************************************** // Driver for the delta process. //***************************************************************************** __checkReturn HRESULT CMiniMdRW::ApplyDelta( CMiniMdRW &mdDelta) // Interface to MD with the ENC delta. { HRESULT hr = S_OK; ULONG iENC; // Loop control. ULONG iRid; // RID of some record. ULONG iNew; // RID of a new record. int i; // Loop control. ULONG ixTbl; // A table. #ifdef _DEBUG if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_MD_ApplyDeltaBreak)) { _ASSERTE(!"CMiniMDRW::ApplyDelta()"); } #endif // _DEBUG // Init the suppressed column table. We know this one isn't zero... if (m_SuppressedDeltaColumns[TBL_TypeDef] == 0) { m_SuppressedDeltaColumns[TBL_EventMap] = (1 << EventMapRec::COL_EventList); m_SuppressedDeltaColumns[TBL_PropertyMap] = (1 << PropertyMapRec::COL_PropertyList); m_SuppressedDeltaColumns[TBL_EventMap] = (1 << EventMapRec::COL_EventList); m_SuppressedDeltaColumns[TBL_Method] = (1 << MethodRec::COL_ParamList); m_SuppressedDeltaColumns[TBL_TypeDef] = (1 << TypeDefRec::COL_FieldList)|(1<<TypeDefRec::COL_MethodList); } // Verify the version of the MD. if (m_Schema.m_major != mdDelta.m_Schema.m_major || m_Schema.m_minor != mdDelta.m_Schema.m_minor) { _ASSERTE(!"Version of Delta MetaData is a incompatible with current MetaData."); //<TODO>@FUTURE: unique error in the future since we are not shipping ENC.</TODO> return E_INVALIDARG; } // verify MVIDs. ModuleRec *pModDelta; ModuleRec *pModBase; IfFailGo(mdDelta.GetModuleRecord(1, &pModDelta)); IfFailGo(GetModuleRecord(1, &pModBase)); GUID GuidDelta; GUID GuidBase; IfFailGo(mdDelta.getMvidOfModule(pModDelta, &GuidDelta)); IfFailGo(getMvidOfModule(pModBase, &GuidBase)); if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_MD_DeltaCheck) && (GuidDelta != GuidBase)) { _ASSERTE(!"Delta MetaData has different base than current MetaData."); return E_INVALIDARG; } #ifndef FEATURE_CORECLR // Verify that the delta is based on the base. IfFailGo(mdDelta.getEncBaseIdOfModule(pModDelta, &GuidDelta)); IfFailGo(getEncBaseIdOfModule(pModBase,&GuidBase)); if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_MD_DeltaCheck) && CLRConfig::GetConfigValue(CLRConfig::INTERNAL_MD_UseMinimalDeltas) && (GuidDelta != GuidBase)) { _ASSERTE(!"The Delta MetaData is based on a different generation than the current MetaData."); return E_INVALIDARG; } #endif //!FEATURE_CORECLR // Let the other md prepare for sparse records. IfFailGo(mdDelta.StartENCMap()); // Fix the heaps. IfFailGo(ApplyHeapDeltas(mdDelta)); // Truncate some tables in preparation to copy in new ENCLog data. for (i = 0; (ixTbl = m_TruncatedEncTables[i]) != (ULONG)-1; ++i) { m_Tables[ixTbl].Delete(); IfFailGo(m_Tables[ixTbl].InitializeEmpty_WithRecordCount( m_TableDefs[ixTbl].m_cbRec, mdDelta.m_Schema.m_cRecs[ixTbl] COMMA_INDEBUG_MD(TRUE))); // fIsReadWrite INDEBUG_MD(m_Tables[ixTbl].Debug_SetTableInfo(NULL, ixTbl)); m_Schema.m_cRecs[ixTbl] = 0; } // For each record in the ENC log... for (iENC = 1; iENC <= mdDelta.m_Schema.m_cRecs[TBL_ENCLog]; ++iENC) { // Get the record, and the updated token. ENCLogRec *pENC; IfFailGo(mdDelta.GetENCLogRecord(iENC, &pENC)); ENCLogRec *pENC2; IfFailGo(AddENCLogRecord(&pENC2, &iNew)); IfNullGo(pENC2); ENCLogRec *pENC3; _ASSERTE(iNew == iENC); ULONG func = pENC->GetFuncCode(); pENC2->SetFuncCode(pENC->GetFuncCode()); pENC2->SetToken(pENC->GetToken()); // What kind of record is this? if (IsRecId(pENC->GetToken())) { // Non-token table iRid = RidFromRecId(pENC->GetToken()); ixTbl = TblFromRecId(pENC->GetToken()); } else { // Token table. iRid = RidFromToken(pENC->GetToken()); ixTbl = GetTableForToken(pENC->GetToken()); } RID rid_Ignore; // Switch based on the function code. switch (func) { case eDeltaMethodCreate: // Next ENC record will define the new Method. MethodRec *pMethodRecord; IfFailGo(AddMethodRecord(&pMethodRecord, &rid_Ignore)); IfFailGo(AddMethodToTypeDef(iRid, m_Schema.m_cRecs[TBL_Method])); break; case eDeltaParamCreate: // Next ENC record will define the new Param. This record is // tricky because params will be re-ordered based on their sequence, // but the sequence isn't set until the NEXT record is applied. // So, for ParamCreate only, apply the param record delta before // adding the parent-child linkage. ParamRec *pParamRecord; IfFailGo(AddParamRecord(&pParamRecord, &rid_Ignore)); // Should have recorded a Param delta after the Param add. _ASSERTE(iENC<mdDelta.m_Schema.m_cRecs[TBL_ENCLog]); IfFailGo(mdDelta.GetENCLogRecord(iENC+1, &pENC3)); _ASSERTE(pENC3->GetFuncCode() == 0); _ASSERTE(GetTableForToken(pENC3->GetToken()) == TBL_Param); IfFailGo(ApplyTableDelta(mdDelta, TBL_Param, RidFromToken(pENC3->GetToken()), eDeltaFuncDefault)); // Now that Param record is OK, set up linkage. IfFailGo(AddParamToMethod(iRid, m_Schema.m_cRecs[TBL_Param])); break; case eDeltaFieldCreate: // Next ENC record will define the new Field. FieldRec *pFieldRecord; IfFailGo(AddFieldRecord(&pFieldRecord, &rid_Ignore)); IfFailGo(AddFieldToTypeDef(iRid, m_Schema.m_cRecs[TBL_Field])); break; case eDeltaPropertyCreate: // Next ENC record will define the new Property. PropertyRec *pPropertyRecord; IfFailGo(AddPropertyRecord(&pPropertyRecord, &rid_Ignore)); IfFailGo(AddPropertyToPropertyMap(iRid, m_Schema.m_cRecs[TBL_Property])); break; case eDeltaEventCreate: // Next ENC record will define the new Event. EventRec *pEventRecord; IfFailGo(AddEventRecord(&pEventRecord, &rid_Ignore)); IfFailGo(AddEventToEventMap(iRid, m_Schema.m_cRecs[TBL_Event])); break; case eDeltaFuncDefault: IfFailGo(ApplyTableDelta(mdDelta, ixTbl, iRid, func)); break; default: _ASSERTE(!"Unexpected function in ApplyDelta"); IfFailGo(E_UNEXPECTED); break; } } m_Schema.m_cRecs[TBL_ENCLog] = mdDelta.m_Schema.m_cRecs[TBL_ENCLog]; ErrExit: // Store the result for returning (IfFailRet will modify hr) HRESULT hrReturn = hr; IfFailRet(mdDelta.EndENCMap()); #ifndef FEATURE_CORECLR if (SUCCEEDED(hrReturn) && CLRConfig::GetConfigValue(CLRConfig::INTERNAL_MD_DeltaCheck) && CLRConfig::GetConfigValue(CLRConfig::INTERNAL_MD_UseMinimalDeltas)) { GUID GuidNewBase; // We'll use the delta's 'delta guid' for our new base guid IfFailRet(mdDelta.getEncIdOfModule(pModDelta, &GuidNewBase)); IfFailRet(PutGuid(TBL_Module, ModuleRec::COL_EncBaseId, pModBase, GuidNewBase)); } #endif //!FEATURE_CORECLR return hrReturn; } // CMiniMdRW::ApplyDelta
STDMETHODIMP RegMeta::EnumGenericParamConstraints( HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. mdGenericParam tkOwner, // [IN] GenericParam whose constraints are requested mdGenericParamConstraint rTokens[], // [OUT] Put GenericParamConstraints here. ULONG cMaxTokens, // [IN] Max GenericParamConstraints to put. ULONG *pcTokens) // [OUT] Put # of tokens here. { HRESULT hr = S_OK; BEGIN_ENTRYPOINT_NOTHROW; HENUMInternal **ppmdEnum = reinterpret_cast<HENUMInternal **> (phEnum); ULONG ridStart; ULONG ridEnd; HENUMInternal *pEnum; GenericParamConstraintRec *pRec; ULONG index; CMiniMdRW *pMiniMd = NULL; LOG((LOGMD, "RegMeta::EnumGenericParamConstraints(0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n", phEnum, tkOwner, rTokens, cMaxTokens, pcTokens)); START_MD_PERF(); LOCKREAD(); pMiniMd = &(m_pStgdb->m_MiniMd); if(TypeFromToken(tkOwner) != mdtGenericParam) IfFailGo(META_E_BAD_INPUT_PARAMETER); // See if this version of the metadata can do Generics if (!pMiniMd->SupportsGenerics()) { if (pcTokens) *pcTokens = 0; hr = S_FALSE; goto ErrExit; } if ( *ppmdEnum == 0 ) { // instantiating a new ENUM //<TODO> GENERICS: review this. Are we expecting a sorted table or not? </TODO> if ( pMiniMd->IsSorted( TBL_GenericParamConstraint ) ) { IfFailGo(pMiniMd->getGenericParamConstraintsForGenericParam(RidFromToken(tkOwner), &ridEnd, &ridStart)); IfFailGo( HENUMInternal::CreateSimpleEnum(mdtGenericParamConstraint, ridStart, ridEnd, &pEnum) ); } else { // table is not sorted so we have to create dynamic array // create the dynamic enumerator // ridStart = 1; ridEnd = pMiniMd->getCountGenericParamConstraints() + 1; IfFailGo( HENUMInternal::CreateDynamicArrayEnum(mdtGenericParamConstraint, &pEnum)); for (index = ridStart; index < ridEnd; index ++ ) { IfFailGo(pMiniMd->GetGenericParamConstraintRecord(index, &pRec)); if ( tkOwner == pMiniMd->getOwnerOfGenericParamConstraint(pRec)) { IfFailGo( HENUMInternal::AddElementToEnum(pEnum, TokenFromRid(index, mdtGenericParamConstraint))); } } } // set the output parameter *ppmdEnum = pEnum; } else { pEnum = *ppmdEnum; } // fill the output token buffer hr = HENUMInternal::EnumWithCount(pEnum, cMaxTokens, rTokens, pcTokens); ErrExit: HENUMInternal::DestroyEnumIfEmpty(ppmdEnum); STOP_MD_PERF(EnumGenericParamConstraints); END_ENTRYPOINT_NOTHROW; return hr; }
STDMETHODIMP RegMeta::EnumMethodSpecs( HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. mdToken tkOwner, // [IN] MethodDef or MemberRef whose MethodSpecs are requested mdMethodSpec rTokens[], // [OUT] Put MethodSpecs here. ULONG cMaxTokens, // [IN] Max tokens to put. ULONG *pcTokens) // [OUT] Put actual count here. { HRESULT hr = S_OK; BEGIN_ENTRYPOINT_NOTHROW; HENUMInternal **ppmdEnum = reinterpret_cast<HENUMInternal **> (phEnum); ULONG ridStart; ULONG ridEnd; HENUMInternal *pEnum; MethodSpecRec *pRec; ULONG index; CMiniMdRW *pMiniMd = NULL; LOG((LOGMD, "RegMeta::EnumMethodSpecs(0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n", phEnum, tkOwner, rTokens, cMaxTokens, pcTokens)); START_MD_PERF(); LOCKREAD(); pMiniMd = &(m_pStgdb->m_MiniMd); // See if this version of the metadata can do Generics if (!pMiniMd->SupportsGenerics()) { if (pcTokens) *pcTokens = 0; hr = S_FALSE; goto ErrExit; } _ASSERTE(RidFromToken(tkOwner)==0 || TypeFromToken(tkOwner) == mdtMethodDef || TypeFromToken(tkOwner) == mdtMemberRef); if ( *ppmdEnum == 0 ) { // instantiating a new ENUM if(RidFromToken(tkOwner)==0) // enumerate all MethodSpecs { ridStart = 1; ridEnd = pMiniMd->getCountMethodSpecs() + 1; IfFailGo( HENUMInternal::CreateSimpleEnum( mdtMethodSpec, ridStart, ridEnd, &pEnum) ); } else { //@todo GENERICS: review this. Are we expecting a sorted table or not? if ( pMiniMd->IsSorted( TBL_MethodSpec ) ) { if (TypeFromToken(tkOwner) == mdtMemberRef) { IfFailGo(pMiniMd->getMethodSpecsForMemberRef(RidFromToken(tkOwner), &ridEnd, &ridStart)); } else { IfFailGo(pMiniMd->getMethodSpecsForMethodDef(RidFromToken(tkOwner), &ridEnd, &ridStart)); } IfFailGo( HENUMInternal::CreateSimpleEnum(mdtMethodSpec, ridStart, ridEnd, &pEnum) ); } else { // table is not sorted so we have to create dynamic array // create the dynamic enumerator // ridStart = 1; ridEnd = pMiniMd->getCountMethodSpecs() + 1; IfFailGo( HENUMInternal::CreateDynamicArrayEnum(mdtMethodSpec, &pEnum) ); for (index = ridStart; index < ridEnd; index ++ ) { IfFailGo(pMiniMd->GetMethodSpecRecord(index, &pRec)); if ( tkOwner == pMiniMd->getMethodOfMethodSpec(pRec) ) { IfFailGo( HENUMInternal::AddElementToEnum(pEnum, TokenFromRid(index, mdtMethodSpec) ) ); } } } } // set the output parameter *ppmdEnum = pEnum; } else { pEnum = *ppmdEnum; } // fill the output token buffer hr = HENUMInternal::EnumWithCount(pEnum, cMaxTokens, rTokens, pcTokens); ErrExit: HENUMInternal::DestroyEnumIfEmpty(ppmdEnum); STOP_MD_PERF(EnumMethodSpecs); END_ENTRYPOINT_NOTHROW; return hr; } // STDMETHODIMP RegMeta::EnumMethodSpecs()
//***************************************************************************** // Enumerate Sym.InterfaceImpl where Coclass == td //***************************************************************************** STDMETHODIMP RegMeta::EnumInterfaceImpls( HCORENUM *phEnum, // Pointer to the enum. mdTypeDef td, // TypeDef to scope the enumeration. mdInterfaceImpl rImpls[], // Put InterfaceImpls here. ULONG cMax, // Max InterfaceImpls to put. ULONG *pcImpls) // Put # put here. { HRESULT hr = S_OK; BEGIN_ENTRYPOINT_NOTHROW; HENUMInternal **ppmdEnum = reinterpret_cast<HENUMInternal **> (phEnum); ULONG ridStart; ULONG ridEnd; HENUMInternal *pEnum; InterfaceImplRec *pRec; ULONG index; LOG((LOGMD, "RegMeta::EnumInterfaceImpls(0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n", phEnum, td, rImpls, cMax, pcImpls)); START_MD_PERF(); LOCKREAD(); _ASSERTE(TypeFromToken(td) == mdtTypeDef); if ( *ppmdEnum == 0 ) { // instantiating a new ENUM CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); if ( pMiniMd->IsSorted( TBL_InterfaceImpl ) ) { IfFailGo(pMiniMd->getInterfaceImplsForTypeDef(RidFromToken(td), &ridEnd, &ridStart)); IfFailGo( HENUMInternal::CreateSimpleEnum( mdtInterfaceImpl, ridStart, ridEnd, &pEnum) ); } else { // table is not sorted so we have to create dynmaic array // create the dynamic enumerator // ridStart = 1; ridEnd = pMiniMd->getCountInterfaceImpls() + 1; IfFailGo( HENUMInternal::CreateDynamicArrayEnum( mdtInterfaceImpl, &pEnum) ); for (index = ridStart; index < ridEnd; index ++ ) { IfFailGo(pMiniMd->GetInterfaceImplRecord(index, &pRec)); if ( td == pMiniMd->getClassOfInterfaceImpl(pRec) ) { IfFailGo( HENUMInternal::AddElementToEnum(pEnum, TokenFromRid(index, mdtInterfaceImpl) ) ); } } } // set the output parameter *ppmdEnum = pEnum; } else { pEnum = *ppmdEnum; } // fill the output token buffer hr = HENUMInternal::EnumWithCount(pEnum, cMax, rImpls, pcImpls); ErrExit: HENUMInternal::DestroyEnumIfEmpty(ppmdEnum); STOP_MD_PERF(EnumInterfaceImpls); END_ENTRYPOINT_NOTHROW; return hr; } // RegMeta::EnumInterfaceImpls
//***************************************************************************** // Enumerate Sym.TypeDef. //***************************************************************************** STDMETHODIMP RegMeta::EnumTypeDefs( HCORENUM *phEnum, // Pointer to the enumerator. mdTypeDef rTypeDefs[], // Put TypeDefs here. ULONG cMax, // Max TypeDefs to put. ULONG *pcTypeDefs) // Put # put here. { HRESULT hr = S_OK; BEGIN_ENTRYPOINT_NOTHROW; HENUMInternal **ppmdEnum = reinterpret_cast<HENUMInternal **> (phEnum); HENUMInternal *pEnum; LOG((LOGMD, "RegMeta::EnumTypeDefs(0x%08x, 0x%08x, 0x%08x, 0x%08x)\n", phEnum, rTypeDefs, cMax, pcTypeDefs)); START_MD_PERF(); LOCKREAD(); if ( *ppmdEnum == 0 ) { // instantiating a new ENUM CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); if (pMiniMd->HasDelete() && ((m_OptionValue.m_ImportOption & MDImportOptionAllTypeDefs) == 0)) { IfFailGo( HENUMInternal::CreateDynamicArrayEnum( mdtTypeDef, &pEnum) ); // add all Types to the dynamic array if name is not _Delete for (ULONG index = 2; index <= pMiniMd->getCountTypeDefs(); index ++ ) { TypeDefRec *pRec; IfFailGo(pMiniMd->GetTypeDefRecord(index, &pRec)); LPCSTR szTypeDefName; IfFailGo(pMiniMd->getNameOfTypeDef(pRec, &szTypeDefName)); if (IsDeletedName(szTypeDefName)) { continue; } IfFailGo( HENUMInternal::AddElementToEnum(pEnum, TokenFromRid(index, mdtTypeDef) ) ); } } else { // create the enumerator IfFailGo( HENUMInternal::CreateSimpleEnum( mdtTypeDef, 2, pMiniMd->getCountTypeDefs() + 1, &pEnum) ); } // set the output parameter *ppmdEnum = pEnum; } else { pEnum = *ppmdEnum; } // we can only fill the minimun of what caller asked for or what we have left hr = HENUMInternal::EnumWithCount(pEnum, cMax, rTypeDefs, pcTypeDefs); ErrExit: HENUMInternal::DestroyEnumIfEmpty(ppmdEnum); STOP_MD_PERF(EnumTypeDefs); END_ENTRYPOINT_NOTHROW; return hr; } // RegMeta::EnumTypeDefs
//***************************************************************************** // Enumerate the CustomAttributes for a given token. //***************************************************************************** STDMETHODIMP RegMeta::EnumCustomAttributes( HCORENUM *phEnum, // Pointer to the enum. mdToken tk, // Token to scope the enumeration. mdToken tkType, // Type to limit the enumeration. mdCustomAttribute rCustomAttributes[], // Put CustomAttributes here. ULONG cMax, // Max CustomAttributes to put. ULONG *pcCustomAttributes) // Put # tokens returned here. { HRESULT hr = S_OK; BEGIN_ENTRYPOINT_NOTHROW; HENUMInternal **ppmdEnum = reinterpret_cast<HENUMInternal **> (phEnum); ULONG ridStart; ULONG ridEnd; HENUMInternal *pEnum = *ppmdEnum; CustomAttributeRec *pRec; ULONG index; LOG((LOGMD, "RegMeta::EnumCustomAttributes(0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n", phEnum, tk, tkType, rCustomAttributes, cMax, pcCustomAttributes)); START_MD_PERF(); LOCKREAD(); if ( pEnum == 0 ) { // instantiating a new ENUM CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); CLookUpHash *pHashTable = pMiniMd->m_pLookUpHashs[TBL_CustomAttribute]; // Does caller want all custom Values? if (IsNilToken(tk)) { IfFailGo( HENUMInternal::CreateSimpleEnum(mdtCustomAttribute, 1, pMiniMd->getCountCustomAttributes()+1, &pEnum) ); } else { // Scope by some object. if ( pMiniMd->IsSorted( TBL_CustomAttribute ) ) { // Get CustomAttributes for the object. IfFailGo(pMiniMd->getCustomAttributeForToken(tk, &ridEnd, &ridStart)); if (IsNilToken(tkType)) { // Simple enumerator for object's entire list. IfFailGo( HENUMInternal::CreateSimpleEnum( mdtCustomAttribute, ridStart, ridEnd, &pEnum) ); } else { // Dynamic enumerator for subsetted list. IfFailGo( HENUMInternal::CreateDynamicArrayEnum( mdtCustomAttribute, &pEnum) ); for (index = ridStart; index < ridEnd; index ++ ) { IfFailGo(pMiniMd->GetCustomAttributeRecord(index, &pRec)); if (tkType == pMiniMd->getTypeOfCustomAttribute(pRec)) { IfFailGo( HENUMInternal::AddElementToEnum(pEnum, TokenFromRid(index, mdtCustomAttribute) ) ); } } } } else { if (pHashTable) { // table is not sorted but hash is built // We want to create dynmaic array to hold the dynamic enumerator. TOKENHASHENTRY *p; ULONG iHash; int pos; mdToken tkParentTmp; mdToken tkTypeTmp; // Hash the data. iHash = pMiniMd->HashCustomAttribute(tk); IfFailGo( HENUMInternal::CreateDynamicArrayEnum( mdtCustomAttribute, &pEnum) ); // Go through every entry in the hash chain looking for ours. for (p = pHashTable->FindFirst(iHash, pos); p; p = pHashTable->FindNext(pos)) { CustomAttributeRec *pCustomAttribute; IfFailGo(pMiniMd->GetCustomAttributeRecord(RidFromToken(p->tok), &pCustomAttribute)); tkParentTmp = pMiniMd->getParentOfCustomAttribute(pCustomAttribute); tkTypeTmp = pMiniMd->getTypeOfCustomAttribute(pCustomAttribute); if (tkParentTmp == tk) { if (IsNilToken(tkType) || tkType == tkTypeTmp) { // compare the blob value IfFailGo( HENUMInternal::AddElementToEnum(pEnum, TokenFromRid(p->tok, mdtCustomAttribute )) ); } } } } else { // table is not sorted and hash is not built so we have to create dynmaic array // create the dynamic enumerator and loop through CA table linearly // ridStart = 1; ridEnd = pMiniMd->getCountCustomAttributes() + 1; IfFailGo( HENUMInternal::CreateDynamicArrayEnum( mdtCustomAttribute, &pEnum) ); for (index = ridStart; index < ridEnd; index ++ ) { IfFailGo(pMiniMd->GetCustomAttributeRecord(index, &pRec)); if ( tk == pMiniMd->getParentOfCustomAttribute(pRec) && (tkType == pMiniMd->getTypeOfCustomAttribute(pRec) || IsNilToken(tkType))) { IfFailGo( HENUMInternal::AddElementToEnum(pEnum, TokenFromRid(index, mdtCustomAttribute) ) ); } } } } } // set the output parameter *ppmdEnum = pEnum; } // fill the output token buffer hr = HENUMInternal::EnumWithCount(pEnum, cMax, rCustomAttributes, pcCustomAttributes); ErrExit: HENUMInternal::DestroyEnumIfEmpty(ppmdEnum); STOP_MD_PERF(EnumCustomAttributes); END_ENTRYPOINT_NOTHROW; return hr; } // STDMETHODIMP RegMeta::EnumCustomAttributes()