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 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 #3
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 #4
0
//*****************************************************************************
// Add a RegMeta pointer to the loaded module list
//*****************************************************************************
HRESULT LOADEDMODULES::AddModuleToLoadedList(RegMeta * pRegMeta)
{
    HRESULT    hr = NOERROR;
    RegMeta ** ppRegMeta;
    
    IfFailGo(InitializeStatics());
    
    {
        LOCKWRITE();
    
        ppRegMeta = s_pLoadedModules->Append();
        IfNullGo(ppRegMeta);
    
        // The cache holds a copy of the pointer, but no ref-count.  There is no
        //  point to the ref-count, because it just changes comparisons against 0
        //  to comparisons against 1.
        *ppRegMeta = pRegMeta;
    
        // If the module is read-only, hash it.
        if (pRegMeta->IsReadOnly())
        {
            ULONG ixHash = HashFileName(pRegMeta->GetNameOfDBFile());
            m_HashedModules[ixHash] = pRegMeta;
        }
    }
    
ErrExit:    
    return hr;
} // LOADEDMODULES::AddModuleToLoadedList
Beispiel #5
0
//*******************************************************************************
// helper to set field layout
// 
// Implements internal API code:IMetaDataEmitHelper::SetFieldLayoutHelper.
//*******************************************************************************
HRESULT RegMeta::SetFieldLayoutHelper(  // Return hresult.
    mdFieldDef  fd,                     // [IN] field to associate the layout info
    ULONG       ulOffset)               // [IN] the offset for the field
{
    HRESULT     hr;
    FieldLayoutRec *pFieldLayoutRec;
    RID         iFieldLayoutRec;

    LOCKWRITE();

    if (ulOffset == ULONG_MAX)
    {
        // invalid argument
        IfFailGo( E_INVALIDARG );
    }

    // create a field layout record
    IfFailGo(m_pStgdb->m_MiniMd.AddFieldLayoutRecord(&pFieldLayoutRec, &iFieldLayoutRec));

    // Set the Field entry.
    IfFailGo(m_pStgdb->m_MiniMd.PutToken(
        TBL_FieldLayout,
        FieldLayoutRec::COL_Field,
        pFieldLayoutRec,
        fd));
    pFieldLayoutRec->SetOffSet(ulOffset);
    IfFailGo( m_pStgdb->m_MiniMd.AddFieldLayoutToHash(iFieldLayoutRec) );

ErrExit:

    return hr;
} // RegMeta::SetFieldLayout
Beispiel #6
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()
Beispiel #7
0
//*******************************************************************************
// helper to define method semantics
// 
// Implements internal API code:IMetaDataEmitHelper::DefineMethodSemanticsHelper.
//*******************************************************************************
HRESULT RegMeta::DefineMethodSemanticsHelper(
    mdToken     tkAssociation,          // [IN] property or event token
    DWORD       dwFlags,                // [IN] semantics
    mdMethodDef md)                     // [IN] method to associated with
{
    HRESULT     hr;
    LOCKWRITE();
    hr = _DefineMethodSemantics((USHORT) dwFlags, md, tkAssociation, false);

ErrExit:
    return hr;
} // RegMeta::DefineMethodSemantics
Beispiel #8
0
//*****************************************************************************
// Helper : Set ResolutionScope of a TypeRef
// 
// Implements internal API code:IMetaDataEmitHelper::SetResolutionScopeHelper.
//*****************************************************************************
HRESULT RegMeta::SetResolutionScopeHelper(  // Return hresult.
    mdTypeRef   tr,                     // [IN] TypeRef record to update
    mdToken     rs)                     // [IN] new ResolutionScope
{
    HRESULT      hr = NOERROR;
    TypeRefRec * pTypeRef;
    
    LOCKWRITE();
    
    IfFailGo(m_pStgdb->m_MiniMd.GetTypeRefRecord(RidFromToken(tr), &pTypeRef));
    IfFailGo(m_pStgdb->m_MiniMd.PutToken(TBL_TypeRef, TypeRefRec::COL_ResolutionScope, pTypeRef, rs));
    
ErrExit:
    return hr;
} // RegMeta::SetResolutionScopeHelper
Beispiel #9
0
//*******************************************************************************
// helper to set type's extends column
// 
// Implements internal API code:IMetaDataEmitHelper::SetTypeParent.
//*******************************************************************************
HRESULT RegMeta::SetTypeParent(         // Return hresult.
    mdTypeDef   td,                     // [IN] Type definition
    mdToken     tkExtends)              // [IN] parent type
{
    HRESULT     hr;
    TypeDefRec  *pRec;

    LOCKWRITE();

    IfFailGo(m_pStgdb->m_MiniMd.GetTypeDefRecord(RidFromToken(td), &pRec));
    IfFailGo( m_pStgdb->m_MiniMd.PutToken(TBL_TypeDef, TypeDefRec::COL_Extends, pRec, tkExtends) );

ErrExit:
    return hr;
} // RegMeta::SetTypeParent
Beispiel #10
0
//*****************************************************************************
// Helper : Set offset of a ManifestResource
// 
// Implements internal API code:IMetaDataEmitHelper::SetManifestResourceOffsetHelper.
//*****************************************************************************
HRESULT 
RegMeta::SetManifestResourceOffsetHelper(
    mdManifestResource mr,          // [IN] The manifest token
    ULONG              ulOffset)    // [IN] new offset
{
    HRESULT hr = NOERROR;
    ManifestResourceRec * pRec;
    
    LOCKWRITE();
    
    IfFailGo(m_pStgdb->m_MiniMd.GetManifestResourceRecord(RidFromToken(mr), &pRec));
    pRec->SetOffset(ulOffset);
    
ErrExit:
    return hr;
} // RegMeta::SetManifestResourceOffsetHelper
Beispiel #11
0
//*****************************************************************************
// Remove a RegMeta pointer from the loaded module list
//*****************************************************************************
BOOL LOADEDMODULES::RemoveModuleFromLoadedList(RegMeta *pRegMeta)
{
	int			count;
	int			index;
    BOOL        bRemoved = FALSE;
    ULONG       cRef;
    
    LOCKWRITE();
    
    // The cache is locked for write, so no other thread can obtain the RegMeta
    //  from the cache.  See if some other thread has a ref-count.
    cRef = pRegMeta->GetRefCount();
    
    // If some other thread has a ref-count, don't remove from the cache.
    if (cRef > 0)
        return FALSE;
    
	// If there is no loaded modules, don't bother
	if (g_LoadedModules == NULL)
	{
		return TRUE; // Can't be cached, same as if removed by this thread.
	}

	// loop through each loaded modules
	count = g_LoadedModules->Count();
	for (index = 0; index < count; index++)
	{
		if ((*g_LoadedModules)[index] == pRegMeta)
		{
			// found a match to remove
			g_LoadedModules->Delete(index);
            bRemoved = TRUE;
			break;
		}
	}

	// If no more loaded modules, delete the dynamic array
	if (g_LoadedModules->Count() == 0)
	{
		delete g_LoadedModules;
		g_LoadedModules = NULL;
	}
    
    return bRemoved;
}	// LOADEDMODULES::RemoveModuleFromLoadedList
Beispiel #12
0
//*******************************************************************************
// helper to set type's extends column
// 
// Implements internal API code:IMetaDataEmitHelper::AddInterfaceImpl.
//*******************************************************************************
HRESULT RegMeta::AddInterfaceImpl(      // Return hresult.
    mdTypeDef   td,                     // [IN] Type definition
    mdToken     tkInterface)            // [IN] interface type
{
    HRESULT             hr;
    InterfaceImplRec    *pRec;
    RID                 ii;

    LOCKWRITE();
    hr = ImportHelper::FindInterfaceImpl(&(m_pStgdb->m_MiniMd), td, tkInterface, (mdInterfaceImpl *)&ii);
    if (hr == S_OK)
        goto ErrExit;
    IfFailGo(m_pStgdb->m_MiniMd.AddInterfaceImplRecord(&pRec, &ii));
    IfFailGo(m_pStgdb->m_MiniMd.PutToken( TBL_InterfaceImpl, InterfaceImplRec::COL_Class, pRec, td));
    IfFailGo(m_pStgdb->m_MiniMd.PutToken( TBL_InterfaceImpl, InterfaceImplRec::COL_Interface, pRec, tkInterface));

ErrExit:
    return hr;
} // RegMeta::AddInterfaceImpl
Beispiel #13
0
//*******************************************************************************
// helper to define event
// 
// Implements internal API code:IMetaDataEmitHelper::DefineEventHelper.
//*******************************************************************************
STDMETHODIMP RegMeta::DefineEventHelper(    // Return hresult.
    mdTypeDef   td,                     // [IN] the class/interface on which the event is being defined
    LPCWSTR     szEvent,                // [IN] Name of the event
    DWORD       dwEventFlags,           // [IN] CorEventAttr
    mdToken     tkEventType,            // [IN] a reference (mdTypeRef or mdTypeRef) to the Event class
    mdEvent     *pmdEvent)              // [OUT] output event token
{
    HRESULT     hr = S_OK;
    LOG((LOGMD, "MD RegMeta::DefineEventHelper(0x%08x, %S, 0x%08x, 0x%08x, 0x%08x)\n",
        td, szEvent, dwEventFlags, tkEventType, pmdEvent));

    LOCKWRITE();
    
    IfFailGo(m_pStgdb->m_MiniMd.PreUpdate());
    
    hr = _DefineEvent(td, szEvent, dwEventFlags, tkEventType, pmdEvent);
    
ErrExit:
    return hr;
} // RegMeta::DefineEvent
Beispiel #14
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 #15
0
//*****************************************************************************
// Add a RegMeta pointer to the loaded module list
//*****************************************************************************
HRESULT LOADEDMODULES::AddModuleToLoadedList(RegMeta *pRegMeta)
{
	HRESULT		hr = NOERROR;
	RegMeta		**ppRegMeta;

    LOCKWRITE();
    
	// create the dynamic array if it is not created yet.
	if (g_LoadedModules == NULL)
	{
		g_LoadedModules = new LOADEDMODULES;
        IfNullGo(g_LoadedModules);
	}

	ppRegMeta = g_LoadedModules->Append();
    IfNullGo(ppRegMeta);
	
	*ppRegMeta = pRegMeta;
    
ErrExit:    
    return hr;
}	// LOADEDMODULES::AddModuleToLoadedList
Beispiel #16
0
//---------------------------------------------------------------------------------------
// 
// Initialize the static instance and lock.
// 
HRESULT 
LOADEDMODULES::InitializeStatics()
{
    HRESULT hr = S_OK;
    
    if (VolatileLoad(&s_pLoadedModules) == NULL)
    {
        // Initialize global read-write lock
        {
            NewHolder<UTSemReadWrite> pSemReadWrite = new (nothrow) UTSemReadWrite();
            IfNullGo(pSemReadWrite);
            IfFailGo(pSemReadWrite->Init());
            
            if (InterlockedCompareExchangeT<UTSemReadWrite *>(&m_pSemReadWrite, pSemReadWrite, NULL) == NULL)
            {   // We won the initialization race
                pSemReadWrite.SuppressRelease();
            }
        }
        
        // Initialize the global instance
        {
            NewHolder<LOADEDMODULES> pLoadedModules = new (nothrow) LOADEDMODULES();
            IfNullGo(pLoadedModules);
            
            {
                LOCKWRITE();
                
                if (VolatileLoad(&s_pLoadedModules) == NULL)
                {
                    VolatileStore(&s_pLoadedModules, pLoadedModules.Extract());
                }
            }
        }
    }
    
ErrExit:
    return hr;
} // LOADEDMODULES::InitializeStatics
Beispiel #17
0
//*****************************************************************************
// Using the existing RegMeta and reopen with another chuck of memory. Make sure that all stgdb
// is still kept alive.
//*****************************************************************************
HRESULT RegMeta::ReOpenWithMemory(
    LPCVOID     pData,                  // [in] Location of scope data.
    ULONG       cbData,                 // [in] Size of the data pointed to by pData.
    DWORD       dwReOpenFlags)           // [in] ReOpen flags
{
    HRESULT hr = NOERROR;

    // Only allow the ofCopyMemory and ofTakeOwnership flags 
    if (dwReOpenFlags != 0 && ((dwReOpenFlags & (~(ofCopyMemory|ofTakeOwnership))) > 0))
        return E_INVALIDARG;

    LOCKWRITE();

    
    // put the current m_pStgdb to the free list
    m_pStgdb->m_pNextStgdb = m_pStgdbFreeList;
    m_pStgdbFreeList = m_pStgdb;
    m_pStgdb = new (nothrow) CLiteWeightStgdbRW;
    IfNullGo( m_pStgdb );
    IfFailGo( OpenExistingMD(0 /* szFileName */, const_cast<void*>(pData), cbData, ofReOpen|dwReOpenFlags /* flags */) );

#ifdef FEATURE_METADATA_INTERNAL_APIS
    // We've created a new Stgdb, but may still have an Internal Importer hanging around accessing the old Stgdb.
    // The free list ensures we don't have a dangling pointer, but the 
    // If we have a corresponding InternalInterface, need to clear it because it's now using stale data.
    // Others will need to update their Internal interface to get the new data.
    {
        HRESULT hrIgnore = SetCachedInternalInterface(NULL);
        (void)hrIgnore; //prevent "unused variable" error from GCC
        _ASSERTE(hrIgnore == NOERROR); // clearing the cached interface should always succeed.
    }
#endif //FEATURE_METADATA_INTERNAL_APIS

    // we are done!
ErrExit:
    if (FAILED(hr))
    {
        // recover to the old state
        if (m_pStgdb)
            delete m_pStgdb;
        m_pStgdb = m_pStgdbFreeList;
        m_pStgdbFreeList = m_pStgdbFreeList->m_pNextStgdb;
    }
#ifdef FEATURE_METADATA_RELEASE_MEMORY_ON_REOPEN
    else
    {
        if( !(CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_MD_PreserveDebuggerMetadataMemory)) && IsSafeToDeleteStgdb())
        {
            // now that success is assured, delete the old block of memory
            // This isn't normally a safe operation because we would have given out
            // internal pointers to the memory. However when this feature is enabled
            // we track calls that might have given out internal pointers. If none
            // of the APIs were ever called then we can safely delete.
            CLiteWeightStgdbRW* pStgdb = m_pStgdbFreeList;
            m_pStgdbFreeList = m_pStgdbFreeList->m_pNextStgdb;
            delete pStgdb;
        }

        MarkSafeToDeleteStgdb(); // As of right now, no APIs have given out internal pointers
                                 // to the newly allocated stgdb
    }
