Exemplo n.º 1
0
//*****************************************************************************
// Get the value of a CustomAttribute, using only TypeName for lookup.
//*****************************************************************************
STDMETHODIMP RegMeta::GetCustomAttributeByName( // S_OK or error.
    mdToken     tkObj,                  // [IN] Object with Custom Attribute.
    LPCWSTR     wzName,                 // [IN] Name of desired Custom Attribute.
    const void  **ppData,               // [OUT] Put pointer to data here.
    ULONG       *pcbData)               // [OUT] Put size of data here.
{
    HRESULT     hr;                     // A result.

    BEGIN_ENTRYPOINT_NOTHROW;

    LPUTF8      szName;                 // Name in UFT8.
    int         iLen;                   // A length.
    CMiniMdRW   *pMiniMd = NULL;

    START_MD_PERF();
    LOCKREAD();
    pMiniMd = &(m_pStgdb->m_MiniMd);

    iLen = WszWideCharToMultiByte(CP_UTF8,0, wzName,-1, NULL,0, 0,0);
    szName = (LPUTF8)_alloca(iLen);
    VERIFY(WszWideCharToMultiByte(CP_UTF8,0, wzName,-1, szName,iLen, 0,0));

    hr = ImportHelper::GetCustomAttributeByName(pMiniMd, tkObj, szName, ppData, pcbData);
     
ErrExit:
    
    STOP_MD_PERF(GetCustomAttributeByName);
    END_ENTRYPOINT_NOTHROW;
    
    return hr;
} // STDMETHODIMP RegMeta::GetCustomAttributeByName()
Exemplo n.º 2
0
//
// returns the "built for" version of a metadata scope.
//
HRESULT RegMeta::GetVersionString(      // S_OK or error.
        LPCSTR      *pVer)              // [OUT] Put version string here.
{
    _ASSERTE(pVer != NULL);
    HRESULT hr;
    LOCKREAD();
#ifdef FEATURE_METADATA_CUSTOM_DATA_SOURCE
    if (m_pStgdb->m_pvMd != NULL)
    {
#endif
        *pVer = reinterpret_cast<const char*>(reinterpret_cast<const STORAGESIGNATURE*>(m_pStgdb->m_pvMd)->pVersion);
#ifdef FEATURE_METADATA_CUSTOM_DATA_SOURCE
    }
    else
    {   
        //This emptry string matches the fallback behavior we have in other places that query the version string.
        //From what I can tell the only caller to this method is the code that tests if we need to apply the WinMD adapter
        //and it checks if pVer == "WindowsRuntime". We don't support the debugger custom metadata source scenario with WinMDs (yet?)
        //so we intend for that check to return FALSE.
        *pVer = "";
    }
#endif
    hr = S_OK;
 ErrExit:
    return hr;
}
Exemplo n.º 3
0
//*****************************************************************************
// Remove a RegMeta pointer from the loaded module list
//*****************************************************************************
HRESULT LOADEDMODULES::ResolveTypeRefWithLoadedModules(
	mdTypeRef   tr,			            // [IN] TypeRef to be resolved.
	IMetaModelCommon *pCommon,  		// [IN] scope in which the typeref is defined.
	REFIID		riid,					// [IN] iid for the return interface
	IUnknown	**ppIScope,				// [OUT] return interface
	mdTypeDef	*ptd)					// [OUT] typedef corresponding the typeref
{
	HRESULT		hr = NOERROR;
	RegMeta		*pRegMeta;
    CQuickArray<mdTypeRef> cqaNesters;
    CQuickArray<LPCUTF8> cqaNesterNamespaces;
    CQuickArray<LPCUTF8> cqaNesterNames;
	int			count;
	int			index;

	if (g_LoadedModules == NULL)
	{
		// No loaded module!
		_ASSERTE(!"Bad state!");
		return E_FAIL;
	}

    LOCKREAD();
    
    // Get the Nesting hierarchy.
    IfFailGo(ImportHelper::GetNesterHierarchy(pCommon, tr, cqaNesters,
                                cqaNesterNamespaces, cqaNesterNames));

    count = g_LoadedModules->Count();
	for (index = 0; index < count; index++)
	{
		pRegMeta = (*g_LoadedModules)[index];

        hr = ImportHelper::FindNestedTypeDef(
                                pRegMeta->GetMiniMd(),
                                cqaNesterNamespaces,
                                cqaNesterNames,
                                mdTokenNil,
                                ptd);
		if (SUCCEEDED(hr))
		{
            // found a loaded module containing the TypeDef.
            hr = pRegMeta->QueryInterface(riid, (void **)ppIScope);			
            break;
        }
        else if (hr != CLDB_E_RECORD_NOTFOUND)
            IfFailGo(hr);
	}
	if (FAILED(hr))
	{
		// cannot find the match!
		hr = E_FAIL;
	}
ErrExit:
	return hr;
}	// LOADEDMODULES::ResolveTypeRefWithLoadedModules
Exemplo n.º 4
0
//*****************************************************************************
// 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()
Exemplo n.º 5
0
//*****************************************************************************
// Given a namespace and a class name, return the typedef
//*****************************************************************************
STDMETHODIMP RegMeta::FindTypeDefByName(// S_OK or error.
    LPCWSTR     wzTypeDef,              // [IN] Name of the Type.
    mdToken     tkEnclosingClass,       // [IN] Enclosing class.
    mdTypeDef   *ptd)                   // [OUT] Put the TypeDef token here.
{
    HRESULT     hr = S_OK;
    BEGIN_ENTRYPOINT_NOTHROW

    LOG((LOGMD, "{%08x} RegMeta::FindTypeDefByName(%S, 0x%08x, 0x%08x)\n", 
            this, MDSTR(wzTypeDef), tkEnclosingClass, ptd));
    START_MD_PERF();
    LOCKREAD();


    if (wzTypeDef == NULL)
        IfFailGo(E_INVALIDARG);
    PREFIX_ASSUME(wzTypeDef != NULL);
    LPSTR       szTypeDef;
    UTF8STR(wzTypeDef, szTypeDef);
    LPCSTR      szNamespace;
    LPCSTR      szName;

    _ASSERTE(ptd);
    _ASSERTE(TypeFromToken(tkEnclosingClass) == mdtTypeDef ||
             TypeFromToken(tkEnclosingClass) == mdtTypeRef ||
             IsNilToken(tkEnclosingClass));

    // initialize output parameter
    *ptd = mdTypeDefNil;

    ns::SplitInline(szTypeDef, szNamespace, szName);
    hr = ImportHelper::FindTypeDefByName(&(m_pStgdb->m_MiniMd), 
                                        szNamespace, 
                                        szName, 
                                        tkEnclosingClass, 
                                        ptd);
ErrExit:
    
    STOP_MD_PERF(FindTypeDefByName);
    END_ENTRYPOINT_NOTHROW;
    
    return hr;
} // STDMETHODIMP RegMeta::FindTypeDefByName()
Exemplo n.º 6
0
//*****************************************************************************
// 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
Exemplo n.º 7
0
//*****************************************************************************
// Gets a cached Internal importer, if available.
// 
// Arguments:
//     fWithLock - if true, takes a reader lock. 
//     If false, assumes caller is handling the synchronization.
//
// Returns:
//     A cached Internal importer, which gets addreffed. Caller must release!
//     If no importer is set, returns NULL
//
// Notes:
//     This function also does not trigger the creation of Internal interface.
//     Set the cached importer via code:RegMeta.SetCachedInternalInterface
// 
// Implements internal API code:IMetaDataHelper::GetCachedInternalInterface.
//*****************************************************************************
IUnknown* RegMeta::GetCachedInternalInterface(BOOL fWithLock) 
{
    IUnknown        *pRet = NULL;
    HRESULT hr = S_OK;
    
    if (fWithLock)
    {
        LOCKREAD();
        
        pRet = m_pInternalImport;
    }
    else
    {
        pRet = m_pInternalImport;
    }
    if (pRet) pRet->AddRef();

ErrExit:

    return pRet;
} //RegMeta::GetCachedInternalInterface
Exemplo n.º 8
0
//*****************************************************************************
// Search the cached RegMetas for a given scope.
//*****************************************************************************
BOOL LOADEDMODULES::IsEntryInList(
    RegMeta * pRegMeta)
{
    HRESULT hr = S_OK;
    
    IfFailGo(InitializeStatics());
    
    {
        LOCKREAD();
    
        // Loop through each loaded modules
        int count = s_pLoadedModules->Count();
        for (int index = 0; index < count; index++)
        {
            if ((*s_pLoadedModules)[index] == pRegMeta)
            {
                return TRUE;
            }
        }
    }

ErrExit:
    return FALSE;
} // LOADEDMODULES::IsEntryInList
Exemplo n.º 9
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
Exemplo n.º 10
0
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;
}
Exemplo n.º 11
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()
Exemplo n.º 12
0
//*****************************************************************************
// 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
Exemplo n.º 13
0
//*****************************************************************************
// 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
Exemplo n.º 14
0
//*****************************************************************************
// Remove a RegMeta pointer from the loaded module list
//*****************************************************************************
// static
HRESULT 
LOADEDMODULES::ResolveTypeRefWithLoadedModules(
    mdTypeRef          tkTypeRef,       // [IN] TypeRef to be resolved.
    RegMeta *          pTypeRefRegMeta, // [IN] Scope in which the TypeRef is defined.
    IMetaModelCommon * pTypeRefScope,   // [IN] Scope in which the TypeRef is defined.
    REFIID             riid,            // [IN] iid for the return interface.
    IUnknown **        ppIScope,        // [OUT] Return interface.
    mdTypeDef *        ptd)             // [OUT] TypeDef corresponding the TypeRef.
{
    HRESULT   hr = NOERROR;
    RegMeta * pRegMeta;
    CQuickArray<mdTypeRef> cqaNesters;
    CQuickArray<LPCUTF8>   cqaNesterNamespaces;
    CQuickArray<LPCUTF8>   cqaNesterNames;
    
    IfFailGo(InitializeStatics());
    
    {
        LOCKREAD();
    
        // Get the Nesting hierarchy.
        IfFailGo(ImportHelper::GetNesterHierarchy(
            pTypeRefScope, 
            tkTypeRef, 
            cqaNesters, 
            cqaNesterNamespaces, 
            cqaNesterNames));

        int count = s_pLoadedModules->Count();
        for (int index = 0; index < count; index++)
        {
            pRegMeta = (*s_pLoadedModules)[index];
        
            {
                // Do not lock the TypeRef RegMeta (again), as it is already locked for read by the caller.
                // The code:UTSemReadWrite will block ReadLock even for thread holding already the read lock if 
                // some other thread is waiting for WriteLock on the same lock. That would cause dead-lock if we 
                // try to lock for read again here.
                CMDSemReadWrite cSemRegMeta((pRegMeta == pTypeRefRegMeta) ? NULL : pRegMeta->GetReaderWriterLock());
                IfFailGo(cSemRegMeta.LockRead());
            
                hr = ImportHelper::FindNestedTypeDef(
                    pRegMeta->GetMiniMd(), 
                    cqaNesterNamespaces, 
                    cqaNesterNames, 
                    mdTokenNil, 
                    ptd);
            }
            if (hr == CLDB_E_RECORD_NOTFOUND)
            {   // Process next MetaData module
                continue;
            }
            IfFailGo(hr);
        
            // Found a loaded module containing the TypeDef.
            IfFailGo(pRegMeta->QueryInterface(riid, (void **)ppIScope));
            break;
        }
    }
    if (FAILED(hr))
    {
        // cannot find the match!
        hr = E_FAIL;
    }
ErrExit:
    return hr;
}    // LOADEDMODULES::ResolveTypeRefWithLoadedModules
Exemplo n.º 15
0
//*****************************************************************************
// Search the cached RegMetas for a given scope.
//*****************************************************************************
HRESULT LOADEDMODULES::FindCachedReadOnlyEntry(
    LPCWSTR    szName,      // Name of the desired file.
    DWORD      dwOpenFlags, // Flags the new file is opened with.
    RegMeta ** ppMeta)      // Put found RegMeta here.
{
    RegMeta * pRegMeta = 0;
    BOOL      bWillBeCopyMemory;    // Will the opened file be copied to memory?
    DWORD     dwLowFileSize;        // Low bytes of this file's size
    DWORD     dwLowFileTime;        // Low butes of this file's last write time
    HRESULT   hr;
    ULONG     ixHash = 0;
    
    IfFailGo(InitializeStatics());
    
    {
        LOCKREAD();

        hr = S_FALSE; // We haven't found a match yet.

        // Avoid confusion.
        *ppMeta = NULL;
    
        bWillBeCopyMemory = IsOfCopyMemory(dwOpenFlags);

        // The cache is locked for read, so the list will not change.
    
        // Figure out the size and timestamp of this file
        WIN32_FILE_ATTRIBUTE_DATA faData;
        if (!WszGetFileAttributesEx(szName, GetFileExInfoStandard, &faData))
            return E_FAIL;
        dwLowFileSize = faData.nFileSizeLow;
        dwLowFileTime = faData.ftLastWriteTime.dwLowDateTime;

        // Check the hash first.
        ixHash = HashFileName(szName);
        if ((pRegMeta = m_HashedModules[ixHash]) != NULL)
        {
            _ASSERTE(pRegMeta->IsReadOnly());

            // Only match if the IsOfCopyMemory() bit is the same in both.  This is because
            //  when ofCopyMemory is set, the file is not locked on disk, and may become stale
            //  in memory.
            //
            // Also, only match if the date and size are the same
            if (pRegMeta->IsCopyMemory() == bWillBeCopyMemory &&
                pRegMeta->GetLowFileTimeOfDBFile() == dwLowFileTime &&
                pRegMeta->GetLowFileSizeOfDBFile() == dwLowFileSize)
            {
                // If the name matches...
                LPCWSTR pszName = pRegMeta->GetNameOfDBFile();
    #ifdef FEATURE_CASE_SENSITIVE_FILESYSTEM
                if (wcscmp(szName, pszName) == 0)
    #else
                if (SString::_wcsicmp(szName, pszName) == 0)
    #endif
                {
                    ULONG cRefs;
                
                    // Found it.  Add a reference, and return it.
                    *ppMeta = pRegMeta;
                    cRefs = pRegMeta->AddRef();
                
                    LOG((LF_METADATA, LL_INFO10, "Disp::OpenScope found cached RegMeta in hash: %#8x, crefs: %d\n", pRegMeta, cRefs));
                
                    return S_OK;
                }
            }
        }

        // Not found in hash; loop through each loaded modules
        int count = s_pLoadedModules->Count();
        for (int index = 0; index < count; index++)
        {
            pRegMeta = (*s_pLoadedModules)[index];

            // If the module is read-only, and the CopyMemory bit matches, and the date
            // and size are the same....
            if (pRegMeta->IsReadOnly() && 
                pRegMeta->IsCopyMemory() == bWillBeCopyMemory &&
                pRegMeta->GetLowFileTimeOfDBFile() == dwLowFileTime &&
                pRegMeta->GetLowFileSizeOfDBFile() == dwLowFileSize)
            {
                // If the name matches...
                LPCWSTR pszName = pRegMeta->GetNameOfDBFile();
    #ifdef FEATURE_CASE_SENSITIVE_FILESYSTEM
                if (wcscmp(szName, pszName) == 0)
    #else
                if (SString::_wcsicmp(szName, pszName) == 0)
    #endif
                {
                    ULONG cRefs;

                    // Found it.  Add a reference, and return it.
                    *ppMeta = pRegMeta;
                    cRefs = pRegMeta->AddRef();

                    // Update the hash.
                    m_HashedModules[ixHash] = pRegMeta;

                    LOG((LF_METADATA, LL_INFO10, "Disp::OpenScope found cached RegMeta by search: %#8x, crefs: %d\n", pRegMeta, cRefs));
                
                    return S_OK;
                }
            }
        }
    }

ErrExit:
    // Didn't find it.
    LOG((LF_METADATA, LL_INFO10, "Disp::OpenScope did not find cached RegMeta\n"));

    _ASSERTE(hr != S_OK);
    return hr;
} // LOADEDMODULES::FindCachedReadOnlyEntry
Exemplo n.º 16
0
//*****************************************************************************
// 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()