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