Beispiel #1
0
//*******************************************************************************
// Set the specified attributes on the given File token.
//*******************************************************************************
STDMETHODIMP RegMeta::SetFileProps(           // S_OK or error.
    mdFile      file,                   // [IN] File token.
    const void  *pbHashValue,           // [IN] Hash Blob.
    ULONG       cbHashValue,            // [IN] Count of bytes in the Hash Blob.
    DWORD       dwFileFlags)            // [IN] Flags.
{
    HRESULT     hr = S_OK;

    BEGIN_ENTRYPOINT_NOTHROW;

    
    _ASSERTE(TypeFromToken(file) == mdtFile && RidFromToken(file));
   
    LOG((LOGMD, "RegMeta::SetFileProps(%#08x, %#08x, %#08x, %#08x)\n",
        file, pbHashValue, cbHashValue, dwFileFlags));
    START_MD_PERF();
    LOCKWRITE();
    
    IfFailGo(m_pStgdb->m_MiniMd.PreUpdate());
    
    IfFailGo( _SetFileProps(file, pbHashValue, cbHashValue, dwFileFlags) );

ErrExit:
    
    STOP_MD_PERF(SetFileProps);
    END_ENTRYPOINT_NOTHROW;
    
    return hr;
}   // RegMeta::SetFileProps
Beispiel #2
0
//*******************************************************************************
// Set the specified attributes on the given Assembly token.
//*******************************************************************************
STDMETHODIMP RegMeta::SetAssemblyProps(       // S_OK or error.
    mdAssembly  ma,                     // [IN] Assembly token.
    const void  *pbPublicKey,           // [IN] Public key of the assembly.
    ULONG       cbPublicKey,            // [IN] Count of bytes in the public key.
    ULONG       ulHashAlgId,            // [IN] Hash Algorithm.
    LPCWSTR     szName,                 // [IN] Name of the assembly.
    const ASSEMBLYMETADATA *pMetaData,  // [IN] Assembly MetaData.
    DWORD       dwAssemblyFlags)        // [IN] Flags.
{
    HRESULT hr = S_OK;
    
    BEGIN_ENTRYPOINT_NOTHROW;
    
    _ASSERTE(TypeFromToken(ma) == mdtAssembly && RidFromToken(ma));
    
    LOG((LOGMD, "RegMeta::SetAssemblyProps(%#08x, %#08x, %#08x, %#08x %S, %#08x, %#08x)\n",
        ma, pbPublicKey, cbPublicKey, ulHashAlgId, MDSTR(szName), pMetaData, dwAssemblyFlags));
    
    START_MD_PERF();
    LOCKWRITE();
    
    IfFailGo(m_pStgdb->m_MiniMd.PreUpdate());
    
    IfFailGo(_SetAssemblyProps(ma, pbPublicKey, cbPublicKey, ulHashAlgId, szName, pMetaData, dwAssemblyFlags));
    
ErrExit:
    STOP_MD_PERF(SetAssemblyProps);
    END_ENTRYPOINT_NOTHROW;
    
    return hr;
} // STDMETHODIMP SetAssemblyProps()
Beispiel #3
0
//*******************************************************************************
// Set the specified attributes on the given ManifestResource token.
//*******************************************************************************
STDMETHODIMP RegMeta::SetManifestResourceProps(// S_OK or error.
    mdManifestResource  mr,             // [IN] ManifestResource token.
    mdToken     tkImplementation,       // [IN] mdFile or mdAssemblyRef that provides the resource.
    DWORD       dwOffset,               // [IN] Offset to the beginning of the resource within the file.
    DWORD       dwResourceFlags)        // [IN] Flags.
{
    HRESULT     hr = S_OK;

    BEGIN_ENTRYPOINT_NOTHROW;

    LOG((LOGMD, "RegMeta::SetManifestResourceProps(%#08x, %#08x, %#08x, %#08x)\n",
        mr, tkImplementation, dwOffset, 
        dwResourceFlags));
   
    _ASSERTE(TypeFromToken(tkImplementation) == mdtFile ||
              TypeFromToken(tkImplementation) == mdtAssemblyRef ||
              tkImplementation == mdTokenNil);

    START_MD_PERF();
    LOCKWRITE();
    
    IfFailGo( _SetManifestResourceProps( mr, tkImplementation, dwOffset, dwResourceFlags) );

ErrExit:
    
    STOP_MD_PERF(SetManifestResourceProps);
    END_ENTRYPOINT_NOTHROW;
    
    return hr;
} // STDMETHODIMP RegMeta::SetManifestResourceProps()
//*****************************************************************************
// Query the count of items represented by an enumerator.
//*****************************************************************************
HRESULT CountEnum(
    HCORENUM        hEnum,              // The enumerator.
    ULONG           *pulCount)          // Put the count here.
{
    HENUMInternal   *pmdEnum = reinterpret_cast<HENUMInternal *> (hEnum);
    HRESULT         hr = S_OK;

    // No need to lock this function.

    LOG((LOGMD, "RegMeta::CountEnum(0x%08x, 0x%08x)\n", hEnum, pulCount));
    START_MD_PERF();

    _ASSERTE( pulCount );

    if (pmdEnum == NULL)
    {
        *pulCount = 0;
        goto ErrExit;
    }

    if (pmdEnum->m_tkKind == (TBL_MethodImpl << 24))
    {
        // Number of tokens must always be a multiple of 2.
        _ASSERTE(! (pmdEnum->m_ulCount % 2) );
        // There are two entries in the Enumerator for each MethodImpl.
        *pulCount = pmdEnum->m_ulCount / 2;
    }
    else
        *pulCount = pmdEnum->m_ulCount;
ErrExit:
    STOP_MD_PERF(CountEnum);
    return hr;
} // ::CountEnum
//*****************************************************************************
// Reset an enumerator to any position within the enumerator.
//*****************************************************************************
STDMETHODIMP RegMeta::ResetEnum(
    HCORENUM        hEnum,              // The enumerator.
    ULONG           ulPos)              // Seek position.
{
    HRESULT         hr = S_OK;

    BEGIN_ENTRYPOINT_NOTHROW;

    HENUMInternal   *pmdEnum = reinterpret_cast<HENUMInternal *> (hEnum);

    // No need to lock this function.

    LOG((LOGMD, "RegMeta::ResetEnum(0x%08x, 0x%08x)\n", hEnum, ulPos));
    START_MD_PERF();

    if (pmdEnum == NULL)
        goto ErrExit;

    pmdEnum->u.m_ulCur = pmdEnum->u.m_ulStart + ulPos;

ErrExit:
    STOP_MD_PERF(ResetEnum);
    END_ENTRYPOINT_NOTHROW;
    return hr;
} // RegMeta::ResetEnum
Beispiel #6
0
//*******************************************************************************
// Set the specified attributes on the given ExportedType token.
//*******************************************************************************
STDMETHODIMP RegMeta::SetExportedTypeProps(        // S_OK or error.
    mdExportedType   ct,                     // [IN] ExportedType token.
    mdToken     tkImplementation,       // [IN] mdFile or mdAssemblyRef that provides the ExportedType.
    mdTypeDef   tkTypeDef,              // [IN] TypeDef token within the file.
    DWORD       dwExportedTypeFlags)         // [IN] Flags.
{
    HRESULT     hr = S_OK;

    BEGIN_ENTRYPOINT_NOTHROW;


    LOG((LOGMD, "RegMeta::SetExportedTypeProps(%#08x, %#08x, %#08x, %#08x)\n",
        ct, tkImplementation, tkTypeDef, dwExportedTypeFlags));

    START_MD_PERF();
    LOCKWRITE();
    
    IfFailGo( _SetExportedTypeProps( ct, tkImplementation, tkTypeDef, dwExportedTypeFlags) );

ErrExit:
    
    STOP_MD_PERF(SetExportedTypeProps);
    END_ENTRYPOINT_NOTHROW;
    
    return hr;
}   // RegMeta::SetExportedTypeProps
Beispiel #7
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()
//*****************************************************************************
// 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()
//*****************************************************************************
// 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()
Beispiel #10
0
//*******************************************************************************
// Set the specified attributes on the given AssemblyRef token.
//*******************************************************************************
STDMETHODIMP RegMeta::SetAssemblyRefProps(    // S_OK or error.
    mdAssemblyRef ar,                   // [IN] AssemblyRefToken.
    const void  *pbPublicKeyOrToken,    // [IN] Public key or token of the assembly.
    ULONG       cbPublicKeyOrToken,     // [IN] Count of bytes in the public key or token.
    LPCWSTR     szName,                 // [IN] Name of the assembly being referenced.
    const ASSEMBLYMETADATA *pMetaData,  // [IN] Assembly MetaData.
    const void  *pbHashValue,           // [IN] Hash Blob.
    ULONG       cbHashValue,            // [IN] Count of bytes in the Hash Blob.
    DWORD       dwAssemblyRefFlags)     // [IN] Flags.
{
    HRESULT hr = S_OK;
    
    BEGIN_ENTRYPOINT_NOTHROW;
    
    _ASSERTE(TypeFromToken(ar) == mdtAssemblyRef && RidFromToken(ar));
    
    LOG((LOGMD, "RegMeta::SetAssemblyRefProps(0x%08x, 0x%08x, 0x%08x, %S, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
        ar, pbPublicKeyOrToken, cbPublicKeyOrToken, MDSTR(szName), pMetaData, pbHashValue, cbHashValue,
        dwAssemblyRefFlags));
    
    START_MD_PERF();
    LOCKWRITE();
    
    IfFailGo(m_pStgdb->m_MiniMd.PreUpdate());
    
    IfFailGo(_SetAssemblyRefProps(
        ar,
        pbPublicKeyOrToken,
        cbPublicKeyOrToken,
        szName,
        pMetaData,
        pbHashValue,
        cbHashValue,
        dwAssemblyRefFlags));
    
ErrExit:
    STOP_MD_PERF(SetAssemblyRefProps);
    END_ENTRYPOINT_NOTHROW;
    
    return hr;
}   // RegMeta::SetAssemblyRefProps
Beispiel #11
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
Beispiel #12
0
//*******************************************************************************
// Define a ExportedType and set the attributes.
//*******************************************************************************
STDMETHODIMP RegMeta::DefineExportedType(     // S_OK or error.
    LPCWSTR     szName,                 // [IN] Name of the Com Type.
    mdToken     tkImplementation,       // [IN] mdFile or mdAssemblyRef that provides the ExportedType.
    mdTypeDef   tkTypeDef,              // [IN] TypeDef token within the file.
    DWORD       dwExportedTypeFlags,    // [IN] Flags.
    mdExportedType   *pmct)             // [OUT] Returned ExportedType token.
{
    HRESULT hr = S_OK;
    
    BEGIN_ENTRYPOINT_NOTHROW;
    
    ExportedTypeRec  *pRecord = NULL;
    ULONG       iRecord;
    LPSTR       szNameUTF8;
    LPCSTR      szTypeNameUTF8;
    LPCSTR      szTypeNamespaceUTF8;
    
    LOG((LOGMD, "RegMeta::DefineExportedType(%S, %#08x, %08x, %#08x, %#08x)\n",
        MDSTR(szName), tkImplementation, tkTypeDef, 
         dwExportedTypeFlags, pmct));
    
    START_MD_PERF();
    LOCKWRITE();
    
    // Validate name for prefix.
    if (szName == NULL)
        IfFailGo(E_INVALIDARG);
    
    IfFailGo(m_pStgdb->m_MiniMd.PreUpdate());
    
    //SLASHES2DOTS_NAMESPACE_BUFFER_UNICODE(szName, szName);
    
    UTF8STR(szName, szNameUTF8);
    // Split the name into name/namespace pair.
    ns::SplitInline(szNameUTF8, szTypeNamespaceUTF8, szTypeNameUTF8);
    
    _ASSERTE(szName && dwExportedTypeFlags != ULONG_MAX && pmct);
    _ASSERTE(TypeFromToken(tkImplementation) == mdtFile ||
              TypeFromToken(tkImplementation) == mdtAssemblyRef ||
              TypeFromToken(tkImplementation) == mdtExportedType ||
              tkImplementation == mdTokenNil);
    
    if (CheckDups(MDDupExportedType))
    {
        hr = ImportHelper::FindExportedType(&m_pStgdb->m_MiniMd,
                                       szTypeNamespaceUTF8,
                                       szTypeNameUTF8,
                                       tkImplementation,
                                       pmct);
        if (SUCCEEDED(hr))
        {
            if (IsENCOn())
            {
                IfFailGo(m_pStgdb->m_MiniMd.GetExportedTypeRecord(RidFromToken(*pmct), &pRecord));
            }
            else
            {
                hr = META_S_DUPLICATE;
                goto ErrExit;
            }
        }
        else if (hr != CLDB_E_RECORD_NOTFOUND)
        {
            IfFailGo(hr);
        }
    }

    // Create a new record if needed.
    if (pRecord == NULL)
    {
        // Create a new record.
        IfFailGo(m_pStgdb->m_MiniMd.AddExportedTypeRecord(&pRecord, &iRecord));

        // Set the output parameter.
        *pmct = TokenFromRid(iRecord, mdtExportedType);

        // Set the TypeName and TypeNamespace.
        IfFailGo(m_pStgdb->m_MiniMd.PutString(TBL_ExportedType,
                ExportedTypeRec::COL_TypeName, pRecord, szTypeNameUTF8));
        if (szTypeNamespaceUTF8)
        {
            IfFailGo(m_pStgdb->m_MiniMd.PutString(TBL_ExportedType,
                    ExportedTypeRec::COL_TypeNamespace, pRecord, szTypeNamespaceUTF8));
        }
    }

    // Set rest of the attributes.
    IfFailGo(_SetExportedTypeProps(*pmct, tkImplementation, tkTypeDef,
                             dwExportedTypeFlags));
ErrExit:
    
    STOP_MD_PERF(DefineExportedType);
    END_ENTRYPOINT_NOTHROW;
    
    return hr;
}   // RegMeta::DefineExportedType
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
Beispiel #17
0
//*******************************************************************************
// Define an Assembly and set the attributes.
//*******************************************************************************
STDMETHODIMP RegMeta::DefineAssembly(         // S_OK or error.
    const void  *pbPublicKey,           // [IN] Public key of the assembly.
    ULONG       cbPublicKey,            // [IN] Count of bytes in the public key.
    ULONG       ulHashAlgId,            // [IN] Hash Algorithm.
    LPCWSTR     szName,                 // [IN] Name of the assembly.
    const ASSEMBLYMETADATA *pMetaData,  // [IN] Assembly MetaData.
    DWORD       dwAssemblyFlags,        // [IN] Flags.
    mdAssembly  *pma)                   // [OUT] Returned Assembly token.
{
    HRESULT     hr = S_OK;
    
    AssemblyRec *pRecord = NULL;        // The assembly record.
    ULONG        iRecord;               // RID of the assembly record.
    
    if (szName == NULL || pMetaData == NULL || pma == NULL)
        return E_INVALIDARG;
    
    BEGIN_ENTRYPOINT_NOTHROW;
    
    LOG((LOGMD, "RegMeta::DefineAssembly(0x%08x, 0x%08x, 0x%08x, %S, 0x%08x, 0x%08x, 0x%08x)\n",
        pbPublicKey, cbPublicKey, ulHashAlgId, MDSTR(szName), pMetaData, 
        dwAssemblyFlags, pma));
    
    START_MD_PERF();
    LOCKWRITE();
    
    _ASSERTE(szName && pMetaData && pma);
    
    IfFailGo(m_pStgdb->m_MiniMd.PreUpdate());
    
    // Assembly defs always contain a full public key (assuming they're strong
    // named) rather than the tokenized version. Force the flag on to indicate
    // this, and this way blindly copying public key & flags from a def to a ref
    // will work (though the ref will be bulkier than strictly necessary).
    if (cbPublicKey != 0)
        dwAssemblyFlags |= afPublicKey;
    
    if (CheckDups(MDDupAssembly))
    {   // Should be no more than one -- just check count of records.
        if (m_pStgdb->m_MiniMd.getCountAssemblys() > 0)
        {   // S/b only one, so we know the rid.
            iRecord = 1;
            // If ENC, let them update the existing record.
            if (IsENCOn())
                IfFailGo(m_pStgdb->m_MiniMd.GetAssemblyRecord(iRecord, &pRecord));
            else
            {   // Not ENC, so it is a duplicate.
                *pma = TokenFromRid(iRecord, mdtAssembly);
                hr = META_S_DUPLICATE;
                goto ErrExit;
            }
        }
    }
    else
    {   // Not ENC, not duplicate checking, so shouldn't already have one.
        _ASSERTE(m_pStgdb->m_MiniMd.getCountAssemblys() == 0);
    }

    // Create a new record, if needed.
    if (pRecord == NULL)
    {
        IfFailGo(m_pStgdb->m_MiniMd.AddAssemblyRecord(&pRecord, &iRecord));
    }

    // Set the output parameter.
    *pma = TokenFromRid(iRecord, mdtAssembly);

    IfFailGo(_SetAssemblyProps(*pma, pbPublicKey, cbPublicKey, ulHashAlgId, szName, pMetaData, dwAssemblyFlags));

ErrExit:

    STOP_MD_PERF(DefineAssembly);
    END_ENTRYPOINT_NOTHROW;
    
    return hr;
}   // RegMeta::DefineAssembly
Beispiel #18
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()
Beispiel #19
0
//*******************************************************************************
// Define a File and set the attributes.
//*******************************************************************************
STDMETHODIMP RegMeta::DefineFile(             // S_OK or error.
    LPCWSTR     szName,                 // [IN] Name of the file.
    const void  *pbHashValue,           // [IN] Hash Blob.
    ULONG       cbHashValue,            // [IN] Count of bytes in the Hash Blob.
    DWORD       dwFileFlags,            // [IN] Flags.
    mdFile      *pmf)                   // [OUT] Returned File token.
{
    HRESULT hr = S_OK;
    
    BEGIN_ENTRYPOINT_NOTHROW;
    
    FileRec     *pRecord = NULL;
    ULONG       iRecord;
    
    LOG((LOGMD, "RegMeta::DefineFile(%S, %#08x, %#08x, %#08x, %#08x)\n",
        MDSTR(szName), pbHashValue, cbHashValue, dwFileFlags, pmf));
    
    START_MD_PERF();
    LOCKWRITE();
    
    IfFailGo(m_pStgdb->m_MiniMd.PreUpdate());
    
    _ASSERTE(szName && pmf);
    
    if (CheckDups(MDDupFile))
    {
        LPUTF8 szUTF8Name;
        UTF8STR(szName, szUTF8Name);
        hr = ImportHelper::FindFile(&m_pStgdb->m_MiniMd, szUTF8Name, pmf);
        if (SUCCEEDED(hr))
        {
            if (IsENCOn())
            {
                IfFailGo(m_pStgdb->m_MiniMd.GetFileRecord(RidFromToken(*pmf), &pRecord));
            }
            else
            {
                hr = META_S_DUPLICATE;
                goto ErrExit;
            }
        }
        else if (hr != CLDB_E_RECORD_NOTFOUND)
        {
            IfFailGo(hr);
        }
    }
    
    // Create a new record if needed.
    if (pRecord == NULL)
    {
        // Create a new record.
        IfFailGo(m_pStgdb->m_MiniMd.AddFileRecord(&pRecord, &iRecord));

        // Set the output parameter.
        *pmf = TokenFromRid(iRecord, mdtFile);

        // Set the name.
        IfFailGo(m_pStgdb->m_MiniMd.PutStringW(TBL_File, FileRec::COL_Name, pRecord, szName));
    }

    // Set rest of the attributes.
    IfFailGo(_SetFileProps(*pmf, pbHashValue, cbHashValue, dwFileFlags));
ErrExit:
    
    STOP_MD_PERF(DefineFile);
    END_ENTRYPOINT_NOTHROW;
    
    return hr;
}   // RegMeta::DefineFile
Beispiel #20
0
//*******************************************************************************
// Define a Resource and set the attributes.
//*******************************************************************************
STDMETHODIMP RegMeta::DefineManifestResource( // S_OK or error.
    LPCWSTR     szName,                 // [IN] Name of the ManifestResource.
    mdToken     tkImplementation,       // [IN] mdFile or mdAssemblyRef that provides the resource.
    DWORD       dwOffset,               // [IN] Offset to the beginning of the resource within the file.
    DWORD       dwResourceFlags,        // [IN] Flags.
    mdManifestResource  *pmmr)          // [OUT] Returned ManifestResource token.
{
    HRESULT hr = S_OK;
    
    BEGIN_ENTRYPOINT_NOTHROW;
    
    ManifestResourceRec *pRecord = NULL;
    ULONG       iRecord;
    
    LOG((LOGMD, "RegMeta::DefineManifestResource(%S, %#08x, %#08x, %#08x, %#08x)\n",
        MDSTR(szName), tkImplementation, dwOffset, dwResourceFlags, pmmr));
    
    START_MD_PERF();
    LOCKWRITE();
    
    IfFailGo(m_pStgdb->m_MiniMd.PreUpdate());
    
    _ASSERTE(szName && dwResourceFlags != ULONG_MAX && pmmr);
    _ASSERTE(TypeFromToken(tkImplementation) == mdtFile ||
              TypeFromToken(tkImplementation) == mdtAssemblyRef ||
              tkImplementation == mdTokenNil);
    
    if (CheckDups(MDDupManifestResource))
    {
        LPUTF8 szUTF8Name;
        UTF8STR(szName, szUTF8Name);
        hr = ImportHelper::FindManifestResource(&m_pStgdb->m_MiniMd, szUTF8Name, pmmr);
        if (SUCCEEDED(hr))
        {
            if (IsENCOn())
            {
                IfFailGo(m_pStgdb->m_MiniMd.GetManifestResourceRecord(RidFromToken(*pmmr), &pRecord));
            }
            else
            {
                hr = META_S_DUPLICATE;
                goto ErrExit;
            }
        }
        else if (hr != CLDB_E_RECORD_NOTFOUND)
        {
            IfFailGo(hr);
        }
    }

    // Create a new record if needed.
    if (pRecord == NULL)
    {
        // Create a new record.
        IfFailGo(m_pStgdb->m_MiniMd.AddManifestResourceRecord(&pRecord, &iRecord));

        // Set the output parameter.
        *pmmr = TokenFromRid(iRecord, mdtManifestResource);

        // Set the name.
        IfFailGo(m_pStgdb->m_MiniMd.PutStringW(TBL_ManifestResource,
                                    ManifestResourceRec::COL_Name, pRecord, szName));
    }

    // Set the rest of the attributes.
    IfFailGo(_SetManifestResourceProps(*pmmr, tkImplementation, 
                                dwOffset, dwResourceFlags));

ErrExit:
    
    STOP_MD_PERF(DefineManifestResource);
    END_ENTRYPOINT_NOTHROW;
    
    return hr;
}   // RegMeta::DefineManifestResource
Beispiel #21
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
Beispiel #22
0
//*******************************************************************************
// Define an AssemblyRef and set the attributes.
//*******************************************************************************
STDMETHODIMP RegMeta::DefineAssemblyRef(      // S_OK or error.
    const void  *pbPublicKeyOrToken,    // [IN] Public key or token of the assembly.
    ULONG       cbPublicKeyOrToken,     // [IN] Count of bytes in the public key or token.
    LPCWSTR     szName,                 // [IN] Name of the assembly being referenced.
    const ASSEMBLYMETADATA *pMetaData,  // [IN] Assembly MetaData.
    const void  *pbHashValue,           // [IN] Hash Blob.
    ULONG       cbHashValue,            // [IN] Count of bytes in the Hash Blob.
    DWORD       dwAssemblyRefFlags,     // [IN] Flags.
    mdAssemblyRef *pmar)                // [OUT] Returned AssemblyRef token.
{
    HRESULT hr = S_OK;
    
    AssemblyRefRec *pRecord = NULL;
    ULONG           iRecord;
    
    if (szName == NULL || pmar == NULL || pMetaData == NULL)
        return E_INVALIDARG;
    
    BEGIN_ENTRYPOINT_NOTHROW;
    
    LOG((LOGMD, "RegMeta::DefineAssemblyRef(0x%08x, 0x%08x, %S, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
        pbPublicKeyOrToken, cbPublicKeyOrToken, MDSTR(szName), pMetaData, pbHashValue,
        cbHashValue, dwAssemblyRefFlags, pmar));
    
    START_MD_PERF();
    LOCKWRITE();
    
    IfFailGo(m_pStgdb->m_MiniMd.PreUpdate());
    
    _ASSERTE(szName && pmar);
    
    if (CheckDups(MDDupAssemblyRef))
    {
        LPUTF8 szUTF8Name, szUTF8Locale;
        UTF8STR(szName, szUTF8Name);
        UTF8STR(pMetaData->szLocale, szUTF8Locale);
        hr = ImportHelper::FindAssemblyRef(&m_pStgdb->m_MiniMd,
                                           szUTF8Name,
                                           szUTF8Locale,
                                           pbPublicKeyOrToken,
                                           cbPublicKeyOrToken,
                                           pMetaData->usMajorVersion,
                                           pMetaData->usMinorVersion,
                                           pMetaData->usBuildNumber,
                                           pMetaData->usRevisionNumber,
                                           dwAssemblyRefFlags,
                                           pmar);
        if (SUCCEEDED(hr))
        {
            if (IsENCOn())
            {
                IfFailGo(m_pStgdb->m_MiniMd.GetAssemblyRefRecord(RidFromToken(*pmar), &pRecord));
            }
            else
            {
                hr = META_S_DUPLICATE;
                goto ErrExit;
            }
        }
        else if (hr != CLDB_E_RECORD_NOTFOUND)
        {
            IfFailGo(hr);
        }
    }
    
    // Create a new record if needed.
    if (pRecord == NULL)
    {
        // Create a new record.
        IfFailGo(m_pStgdb->m_MiniMd.AddAssemblyRefRecord(&pRecord, &iRecord));

        // Set the output parameter.
        *pmar = TokenFromRid(iRecord, mdtAssemblyRef);
    }

    // Set rest of the attributes.
    SetCallerDefine();
    IfFailGo(_SetAssemblyRefProps(*pmar, pbPublicKeyOrToken, cbPublicKeyOrToken, szName, pMetaData,
                                 pbHashValue, cbHashValue, 
                                 dwAssemblyRefFlags));
ErrExit:
    SetCallerExternal();
    
    STOP_MD_PERF(DefineAssemblyRef);
    END_ENTRYPOINT_NOTHROW;
    
    return hr;
}   // RegMeta::DefineAssemblyRef