Esempio n. 1
0
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()