#endif

    return hr;
} // RegMeta::ReOpenWithMemory
Beispiel #18
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
Beispiel #19
0
//*****************************************************************************
// translating signature from one scope to another scope
// 
// Implements public API code:IMetaDataEmit::TranslateSigWithScope.
// Implements internal API code:IMetaDataHelper::TranslateSigWithScope.
//*****************************************************************************
STDMETHODIMP RegMeta::TranslateSigWithScope(    // S_OK or error.
    IMetaDataAssemblyImport *pAssemImport, // [IN] importing assembly interface
    const void  *pbHashValue,           // [IN] Hash Blob for Assembly.
    ULONG       cbHashValue,            // [IN] Count of bytes.
    IMetaDataImport *pImport,           // [IN] importing interface
    PCCOR_SIGNATURE pbSigBlob,          // [IN] signature in the importing scope
    ULONG       cbSigBlob,              // [IN] count of bytes of signature
    IMetaDataAssemblyEmit   *pAssemEmit,// [IN] emit assembly interface
    IMetaDataEmit *pEmit,               // [IN] emit interface
    PCOR_SIGNATURE pvTranslatedSig,     // [OUT] buffer to hold translated signature
    ULONG       cbTranslatedSigMax,
    ULONG       *pcbTranslatedSig)      // [OUT] count of bytes in the translated signature
{
#ifdef FEATURE_METADATA_EMIT
    HRESULT     hr = S_OK;

    IMDCommon   *pAssemImportMDCommon = NULL;
    IMDCommon   *pImportMDCommon = NULL;

    BEGIN_ENTRYPOINT_NOTHROW;

    RegMeta     *pRegMetaAssemEmit = static_cast<RegMeta*>(pAssemEmit);
    RegMeta     *pRegMetaEmit = NULL;

    CQuickBytes qkSigEmit;
    ULONG       cbEmit;

    pRegMetaEmit = static_cast<RegMeta*>(pEmit);

    {
        // This function can cause new TypeRef being introduced.
        LOCKWRITE();
        
        IfFailGo(m_pStgdb->m_MiniMd.PreUpdate());
        
        _ASSERTE(pvTranslatedSig && pcbTranslatedSig);

        if (pAssemImport)
        {
            IfFailGo(pAssemImport->QueryInterface(IID_IMDCommon, (void**)&pAssemImportMDCommon));
        }
        IMetaModelCommon *pAssemImportMetaModelCommon = pAssemImportMDCommon ? pAssemImportMDCommon->GetMetaModelCommon() : 0;

        IfFailGo(pImport->QueryInterface(IID_IMDCommon, (void**)&pImportMDCommon));
        IMetaModelCommon *pImportMetaModelCommon = pImportMDCommon->GetMetaModelCommon();

        IfFailGo( ImportHelper::MergeUpdateTokenInSig(  // S_OK or error.
                pRegMetaAssemEmit ? &(pRegMetaAssemEmit->m_pStgdb->m_MiniMd) : 0, // The assembly emit scope.
                &(pRegMetaEmit->m_pStgdb->m_MiniMd),    // The emit scope.
                pAssemImportMetaModelCommon,            // Assembly where the signature is from.
                pbHashValue,                            // Hash value for the import assembly.
                cbHashValue,                            // Size in bytes.
                pImportMetaModelCommon,                 // The scope where signature is from.
                pbSigBlob,                              // signature from the imported scope
                NULL,                                   // Internal OID mapping structure.
                &qkSigEmit,                             // [OUT] translated signature
                0,                                      // start from first byte of the signature
                0,                                      // don't care how many bytes consumed
                &cbEmit));                              // [OUT] total number of bytes write to pqkSigEmit
        memcpy(pvTranslatedSig, qkSigEmit.Ptr(), cbEmit > cbTranslatedSigMax ? cbTranslatedSigMax :cbEmit );
        *pcbTranslatedSig = cbEmit;
        if (cbEmit > cbTranslatedSigMax)
            hr = CLDB_S_TRUNCATION;
    }

ErrExit:
    END_ENTRYPOINT_NOTHROW;

    if (pAssemImportMDCommon)
        pAssemImportMDCommon->Release();
    if (pImportMDCommon)
        pImportMDCommon->Release();

    return hr;
#else //!FEATURE_METADATA_EMIT
    return E_NOTIMPL;
#endif //!FEATURE_METADATA_EMIT
} // RegMeta::TranslateSigWithScope
Beispiel #20
0
//*******************************************************************************
// helper to add a declarative security blob to a class or method
// 
// Implements internal API code:IMetaDataEmitHelper::AddDeclarativeSecurityHelper.
//*******************************************************************************
STDMETHODIMP RegMeta::AddDeclarativeSecurityHelper(
    mdToken     tk,                     // [IN] Parent token (typedef/methoddef)
    DWORD       dwAction,               // [IN] Security action (CorDeclSecurity)
    void const  *pValue,                // [IN] Permission set blob
    DWORD       cbValue,                // [IN] Byte count of permission set blob
    mdPermission*pmdPermission)         // [OUT] Output permission token
{
    HRESULT         hr = S_OK;
    DeclSecurityRec *pDeclSec = NULL;
    RID             iDeclSec;
    short           sAction = static_cast<short>(dwAction);
    mdPermission    tkPerm;

    LOG((LOGMD, "MD RegMeta::AddDeclarativeSecurityHelper(0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
        tk, dwAction, pValue, cbValue, pmdPermission));
    
    LOCKWRITE();
    IfFailGo(m_pStgdb->m_MiniMd.PreUpdate());
    
    _ASSERTE(TypeFromToken(tk) == mdtTypeDef || TypeFromToken(tk) == mdtMethodDef || TypeFromToken(tk) == mdtAssembly);

    // Check for valid Action.
    if (sAction == 0 || sAction > dclMaximumValue)
        IfFailGo(E_INVALIDARG);

    if (CheckDups(MDDupPermission))
    {
        hr = ImportHelper::FindPermission(&(m_pStgdb->m_MiniMd), tk, sAction, &tkPerm);

        if (SUCCEEDED(hr))
        {
            // Set output parameter.
            if (pmdPermission)
                *pmdPermission = tkPerm;
            if (IsENCOn())
                IfFailGo(m_pStgdb->m_MiniMd.GetDeclSecurityRecord(RidFromToken(tkPerm), &pDeclSec));
            else
            {
                hr = META_S_DUPLICATE;
                goto ErrExit;
            }
        }
        else if (hr != CLDB_E_RECORD_NOTFOUND)
            IfFailGo(hr);
    }

    // Create a new record.
    if (!pDeclSec)
    {
        IfFailGo(m_pStgdb->m_MiniMd.AddDeclSecurityRecord(&pDeclSec, &iDeclSec));
        tkPerm = TokenFromRid(iDeclSec, mdtPermission);

        // Set output parameter.
        if (pmdPermission)
            *pmdPermission = tkPerm;

        // Save parent and action information.
        IfFailGo(m_pStgdb->m_MiniMd.PutToken(TBL_DeclSecurity, DeclSecurityRec::COL_Parent, pDeclSec, tk));
        pDeclSec->SetAction(sAction);

        // Turn on the internal security flag on the parent.
        if (TypeFromToken(tk) == mdtTypeDef)
            IfFailGo(_TurnInternalFlagsOn(tk, tdHasSecurity));
        else if (TypeFromToken(tk) == mdtMethodDef)
            IfFailGo(_TurnInternalFlagsOn(tk, mdHasSecurity));
        IfFailGo(UpdateENCLog(tk));
    }

    // Write the blob into the record.
    IfFailGo(m_pStgdb->m_MiniMd.PutBlob(TBL_DeclSecurity, DeclSecurityRec::COL_PermissionSet,
                                        pDeclSec, pValue, cbValue));

    IfFailGo(UpdateENCLog(tkPerm));

ErrExit:

    return hr;
} // RegMeta::AddDeclarativeSecurityHelper
Beispiel #21
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 #22
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
Beispiel #23
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 #24
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 #25
0
//*****************************************************************************
// Remove a RegMeta pointer from the loaded module list
//*****************************************************************************
BOOL LOADEDMODULES::RemoveModuleFromLoadedList(RegMeta * pRegMeta)
{
    BOOL  bRemoved = FALSE;     // Was this module removed from the cache?
    int   iFound = -1;          // Index at which it was found.
    ULONG cRef;                 // Ref count of the module.
    
    // Lock the cache for write, so that no other thread will find what this 
    //  thread is about to delete, and so that no other thread will delete
    //  what this thread is about to try to find.
    HRESULT hr = S_OK;
    
    IfFailGo(InitializeStatics());
    
    {
        LOCKWRITE();
    
        // Search for this module in list of loaded modules.
        int count = s_pLoadedModules->Count();
        for (int index = 0; index < count; index++)
        {
            if ((*s_pLoadedModules)[index] == pRegMeta)
            {   // found a match to remove
                iFound = index;
                break;
            }
        }
    
        // If the module is still in the cache, it hasn't been deleted yet.
        if (iFound >= 0)
        {
            // See if there are any external references left.
            cRef = pRegMeta->GetRefCount();

            // If the cRef that we got from the module is zero, it will stay that way,
            //  because no other thread can discover the module while this thread holds
            //  the lock.

            // OTOH, if the cRef is not zero, this thread can just return, because the
            //  other thread will eventually take the ref count to zero, and will then 
            //  come through here to clean up the module. And this thread must not 
            //  delete the module out from under other threads.

            // It is possible that the cRef is zero, yet another thread has a pointer that
            //  it discovered before this thread took the lock.  (And that thread has
            //  released the ref-counts.)  In such a case, this thread can still remove the 
            //  module from the cache, and tell the caller to delete it, because the
            //  other thread will wait on the lock, then discover that the module
            //  is not in the cache, and it won't try to delete the module.

            if (cRef != 0)
            {   // Some other thread snuck in and found the entry in the cache.
                return FALSE;
            }

            // No other thread owns the object.  Remove from cache, and tell caller
            //  that we're done with it.  (Caller will delete.)
            s_pLoadedModules->Delete(iFound);
            bRemoved = TRUE;

            // If the module is read-only, remove from hash.
            if (pRegMeta->IsReadOnly())
            {
                // There may have been multiple capitalizations pointing to the same entry.
                //  Find and remove all of them.
                for (ULONG ixHash = 0; ixHash < LOADEDMODULES_HASH_SIZE; ++ixHash)
                {
                    if (m_HashedModules[ixHash] == pRegMeta)
                        m_HashedModules[ixHash] = NULL;
                }
            }
        }
    }
    
ErrExit:
    return bRemoved;
}  // LOADEDMODULES::RemoveModuleFromLoadedList
Beispiel #26
0
HRESULT 
RegMeta::QueryInterface(
    REFIID  riid, 
    void ** ppUnk)
{
    HRESULT hr = S_OK;
    BEGIN_ENTRYPOINT_NOTHROW;
    int fIsInterfaceRW = false;
    *ppUnk = 0;

    if (riid == IID_IUnknown)
    {
        *ppUnk = (IUnknown *)(IMetaDataImport2 *)this;
    }
    else if (riid == IID_IMDCommon)
    {
        *ppUnk = (IMDCommon *)this;
    }
    else if (riid == IID_IMetaDataImport)
    {
        *ppUnk = (IMetaDataImport2 *)this;
    }
    else if (riid == IID_IMetaDataImport2)
    {
        *ppUnk = (IMetaDataImport2 *)this;
    }
    else if (riid == IID_IMetaDataAssemblyImport)
    {
        *ppUnk = (IMetaDataAssemblyImport *)this;
    }
    else if (riid == IID_IMetaDataTables)
    {
        *ppUnk = static_cast<IMetaDataTables *>(this);
    }
    else if (riid == IID_IMetaDataTables2)
    {
        *ppUnk = static_cast<IMetaDataTables2 *>(this);
    }

#ifndef FEATURE_METADATA_STANDALONE_WINRT
    else if (riid == IID_IMetaDataInfo)
    {
        *ppUnk = static_cast<IMetaDataInfo *>(this);
    }
#endif //!FEATURE_METADATA_STANDALONE_WINRT

#ifdef FEATURE_METADATA_EMIT
    else if (riid == IID_IMetaDataEmit)
    {
        *ppUnk = (IMetaDataEmit2 *)this;
        fIsInterfaceRW = true;
    }
    else if (riid == IID_IMetaDataEmit2)
    {
        *ppUnk = (IMetaDataEmit2 *)this;
        fIsInterfaceRW = true;
    }
    else if (riid == IID_IMetaDataAssemblyEmit)
    {
        *ppUnk = (IMetaDataAssemblyEmit *)this;
        fIsInterfaceRW = true;
    }
#endif //FEATURE_METADATA_EMIT

#if defined(FEATURE_METADATA_IN_VM) && !defined(FEATURE_CORECLR)
    else if (riid == IID_IMetaDataValidate)
    {
        *ppUnk = (IMetaDataValidate *)this;
    }
#endif //defined(FEATURE_METADATA_IN_VM) && !defined(FEATURE_CORECLR)

#ifdef FEATURE_METADATA_EMIT_ALL
    else if (riid == IID_IMetaDataFilter)
    {
        *ppUnk = (IMetaDataFilter *)this;
    }
#endif //FEATURE_METADATA_EMIT_ALL

#ifdef FEATURE_METADATA_INTERNAL_APIS
    else if (riid == IID_IMetaDataHelper)
    {
        *ppUnk = (IMetaDataHelper *)this;
    }
    else if (riid == IID_IMDInternalEmit)
    {
        *ppUnk = static_cast<IMDInternalEmit *>(this);
    }
    else if (riid == IID_IGetIMDInternalImport)
    {
        *ppUnk = static_cast<IGetIMDInternalImport *>(this);
    }
#endif //FEATURE_METADATA_INTERNAL_APIS

#if defined(FEATURE_METADATA_EMIT) && defined(FEATURE_METADATA_INTERNAL_APIS)
    else if (riid == IID_IMetaDataEmitHelper)
    {
        *ppUnk = (IMetaDataEmitHelper *)this;
        fIsInterfaceRW = true;
    }
#endif //FEATURE_METADATA_EMIT && FEATURE_METADATA_INTERNAL_APIS

#ifdef FEATURE_METADATA_IN_VM
#ifdef FEATURE_COMINTEROP
    else if (riid == IID_IMarshal)
    {
        // We will only repond to this interface if scope is opened for ReadOnly
        if (IsOfReadOnly(m_OpenFlags))
        {
            if (m_pFreeThreadedMarshaler == NULL)
            {
                // Guard ourselves against first time QI on IMarshal from two different threads..
                LOCKWRITE();
                if (m_pFreeThreadedMarshaler == NULL)
                {
                    // First time! Create the FreeThreadedMarshaler
                    IfFailGo(CoCreateFreeThreadedMarshaler((IUnknown *)(IMetaDataEmit2 *)this, &m_pFreeThreadedMarshaler));
                }                
            }
            
            _ASSERTE(m_pFreeThreadedMarshaler != NULL);
            
            IfFailGo(m_pFreeThreadedMarshaler->QueryInterface(riid, ppUnk));
            
            // AddRef has happened in the QueryInterface and thus should just return
            goto ErrExit;
        }
        else
        {
            IfFailGo(E_NOINTERFACE);
        }
    }
#endif // FEATURE_COMINTEROP
#ifdef FEATURE_PREJIT
    else if (riid == IID_IMetaDataCorProfileData)
    {
        *ppUnk = (IMetaDataCorProfileData *)this;
    }
    else if (riid == IID_IMDInternalMetadataReorderingOptions)
    {
        *ppUnk = (IMDInternalMetadataReorderingOptions *)this;
    }
#endif //FEATURE_PREJIT
#endif //FEATURE_METADATA_IN_VM
    else
    {
        IfFailGo(E_NOINTERFACE);
    }

    if (fIsInterfaceRW && IsOfReadOnly(m_OpenFlags))
    {
        // They are asking for a read/write interface and this scope was
        // opened as Read-Only

        *ppUnk = NULL;
        IfFailGo(CLDB_E_INCOMPATIBLE);
    }

    if (fIsInterfaceRW)
    {
        LOCKWRITENORET();

        if (SUCCEEDED(hr))
        {
            hr = m_pStgdb->m_MiniMd.ConvertToRW();
        }

        if (FAILED(hr))
        {
            *ppUnk = NULL;
            goto ErrExit;
        }
    }

    AddRef();
ErrExit:
    
    END_ENTRYPOINT_NOTHROW;

    return hr;
} // RegMeta::QueryInterface