Esempio n. 1
0
//*****************************************************************************
// 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