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()