diff options
Diffstat (limited to 'src/md')
39 files changed, 33 insertions, 18804 deletions
diff --git a/src/md/compiler/classfactory.cpp b/src/md/compiler/classfactory.cpp index 603f7975aa..338095add3 100644 --- a/src/md/compiler/classfactory.cpp +++ b/src/md/compiler/classfactory.cpp @@ -42,14 +42,6 @@ const COCLASS_REGISTER g_CoClasses[] = { // pClsid szProgID pfnCreateObject { &CLSID_CorMetaDataDispenser, W("CorMetaDataDispenser"), Disp::CreateObject }, -#if !defined(FEATURE_CORECLR) && !defined(CROSSGEN_COMPILE) // coreclr doesn't export these - { &CLSID_CorMetaDataDispenserRuntime, W("CorMetaDataDispenserRuntime"), Disp::CreateObject }, - - { &CLSID_CorRuntimeHost, W("CorRuntimeHost"), CorHost::CreateObject }, - { &CLSID_CLRRuntimeHost, W("CLRRuntimeHost"), CorHost2::CreateObject }, - { &__uuidof(CLRPrivRuntime), W("CLRPrivRuntime"), CorHost2::CreateObject }, - { &CLSID_TypeNameFactory, NULL, (PFN_CREATE_OBJ)TypeNameFactoryCreateObject }, -#endif // FEATURE_CORECLR && !CROSSGEN_COMPILE { NULL, NULL, NULL } }; diff --git a/src/md/compiler/disp.cpp b/src/md/compiler/disp.cpp index b091729744..85b71286d2 100644 --- a/src/md/compiler/disp.cpp +++ b/src/md/compiler/disp.cpp @@ -16,9 +16,6 @@ #include <corerror.h> #include <mdlog.h> #include <mdcommon.h> -#ifdef FEATURE_COMINTEROP_TLB_SUPPORT -#include <imptlb.h> -#endif #ifdef EnC_SUPPORTED #define ENC_DELTA_HACK @@ -95,11 +92,7 @@ Disp::DefineScope( // Figure out what version of the metadata to emit if (rclsid == CLSID_CLR_v1_MetaData) { -#ifdef FEATURE_METADATA_STANDALONE_WINRT - IfFailGo(E_NOTIMPL); -#else optionForNewScope.m_MetadataVersion = MDVersion1; -#endif //!FEATURE_METADATA_STANDALONE_WINRT } else if (rclsid == CLSID_CLR_v2_MetaData) { @@ -200,7 +193,7 @@ static HRESULT DeliverScope(IMDCommon *pMDCommon, REFIID riid, DWORD dwOpenFlags HRESULT hr; BEGIN_ENTRYPOINT_NOTHROW; -#if !defined(FEATURE_METADATA_STANDALONE_WINRT) && defined(FEATURE_COMINTEROP) +#if defined(FEATURE_COMINTEROP) IfFailGo((dwOpenFlags & ofNoTransform) ? S_FALSE : CheckIfWinMDAdapterNeeded(pMDCommon)); if (hr == S_OK) { @@ -439,13 +432,6 @@ ErrExit: return hr; } // Disp::OpenScopeOnMemory -#if defined(FEATURE_METADATA_IN_VM) && !defined(FEATURE_CORECLR) && !defined(CROSSGEN_COMPILE) - -#include <metahost.h> -// Pointer to the activated CLR interface provided by the shim. -extern ICLRRuntimeInfo * g_pCLRRuntime; - -#endif //***************************************************************************** // Get the directory where the CLR system resides. @@ -458,27 +444,11 @@ Disp::GetCORSystemDirectory( DWORD cchBuffer, // [in] Size of the buffer DWORD *pcchBuffer) // [out] Number of characters returned { -#if defined(FEATURE_METADATA_IN_VM) && !defined(FEATURE_CORECLR) && !defined(CROSSGEN_COMPILE) - HRESULT hr = S_OK; - BEGIN_ENTRYPOINT_NOTHROW; - - // This implies a machine-wide CLR install root, which may not exist for some CLR - // skus using standalone metadata. - *pcchBuffer = cchBuffer; - hr = g_pCLRRuntime->GetRuntimeDirectory(szBuffer, pcchBuffer); - - END_ENTRYPOINT_NOTHROW; - - return hr; -#else //!FEATURE_METADATA_IN_VM || FEATURE_CORECLR -#ifdef FEATURE_CORECLR UNREACHABLE_MSG("Calling IMetaDataDispenser::GetCORSystemDirectory! This code should not be " "reachable or needs to be reimplemented for CoreCLR!"); -#endif //FEATURE_CORECLR return E_NOTIMPL; -#endif //!FEATURE_METADATA_IN_VM || FEATURE_CORECLR } // Disp::GetCORSystemDirectory HRESULT Disp::FindAssembly( // S_OK or error @@ -912,7 +882,7 @@ ErrExit: return hr; } // Disp::GetOption -#if defined(FEATURE_METADATA_IN_VM) || defined(FEATURE_METADATA_STANDALONE_WINRT) +#if defined(FEATURE_METADATA_IN_VM) //--------------------------------------------------------------------------------------- // @@ -924,7 +894,7 @@ void DeleteMetaData() LOADEDMODULES::DeleteStatics(); } -#endif //FEATURE_METADATA_IN_VM || FEATURE_METADATA_STANDALONE_WINRT +#endif //FEATURE_METADATA_IN_VM // // This is the entrypoint for usages of MetaData that need to start with the dispenser (e.g. diff --git a/src/md/compiler/mdperf.h b/src/md/compiler/mdperf.h index 77def32d21..a83c8c9ba7 100644 --- a/src/md/compiler/mdperf.h +++ b/src/md/compiler/mdperf.h @@ -143,7 +143,6 @@ MD_FUNC(GetCustomAttributeProps)\ MD_FUNC(FindTypeRef)\ MD_FUNC(RefToDefOptimization)\ - MD_FUNC(ProcessFilter)\ MD_FUNC(DefineAssembly)\ MD_FUNC(DefineAssemblyRef)\ MD_FUNC(DefineFile)\ diff --git a/src/md/compiler/mdsighelper.h b/src/md/compiler/mdsighelper.h index 0d089729bb..49c0752fe3 100644 --- a/src/md/compiler/mdsighelper.h +++ b/src/md/compiler/mdsighelper.h @@ -104,13 +104,7 @@ class UnifiedAssemblySigComparer : public MDSigComparer::MDSigComparerBaseType protected: RegMeta *m_pRegMeta; -#ifdef FEATURE_FUSION - HRESULT _CreateIAssemblyNameFromAssemblyRef( - mdToken tkAsmRef, - IAssemblyName **ppAsmName); -#else HRESULT _CompareAssemblies(mdToken tkAsmRef1,mdToken tkAsmRef2, BOOL* pfEquivalent); -#endif HRESULT _CreateTypeNameFromTypeRef( mdToken tkTypeRef, diff --git a/src/md/compiler/mdutil.cpp b/src/md/compiler/mdutil.cpp index 2e01258bea..0de5ad45ea 100644 --- a/src/md/compiler/mdutil.cpp +++ b/src/md/compiler/mdutil.cpp @@ -20,7 +20,7 @@ #include <rwutil.h> -#if defined(FEATURE_METADATA_IN_VM) || defined(FEATURE_METADATA_STANDALONE_WINRT) +#if defined(FEATURE_METADATA_IN_VM) LOADEDMODULES * LOADEDMODULES::s_pLoadedModules = NULL; UTSemReadWrite * LOADEDMODULES::m_pSemReadWrite = NULL; @@ -363,7 +363,7 @@ ErrExit: #endif //_DEBUG -#endif //FEATURE_METADATA_IN_VM || FEATURE_METADATA_STANDALONE_WINRT +#endif //FEATURE_METADATA_IN_VM #ifdef FEATURE_METADATA_IN_VM diff --git a/src/md/compiler/mdutil.h b/src/md/compiler/mdutil.h index 58cdbf108a..331817ec9a 100644 --- a/src/md/compiler/mdutil.h +++ b/src/md/compiler/mdutil.h @@ -61,7 +61,7 @@ public: }; // class CORPATHService -#if defined(FEATURE_METADATA_IN_VM) || defined(FEATURE_METADATA_STANDALONE_WINRT) +#if defined(FEATURE_METADATA_IN_VM) class RegMeta; @@ -114,6 +114,6 @@ public: #endif }; // class LOADEDMODULES -#endif //FEATURE_METADATA_IN_VM || FEATURE_METADATA_STANDALONE_WINRT +#endif //FEATURE_METADATA_IN_VM #endif // __MDUtil__h__ diff --git a/src/md/compiler/mdvalidator.cpp b/src/md/compiler/mdvalidator.cpp index adcfd51eb3..ce6c14e468 100644 --- a/src/md/compiler/mdvalidator.cpp +++ b/src/md/compiler/mdvalidator.cpp @@ -19,9 +19,6 @@ #include "pedecoder.h" #include "stgio.h" #include "corhost.h" -#ifdef FEATURE_FUSION -#include "fusion.h" -#endif #include "sstring.h" #include "nsutilpriv.h" #include "holder.h" @@ -5210,7 +5207,7 @@ HRESULT RegMeta::ValidateAssembly(RID rid) dwFlags = (CorAssemblyFlags) pMiniMd->getFlagsOfAssembly(pRecord); // Validate the flags - invalidAssemblyFlags = dwFlags & (~(afPublicKey | afRetargetable | afPA_FullMask | afEnableJITcompileTracking | afDisableJITcompileOptimizer | afContentType_Mask)); + invalidAssemblyFlags = dwFlags & (~(afPublicKey | afRetargetable | afPA_FullMask | afDebuggableAttributeMask | afContentType_Mask)); // Validate we only set a legal processor architecture flags // The processor architecture flags were introduced in CLR v2.0. @@ -7185,123 +7182,7 @@ MDSigComparer::_CompareMethodSignatureHeader( //***************************************************************************** //***************************************************************************** -#ifdef FEATURE_FUSION -HRESULT -UnifiedAssemblySigComparer::_CreateIAssemblyNameFromAssemblyRef( - mdToken tkAsmRef, - IAssemblyName **ppAsmName) -{ - HRESULT hr; - - void const * pvPublicKey; - ULONG cbPublicKey; - ULONG cchName; - ASSEMBLYMETADATA amd; - void const * pvHashValue; - ULONG cbHashValue; - DWORD dwFlags; - - ZeroMemory(&amd, sizeof(amd)); - - IfFailRet(m_pRegMeta->GetAssemblyRefProps(tkAsmRef, - NULL, - NULL, - NULL, - 0, - &cchName, - &amd, - NULL, - NULL, - NULL)); - - StackSString ssName; - StackSString ssLocale; - amd.szLocale = ssLocale.OpenUnicodeBuffer(amd.cbLocale); - - IfFailRet(m_pRegMeta->GetAssemblyRefProps(tkAsmRef, - &pvPublicKey, - &cbPublicKey, - ssName.OpenUnicodeBuffer(cchName), - cchName, - &cchName, - &amd, - &pvHashValue, - &cbHashValue, - &dwFlags)); - - ssName.CloseBuffer(); - ssLocale.CloseBuffer(); - - IAssemblyName *pAsmName = NULL; - - IfFailRet(CreateAssemblyNameObject(&pAsmName, - ssName.GetUnicode(), - CANOF_SET_DEFAULT_VALUES, - NULL)); - - // Set the public key token - IfFailRet(pAsmName->SetProperty(ASM_NAME_PUBLIC_KEY_TOKEN, - (LPVOID)pvPublicKey, - cbPublicKey)); - // Set the culture - if (amd.cbLocale == 0 || amd.szLocale == NULL) - { - IfFailRet(pAsmName->SetProperty(ASM_NAME_CULTURE, - W("Neutral"), - sizeof(W("Neutral")))); - } - else - { - IfFailRet(pAsmName->SetProperty(ASM_NAME_CULTURE, - amd.szLocale, - amd.cbLocale)); - } - - // Set the major version - IfFailRet(pAsmName->SetProperty(ASM_NAME_MAJOR_VERSION, - &amd.usMajorVersion, - sizeof(amd.usMajorVersion))); - - // Set the minor version - IfFailRet(pAsmName->SetProperty(ASM_NAME_MINOR_VERSION, - &amd.usMinorVersion, - sizeof(amd.usMinorVersion))); - - // Set the build number - IfFailRet(pAsmName->SetProperty(ASM_NAME_BUILD_NUMBER, - &amd.usBuildNumber, - sizeof(amd.usBuildNumber))); - - // Set the revision number - IfFailRet(pAsmName->SetProperty(ASM_NAME_REVISION_NUMBER, - &amd.usRevisionNumber, - sizeof(amd.usRevisionNumber))); - - *ppAsmName = pAsmName; - - return S_OK; -} - -//***************************************************************************** -// Define holder to release IAssemblyName on exception. -//***************************************************************************** -void UnifiedAssemblySigComparer_IAssemblyNameRelease(IAssemblyName *value) -{ - if (value != NULL) - { - value->Release(); - } -} - -typedef Holder<IAssemblyName*, - DoNothing<IAssemblyName*>, - &UnifiedAssemblySigComparer_IAssemblyNameRelease, - NULL> UnifiedAssemblySigComparer_IAssemblyNameHolder; - -#endif // FEATURE_FUSION - -#ifndef FEATURE_FUSION HRESULT UnifiedAssemblySigComparer::_CompareAssemblies(mdToken tkAsmRef1,mdToken tkAsmRef2, BOOL* pfEquivalent) { @@ -7417,7 +7298,6 @@ HRESULT UnifiedAssemblySigComparer::_CompareAssemblies(mdToken tkAsmRef1,mdToken return S_OK; }; -#endif // FEATURE_FUSION //***************************************************************************** //***************************************************************************** @@ -7523,38 +7403,8 @@ UnifiedAssemblySigComparer::CompareToken( } BOOL fEquivalent; -#ifdef FEATURE_FUSION //move into _CompareAssemblies - IAssemblyName *pAsmName1 = NULL; - IfFailRet(_CreateIAssemblyNameFromAssemblyRef(tkParent1, &pAsmName1)); - UnifiedAssemblySigComparer_IAssemblyNameHolder anh1(pAsmName1); - - IAssemblyName *pAsmName2 = NULL; - IfFailRet(_CreateIAssemblyNameFromAssemblyRef(tkParent2, &pAsmName2)); - UnifiedAssemblySigComparer_IAssemblyNameHolder anh2(pAsmName2); - - DWORD cchDisplayName = 0; - - StackSString ssDisplayName1; - pAsmName1->GetDisplayName(NULL, &cchDisplayName, NULL); - IfFailRet(pAsmName1->GetDisplayName(ssDisplayName1.OpenUnicodeBuffer(cchDisplayName), &cchDisplayName, NULL)); - ssDisplayName1.CloseBuffer(); - - StackSString ssDisplayName2; - pAsmName2->GetDisplayName(NULL, &cchDisplayName, NULL); - IfFailRet(pAsmName2->GetDisplayName(ssDisplayName2.OpenUnicodeBuffer(cchDisplayName), &cchDisplayName, NULL)); - ssDisplayName2.CloseBuffer(); - - AssemblyComparisonResult res; - IfFailRet(CompareAssemblyIdentity(ssDisplayName1.GetUnicode(), - TRUE, - ssDisplayName2.GetUnicode(), - TRUE, - &fEquivalent, - &res)); -#else // no redirects supported IfFailRet(_CompareAssemblies(tkParent1,tkParent2,&fEquivalent)); -#endif if (!fEquivalent) { diff --git a/src/md/compiler/newmerger.cpp b/src/md/compiler/newmerger.cpp deleted file mode 100644 index d5199bb570..0000000000 --- a/src/md/compiler/newmerger.cpp +++ /dev/null @@ -1,6303 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. -//***************************************************************************** -// NewMerger.cpp -// - -// -// contains utility code to MD directory -// -// This file provides Compiler Support functionality in metadata. -//***************************************************************************** -#include "stdafx.h" - -#include "newmerger.h" -#include "regmeta.h" - - -#include "importhelper.h" -#include "rwutil.h" -#include "mdlog.h" -#include <posterror.h> -#include <sstring.h> -#include "ndpversion.h" - -#ifdef FEATURE_METADATA_EMIT_ALL - -#define MODULEDEFTOKEN TokenFromRid(1, mdtModule) - -#define COR_MSCORLIB_NAME "mscorlib" -#define COR_MSCORLIB_TYPEREF {0xb7, 0x7a, 0x5c, 0x56,0x19,0x34,0xe0,0x89} - -#define COR_CONSTRUCTOR_METADATA_IDENTIFIER W(".ctor") - -#define COR_COMPILERSERVICE_NAMESPACE "System.Runtime.CompilerServices" -#define COR_EXCEPTIONSERVICE_NAMESPACE "System.Runtime.ExceptionServices" -#define COR_SUPPRESS_MERGE_CHECK_ATTRIBUTE "SuppressMergeCheckAttribute" -#define COR_HANDLE_PROCESS_CORRUPTED_STATE_EXCEPTION_ATTRIBUTE "HandleProcessCorruptedStateExceptionsAttribute" -#define COR_MISCBITS_NAMESPACE "Microsoft.VisualC" -#define COR_MISCBITS_ATTRIBUTE "Microsoft.VisualC.MiscellaneousBitsAttribute" -#define COR_NATIVECPPCLASS_ATTRIBUTE "System.Runtime.CompilerServices.NativeCppClassAttribute" - -// MODULE_CA_LOCATION W("System.Runtime.CompilerServices.AssemblyAttributesGoHere") -#define MODULE_CA_TYPENAME "AssemblyAttributesGoHere" // fake assembly type-ref for hanging Assembly-level CAs off of - -//***************************************************************************** -// BEGIN: Security Critical Attributes and Enumeration -//***************************************************************************** -#define COR_SECURITYCRITICALSCOPE_ENUM_W W("System.Security.SecurityCriticalScope") - -#define COR_SECURITYCRITICAL_ATTRIBUTE_FULL "System.Security.SecurityCriticalAttribute" -#define COR_SECURITYTRANSPARENT_ATTRIBUTE_FULL "System.Security.SecurityTransparentAttribute" -#define COR_SECURITYTREATASSAFE_ATTRIBUTE_FULL "System.Security.SecurityTreatAsSafeAttribute" - -#define COR_SECURITYCRITICAL_ATTRIBUTE_FULL_W W("System.Security.SecurityCriticalAttribute") -#define COR_SECURITYTRANSPARENT_ATTRIBUTE_FULL_W W("System.Security.SecurityTransparentAttribute") -#define COR_SECURITYTREATASSAFE_ATTRIBUTE_FULL_W W("System.Security.SecurityTreatAsSafeAttribute") -#define COR_SECURITYSAFECRITICAL_ATTRIBUTE_FULL_W W("System.Security.SecuritySafeCriticalAttribute") - - // definitions of enumeration for System.Security.SecurityCriticalScope (Explicit or Everything) -#define COR_SECURITYCRITICAL_CTOR_ARGCOUNT_NO_SCOPE 0 -#define COR_SECURITYCRITICAL_CTOR_ARGCOUNT_SCOPE_EVERYTHING 1 -#define COR_SECURITYCRITICAL_CTOR_NO_SCOPE_SIG_MAX_SIZE (3) -#define COR_SECURITYCRITICAL_CTOR_SCOPE_SIG_MAX_SIZE (5 + sizeof(mdTypeRef) * 1) - -#define COR_SECURITYCRITICAL_ATTRIBUTE_NAMESPACE "System.Security" -#define COR_SECURITYCRITICAL_ATTRIBUTE "SecurityCriticalAttribute" -#define COR_SECURITYTRANSPARENT_ATTRIBUTE_NAMESPACE "System.Security" -#define COR_SECURITYTRANSPARENT_ATTRIBUTE "SecurityTransparentAttribute" -#define COR_SECURITYTREATASSAFE_ATTRIBUTE_NAMESPACE "System.Security" -#define COR_SECURITYTREATASSAFE_ATTRIBUTE "SecurityTreatAsSafeAttribute" -#define COR_SECURITYSAFECRITICAL_ATTRIBUTE "SecuritySafeCriticalAttribute" - - -#define COR_SECURITYCRITICAL_ATTRIBUTE_VALUE_EVERYTHING { 0x01, 0x00 ,0x01, 0x00, 0x00, 0x00 ,0x00, 0x00 } -#define COR_SECURITYCRITICAL_ATTRIBUTE_VALUE_EXPLICIT {0x01, 0x00, 0x00 ,0x00} -#define COR_SECURITYTREATASSAFE_ATTRIBUTE_VALUE {0x01, 0x00, 0x00 ,0x00} - - - // if true, then registry has been read for enabling or disabling SecurityCritical support -static BOOL g_fRefShouldMergeCriticalChecked = FALSE; - -// by default, security critical attributes will be merged (e.g. unmarked CRT marked Critical/TAS) -// - unless registry config explicitly disables merging -static BOOL g_fRefShouldMergeCritical = TRUE; -//***************************************************************************** -// END: Security Critical Attributes and Enumeration -//***************************************************************************** - -//***************************************************************************** -// Checks to see if the given type is managed or native. We'll key off of the -// Custom Attribute "Microsoft.VisualC.MiscellaneousBitsAttribute". If the third -// byte has the 01000000 bit set then it is an unmanaged type. -// If we can't find the attribute, we will also check for the presence of the -// "System.Runtime.CompilerServices.NativeCppClassAttribute" Custom Attribute -// since the CPP compiler stopped emitting MiscellaneousBitsAttribute in Dev11. -//***************************************************************************** -HRESULT IsManagedType(CMiniMdRW* pMiniMd, - mdTypeDef td, - BOOL *fIsManagedType) -{ - // First look for the custom attribute - HENUMInternal hEnum; - HRESULT hr = S_OK; - - IfFailRet(pMiniMd->CommonEnumCustomAttributeByName(td, COR_MISCBITS_ATTRIBUTE, false, &hEnum)); - - // If there aren't any custom attributes here, then this must be a managed type - if (hEnum.m_ulCount > 0) - { - // Let's loop through these, and see if any of them have that magical bit set. - mdCustomAttribute ca; - CustomAttributeRec *pRec; - ULONG cbData = 0; - - while(HENUMInternal::EnumNext(&hEnum, &ca)) - { - const BYTE* pData = NULL; - - IfFailGo(pMiniMd->GetCustomAttributeRecord(RidFromToken(ca), &pRec)); - IfFailGo(pMiniMd->getValueOfCustomAttribute(pRec, &pData, &cbData)); - - if (pData != NULL && cbData >=3) - { - // See if the magical bit is set to make this an unmanaged type - if ((*(pData+2)&0x40) > 0) - { - // Yes, this is an unmanaged type - HENUMInternal::ClearEnum(&hEnum); - *fIsManagedType = FALSE; - return S_OK; - } - } - } - - } - - HENUMInternal::ClearEnum(&hEnum); - - // If this was emitted by a Dev11+ CPP compiler, we only have NativeCppClassAttribute - // so let's check for that before calling this a managed class. - IfFailRet(pMiniMd->CommonEnumCustomAttributeByName(td, COR_NATIVECPPCLASS_ATTRIBUTE, false, &hEnum)); - if (hEnum.m_ulCount > 0) - { - // Yes, this is an unmanaged type - HENUMInternal::ClearEnum(&hEnum); - *fIsManagedType = FALSE; - return S_OK; - } - - // Nope, this isn't an unmanaged type.... must be managed - HENUMInternal::ClearEnum(&hEnum); - *fIsManagedType = TRUE; - hr = S_OK; -ErrExit: - return hr; -}// IsManagedType - - -//***************************************************************************** -// "Is CustomAttribute from certain namespace and assembly" check helper -// Returns S_OK and fills **ppTypeRefRec. -// Returns error code or S_FALSE otherwise as not found and fills **ppTypeRefRec with NULL. -//***************************************************************************** -HRESULT IsAttributeFromNamespace( - CMiniMdRW *pMiniMd, - mdToken tk, - LPCSTR szNamespace, - LPCSTR szAssembly, - TypeRefRec **ppTypeRefRec) -{ - HRESULT hr = S_OK; - if(TypeFromToken(tk) == mdtMemberRef) - { - MemberRefRec *pMemRefRec; - IfFailGo(pMiniMd->GetMemberRefRecord(RidFromToken(tk), &pMemRefRec)); - tk = pMiniMd->getClassOfMemberRef(pMemRefRec); - } - if(TypeFromToken(tk) == mdtTypeRef) - { - TypeRefRec *pTypeRefRec; - IfFailGo(pMiniMd->GetTypeRefRecord(RidFromToken(tk), &pTypeRefRec)); - LPCSTR szTypeRefNamespace; - IfFailGo(pMiniMd->getNamespaceOfTypeRef(pTypeRefRec, &szTypeRefNamespace)); - if (strcmp(szTypeRefNamespace, szNamespace) == 0) - { - mdToken tkResTmp = pMiniMd->getResolutionScopeOfTypeRef(pTypeRefRec); - if (TypeFromToken(tkResTmp) == mdtAssemblyRef) - { - AssemblyRefRec *pAsmRefRec; - IfFailGo(pMiniMd->GetAssemblyRefRecord(RidFromToken(tkResTmp), &pAsmRefRec)); - LPCSTR szAssemblyRefName; - IfFailGo(pMiniMd->getNameOfAssemblyRef(pAsmRefRec, &szAssemblyRefName)); - if(SString::_stricmp(szAssemblyRefName, szAssembly) == 0) - { - *ppTypeRefRec = pTypeRefRec; - return S_OK; - } - } - } - } - // Record not found - hr = S_FALSE; -ErrExit: - *ppTypeRefRec = NULL; - return hr; -} - -//***************************************************************************** -// constructor -//***************************************************************************** -NEWMERGER::NEWMERGER() - : m_pRegMetaEmit(0), - m_pImportDataList(NULL), - m_optimizeRefToDef(MDRefToDefDefault), - m_isscsSecurityCritical(ISSCS_Unknown), - m_isscsSecurityCriticalAllScopes(~ISSCS_Unknown) -{ - m_pImportDataTail = &(m_pImportDataList); -#if _DEBUG - m_iImport = 0; -#endif // _DEBUG -} // NEWMERGER::NEWMERGER() - -//***************************************************************************** -// initializer -//***************************************************************************** -HRESULT NEWMERGER::Init(RegMeta *pRegMeta) -{ - HRESULT hr = NOERROR; - MergeTypeData * pMTD; - - m_pRegMetaEmit = pRegMeta; - - // burn an entry so that the RID matches the array index - IfNullGo(pMTD = m_rMTDs.Append()); - - pMTD->m_bSuppressMergeCheck = false; - pMTD->m_cMethods = 0; - pMTD->m_cFields = 0; - pMTD->m_cEvents = 0; - pMTD->m_cProperties = 0; - -ErrExit: - return hr; -} // NEWMERGER::Init - -//***************************************************************************** -// destructor -//***************************************************************************** -NEWMERGER::~NEWMERGER() -{ - if (m_pImportDataList) - { - // delete this list and release all AddRef'ed interfaces! - MergeImportData *pNext; - for (pNext = m_pImportDataList; pNext != NULL; ) - { - pNext = m_pImportDataList->m_pNextImportData; - if (m_pImportDataList->m_pHandler) - m_pImportDataList->m_pHandler->Release(); - if (m_pImportDataList->m_pHostMapToken) - m_pImportDataList->m_pHostMapToken->Release(); - if (m_pImportDataList->m_pMDTokenMap) - delete m_pImportDataList->m_pMDTokenMap; - m_pImportDataList->m_pRegMetaImport->Release(); - delete m_pImportDataList; - m_pImportDataList = pNext; - } - } -} // NEWMERGER::~NEWMERGER - -//***************************************************************************** -CMiniMdRW *NEWMERGER::GetMiniMdEmit() -{ - return &(m_pRegMetaEmit->m_pStgdb->m_MiniMd); -} // CMiniMdRW *NEWMERGER::GetMiniMdEmit() - -//***************************************************************************** -// Adding a new import -//***************************************************************************** -HRESULT NEWMERGER::AddImport( - IMetaDataImport2 *pImport, // [IN] The scope to be merged. - IMapToken *pHostMapToken, // [IN] Host IMapToken interface to receive token remap notification - IUnknown *pHandler) // [IN] An object to receive error notification. -{ - HRESULT hr = NOERROR; - MergeImportData *pData; - - RegMeta *pRM = static_cast<RegMeta*>(pImport); - - // Add a MergeImportData to track the information for this import scope - pData = new (nothrow) MergeImportData; - IfNullGo( pData ); - pData->m_pRegMetaImport = pRM; - pData->m_pRegMetaImport->AddRef(); - pData->m_pHostMapToken = pHostMapToken; - if (pData->m_pHostMapToken) - pData->m_pHostMapToken->AddRef(); - if (pHandler) - { - pData->m_pHandler = pHandler; - pData->m_pHandler->AddRef(); - } - else - { - pData->m_pHandler = NULL; - } - - pData->m_pMDTokenMap = NULL; - pData->m_pNextImportData = NULL; -#if _DEBUG - pData->m_iImport = ++m_iImport; -#endif // _DEBUG - - pData->m_tkHandleProcessCorruptedStateCtor = mdTokenNil; - // add the newly create node to the tail of the list - *m_pImportDataTail = pData; - m_pImportDataTail = &(pData->m_pNextImportData); - -ErrExit: - - return hr; -} // HRESULT NEWMERGER::AddImport() - -HRESULT NEWMERGER::InitMergeTypeData() -{ - CMiniMdRW *pMiniMdEmit; - ULONG cTypeDefRecs; - ULONG i, j; - bool bSuppressMergeCheck; - - ULONG ridStart, ridEnd; - RID ridMap; - - mdToken tkSuppressMergeCheckCtor = mdTokenNil; - mdToken tkCA; - mdMethodDef mdEmit; - mdFieldDef fdEmit; - mdEvent evEmit; - mdProperty prEmit; - - TypeDefRec *pTypeDefRec; - EventMapRec *pEventMapRec; - PropertyMapRec *pPropertyMapRec; - - MergeTypeData *pMTD; - - HRESULT hr = NOERROR; - - pMiniMdEmit = GetMiniMdEmit(); - - // cache the SuppressMergeCheckAttribute.ctor token - ImportHelper::FindCustomAttributeCtorByName( - pMiniMdEmit, COR_MSCORLIB_NAME, - COR_COMPILERSERVICE_NAMESPACE, COR_SUPPRESS_MERGE_CHECK_ATTRIBUTE, - &tkSuppressMergeCheckCtor); - - cTypeDefRecs = pMiniMdEmit->getCountTypeDefs(); - _ASSERTE(m_rMTDs.Count() > 0); - - for (i = m_rMTDs.Count(); i <= cTypeDefRecs; i++) - { - IfNullGo(pMTD = m_rMTDs.Append()); - - pMTD->m_cMethods = 0; - pMTD->m_cFields = 0; - pMTD->m_cEvents = 0; - pMTD->m_cProperties = 0; - pMTD->m_bSuppressMergeCheck = (tkSuppressMergeCheckCtor != mdTokenNil) && - (S_OK == ImportHelper::FindCustomAttributeByToken(pMiniMdEmit, - TokenFromRid(i, mdtTypeDef), tkSuppressMergeCheckCtor, - NULL, 0, &tkCA)); - - IfFailGo(pMiniMdEmit->GetTypeDefRecord(i, &pTypeDefRec)); - - // Count the number methods - ridStart = pMiniMdEmit->getMethodListOfTypeDef(pTypeDefRec); - IfFailGo(pMiniMdEmit->getEndMethodListOfTypeDef(i, &ridEnd)); - - for (j = ridStart; j < ridEnd; j++) - { - IfFailGo(pMiniMdEmit->GetMethodRid(j, (ULONG *)&mdEmit)); - bSuppressMergeCheck = pMTD->m_bSuppressMergeCheck || - ((tkSuppressMergeCheckCtor != mdTokenNil) && - (S_OK == ImportHelper::FindCustomAttributeByToken(pMiniMdEmit, - mdEmit, tkSuppressMergeCheckCtor, NULL, 0, &tkCA))); - - if (!bSuppressMergeCheck) - { - pMTD->m_cMethods++; - } - } - - // Count the number fields - ridStart = pMiniMdEmit->getFieldListOfTypeDef(pTypeDefRec); - IfFailGo(pMiniMdEmit->getEndFieldListOfTypeDef(i, &ridEnd)); - - for (j = ridStart; j < ridEnd; j++) - { - IfFailGo(pMiniMdEmit->GetFieldRid(j, (ULONG *)&fdEmit)); - bSuppressMergeCheck = pMTD->m_bSuppressMergeCheck || - ((tkSuppressMergeCheckCtor != mdTokenNil) && - (S_OK == ImportHelper::FindCustomAttributeByToken(pMiniMdEmit, - fdEmit, tkSuppressMergeCheckCtor, NULL, 0, &tkCA))); - - if (!bSuppressMergeCheck) - { - pMTD->m_cFields++; - } - } - - // Count the number of events - IfFailGo(pMiniMdEmit->FindEventMapFor(i, &ridMap)); - if (!InvalidRid(ridMap)) - { - IfFailGo(pMiniMdEmit->GetEventMapRecord(ridMap, &pEventMapRec)); - ridStart = pMiniMdEmit->getEventListOfEventMap(pEventMapRec); - IfFailGo(pMiniMdEmit->getEndEventListOfEventMap(ridMap, &ridEnd)); - - for (j = ridStart; j < ridEnd; j++) - { - IfFailGo(pMiniMdEmit->GetEventRid(j, (ULONG *)&evEmit)); - bSuppressMergeCheck = pMTD->m_bSuppressMergeCheck || - ((tkSuppressMergeCheckCtor != mdTokenNil) && - (S_OK == ImportHelper::FindCustomAttributeByToken(pMiniMdEmit, - evEmit, tkSuppressMergeCheckCtor, NULL, 0, &tkCA))); - - if (!bSuppressMergeCheck) - { - pMTD->m_cEvents++; - } - } - } - - // Count the number of properties - IfFailGo(pMiniMdEmit->FindPropertyMapFor(i, &ridMap)); - if (!InvalidRid(ridMap)) - { - IfFailGo(pMiniMdEmit->GetPropertyMapRecord(ridMap, &pPropertyMapRec)); - ridStart = pMiniMdEmit->getPropertyListOfPropertyMap(pPropertyMapRec); - IfFailGo(pMiniMdEmit->getEndPropertyListOfPropertyMap(ridMap, &ridEnd)); - - for (j = ridStart; j < ridEnd; j++) - { - IfFailGo(pMiniMdEmit->GetPropertyRid(j, (ULONG *)&prEmit)); - bSuppressMergeCheck = pMTD->m_bSuppressMergeCheck || - ((tkSuppressMergeCheckCtor != mdTokenNil) && - (S_OK == ImportHelper::FindCustomAttributeByToken(pMiniMdEmit, - prEmit, tkSuppressMergeCheckCtor, NULL, 0, &tkCA))); - - if (!bSuppressMergeCheck) - { - pMTD->m_cProperties++; - } - } - } - } - -ErrExit: - return hr; -} - -//***************************************************************************** -// Merge now -//***************************************************************************** -HRESULT NEWMERGER::Merge(MergeFlags dwMergeFlags, CorRefToDefCheck optimizeRefToDef) -{ - MergeImportData *pImportData = m_pImportDataList; - MDTOKENMAP **pPrevMap = NULL; - MDTOKENMAP *pMDTokenMap; - HRESULT hr = NOERROR; - MDTOKENMAP *pCurTKMap; - int i; - -#if _DEBUG - { - LOG((LOGMD, "++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n")); - LOG((LOGMD, "Merge scope list\n")); - i = 0; - for (MergeImportData *pID = m_pImportDataList; pID != NULL; pID = pID->m_pNextImportData) - { - WCHAR szScope[1024], szGuid[40]; - GUID mvid; - ULONG cchScope; - pID->m_pRegMetaImport->GetScopeProps(szScope, 1024, &cchScope, &mvid); - szScope[1023] = 0; - GuidToLPWSTR(mvid, szGuid, 40); - ++i; // Counter is 1-based. - LOG((LOGMD, "%3d: %ls : %ls\n", i, szGuid, szScope)); - } - LOG((LOGMD, "++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n")); - } -#endif // _DEBUG - - m_dwMergeFlags = dwMergeFlags; - m_optimizeRefToDef = optimizeRefToDef; - - // check to see if we need to do dup check - m_fDupCheck = ((m_dwMergeFlags & NoDupCheck) != NoDupCheck); - - while (pImportData) - { - // Verify that we have a filter for each import scope. - IfNullGo( pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd.GetFilterTable() ); - - // cache the SuppressMergeCheckAttribute.ctor token for each import scope - ImportHelper::FindCustomAttributeCtorByName( - &pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd, COR_MSCORLIB_NAME, - COR_COMPILERSERVICE_NAMESPACE, COR_SUPPRESS_MERGE_CHECK_ATTRIBUTE, - &pImportData->m_tkSuppressMergeCheckCtor); - - // cache the HandleProcessCorruptedStateExceptionsAttribute.ctor token for each import scope - ImportHelper::FindCustomAttributeCtorByName( - &pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd, COR_MSCORLIB_NAME, - COR_EXCEPTIONSERVICE_NAMESPACE, COR_HANDLE_PROCESS_CORRUPTED_STATE_EXCEPTION_ATTRIBUTE, - &pImportData->m_tkHandleProcessCorruptedStateCtor); - - // check for security critical attribute in the assembly (i.e. explicit annotations) - InputScopeSecurityCriticalStatus isscsTemp = CheckInputScopeIsCritical(pImportData, hr); - IfFailGo(hr); - // clear the unset flag bits (e.g. if critical, clear transparent bit) - // whatever bits remain are bits that have been set in all scopes - if (ISSCS_Unknown == (isscsTemp & ISSCS_SECURITYCRITICAL_FLAGS)) - m_isscsSecurityCriticalAllScopes &= ISSCS_SECURITYCRITICAL_LEGACY; - else - m_isscsSecurityCriticalAllScopes &= isscsTemp; - // set the flag bits (essentially, this allows us to see if _any_ scopes requested a bit) - m_isscsSecurityCritical |= isscsTemp; - - // create the tokenmap class to track metadata token remap for each import scope - pMDTokenMap = new (nothrow) MDTOKENMAP; - IfNullGo(pMDTokenMap); - IfFailGo(pMDTokenMap->Init((IMetaDataImport2*)pImportData->m_pRegMetaImport)); - pImportData->m_pMDTokenMap = pMDTokenMap; - pImportData->m_pMDTokenMap->m_pMap = pImportData->m_pHostMapToken; - if (pImportData->m_pHostMapToken) - pImportData->m_pHostMapToken->AddRef(); - pImportData->m_pMDTokenMap->m_pNextMap = NULL; - if (pPrevMap) - *pPrevMap = pImportData->m_pMDTokenMap; - pPrevMap = &(pImportData->m_pMDTokenMap->m_pNextMap); - pImportData = pImportData->m_pNextImportData; - } - - // Populate the m_rMTDs with the type info already defined in the emit scope - IfFailGo( InitMergeTypeData() ); - - // 1. Merge Module - IfFailGo( MergeModule( ) ); - - // 2. Merge TypeDef partially (i.e. only name) - IfFailGo( MergeTypeDefNamesOnly() ); - - // 3. Merge ModuleRef property and do ModuleRef to ModuleDef optimization - IfFailGo( MergeModuleRefs() ); - - // 4. Merge AssemblyRef. - IfFailGo( MergeAssemblyRefs() ); - - // 5. Merge TypeRef with TypeRef to TypeDef optimization - IfFailGo( MergeTypeRefs() ); - - // 6. Merge TypeSpec & MethodSpec - IfFailGo( MergeTypeSpecs() ); - - // 7. Now Merge the remaining of TypeDef records - IfFailGo( CompleteMergeTypeDefs() ); - - // 8. Merge Methods and Fields. Such that Signature translation is respecting the TypeRef to TypeDef optimization. - IfFailGo( MergeTypeDefChildren() ); - - // 9. Merge MemberRef with MemberRef to MethodDef/FieldDef optimization - IfFailGo( MergeMemberRefs( ) ); - - // 10. Merge InterfaceImpl - IfFailGo( MergeInterfaceImpls( ) ); - - // merge all of the remaining in metadata .... - - // 11. constant has dependency on property, field, param - IfFailGo( MergeConstants() ); - - // 12. field marshal has dependency on param and field - IfFailGo( MergeFieldMarshals() ); - - // 13. in ClassLayout, move over the FieldLayout and deal with FieldLayout as well - IfFailGo( MergeClassLayouts() ); - - // 14. FieldLayout has dependency on FieldDef. - IfFailGo( MergeFieldLayouts() ); - - // 15. FieldRVA has dependency on FieldDef. - IfFailGo( MergeFieldRVAs() ); - - // 16. MethodImpl has dependency on MemberRef, MethodDef, TypeRef and TypeDef. - IfFailGo( MergeMethodImpls() ); - - // 17. pinvoke depends on MethodDef and ModuleRef - IfFailGo( MergePinvoke() ); - - IfFailGo( MergeStandAloneSigs() ); - - IfFailGo( MergeMethodSpecs() ); - - IfFailGo( MergeStrings() ); - - if (m_dwMergeFlags & MergeManifest) - { - // keep the manifest!! - IfFailGo( MergeAssembly() ); - IfFailGo( MergeFiles() ); - IfFailGo( MergeExportedTypes() ); - IfFailGo( MergeManifestResources() ); - } - else if (m_dwMergeFlags & ::MergeExportedTypes) - { - IfFailGo( MergeFiles() ); - IfFailGo( MergeExportedTypes() ); - } - - IfFailGo( MergeCustomAttributes() ); - IfFailGo( MergeDeclSecuritys() ); - - - // Please don't add any MergeXxx() below here. CustomAttributess must be - // very late, because custom values are various other types. - - // Fixup list cannot be merged. Linker will need to re-emit them. - - // Now call back to host for the result of token remap - // - for (pImportData = m_pImportDataList; pImportData != NULL; pImportData = pImportData->m_pNextImportData) - { - // Send token remap information for each import scope - pCurTKMap = pImportData->m_pMDTokenMap; - TOKENREC *pRec; - if (pImportData->m_pHostMapToken) - { - for (i = 0; i < pCurTKMap->Count(); i++) - { - pRec = pCurTKMap->Get(i); - if (!pRec->IsEmpty()) - pImportData->m_pHostMapToken->Map(pRec->m_tkFrom, pRec->m_tkTo); - } - } - } - - // And last, but not least, let's do Security critical module-level attribute consolidation - // and metadata fixups. - IfFailGo( MergeSecurityCriticalAttributes() ); - - - - - -#if _DEBUG - for (pImportData = m_pImportDataList; pImportData != NULL; pImportData = pImportData->m_pNextImportData) - { - // dump the mapping - LOG((LOGMD, "++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n")); - LOG((LOGMD, "Dumping token remap for one import scope!\n")); - LOG((LOGMD, "This is the %d import scope for merge!\n", pImportData->m_iImport)); - - pCurTKMap = pImportData->m_pMDTokenMap; - TOKENREC *pRec; - for (i = 0; i < pCurTKMap->Count(); i++) - { - pRec = pCurTKMap->Get(i); - if (!pRec->IsEmpty()) - { - LOG((LOGMD, " Token 0x%08x ====>>>> Token 0x%08x\n", pRec->m_tkFrom, pRec->m_tkTo)); - } - } - LOG((LOGMD, "End dumping token remap!\n")); - LOG((LOGMD, "++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n")); - } -#endif // _DEBUG - -ErrExit: - return hr; -} // HRESULT NEWMERGER::Merge() - - -//***************************************************************************** -// Merge ModuleDef -//***************************************************************************** -HRESULT NEWMERGER::MergeModule() -{ - MergeImportData *pImportData; - MDTOKENMAP *pCurTkMap; - HRESULT hr = NOERROR; - TOKENREC *pTokenRec; - - // we don't really merge Module information but we create a one to one mapping for each module token into the TokenMap - for (pImportData = m_pImportDataList; pImportData != NULL; pImportData = pImportData->m_pNextImportData) - { - // for each import scope - // set the current MDTokenMap - - pCurTkMap = pImportData->m_pMDTokenMap; - IfFailGo( pCurTkMap->InsertNotFound(MODULEDEFTOKEN, true, MODULEDEFTOKEN, &pTokenRec) ); - } -ErrExit: - return hr; -} // HRESULT NEWMERGER::MergeModule() - - -//***************************************************************************** -// Merge TypeDef but only Names. This is a partial merge to support TypeRef to TypeDef optimization -//***************************************************************************** -HRESULT NEWMERGER::MergeTypeDefNamesOnly() -{ - HRESULT hr = NOERROR; - TypeDefRec *pRecImport = NULL; - TypeDefRec *pRecEmit = NULL; - CMiniMdRW *pMiniMdImport; - CMiniMdRW *pMiniMdEmit; - ULONG iCount; - ULONG i; - mdTypeDef tdEmit; - mdTypeDef tdImport; - bool bDuplicate; - DWORD dwFlags; - DWORD dwExportFlags; - NestedClassRec *pNestedRec; - RID iNestedRec; - mdTypeDef tdNester; - TOKENREC *pTokenRec; - - LPCUTF8 szNameImp; - LPCUTF8 szNamespaceImp; - - MergeImportData *pImportData; - MDTOKENMAP *pCurTkMap; - - MergeTypeData *pMTD; - BOOL bSuppressMergeCheck; - mdCustomAttribute tkCA; - - pMiniMdEmit = GetMiniMdEmit(); - - for (pImportData = m_pImportDataList; pImportData != NULL; pImportData = pImportData->m_pNextImportData) - { - // for each import scope - pMiniMdImport = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - - // We know that the filter table is not null here. Tell PREFIX that we know it. - PREFIX_ASSUME( pMiniMdImport->GetFilterTable() != NULL ); - - // set the current MDTokenMap - pCurTkMap = pImportData->m_pMDTokenMap; - - iCount = pMiniMdImport->getCountTypeDefs(); - - // Merge the typedefs - for (i = 1; i <= iCount; i++) - { - // only merge those TypeDefs that are marked - if ( pMiniMdImport->GetFilterTable()->IsTypeDefMarked(TokenFromRid(i, mdtTypeDef)) == false) - continue; - - // compare it with the emit scope - IfFailGo(pMiniMdImport->GetTypeDefRecord(i, &pRecImport)); - IfFailGo(pMiniMdImport->getNameOfTypeDef(pRecImport, &szNameImp)); - IfFailGo(pMiniMdImport->getNamespaceOfTypeDef(pRecImport, &szNamespaceImp)); - - // If the class is a Nested class, get the parent token. - dwFlags = pMiniMdImport->getFlagsOfTypeDef(pRecImport); - if (IsTdNested(dwFlags)) - { - IfFailGo(pMiniMdImport->FindNestedClassHelper(TokenFromRid(i, mdtTypeDef), &iNestedRec)); - if (InvalidRid(iNestedRec)) - { - _ASSERTE(!"Bad state!"); - IfFailGo(META_E_BADMETADATA); - } - else - { - IfFailGo(pMiniMdImport->GetNestedClassRecord(iNestedRec, &pNestedRec)); - tdNester = pMiniMdImport->getEnclosingClassOfNestedClass(pNestedRec); - _ASSERTE(!IsNilToken(tdNester)); - IfFailGo(pCurTkMap->Remap(tdNester, &tdNester)); - } - } - else - tdNester = mdTokenNil; - - bSuppressMergeCheck = (pImportData->m_tkSuppressMergeCheckCtor != mdTokenNil) && - (S_OK == ImportHelper::FindCustomAttributeByToken(pMiniMdImport, - TokenFromRid(i, mdtTypeDef), pImportData->m_tkSuppressMergeCheckCtor, - NULL, 0, &tkCA)); - - // does this TypeDef already exist in the emit scope? - if ( ImportHelper::FindTypeDefByName( - pMiniMdEmit, - szNamespaceImp, - szNameImp, - tdNester, - &tdEmit) == S_OK ) - { - // Yes, it does - bDuplicate = true; - - // Let's look at their accessiblities. - IfFailGo(pMiniMdEmit->GetTypeDefRecord(RidFromToken(tdEmit), &pRecEmit)); - dwExportFlags = pMiniMdEmit->getFlagsOfTypeDef(pRecEmit); - - // Managed types need to have the same accessiblity - BOOL fManagedType = FALSE; - IfFailGo(IsManagedType(pMiniMdImport, TokenFromRid(i, mdtTypeDef), &fManagedType)); - if (fManagedType) - { - if ((dwFlags&tdVisibilityMask) != (dwExportFlags&tdVisibilityMask)) - { - CheckContinuableErrorEx(META_E_MISMATCHED_VISIBLITY, pImportData, TokenFromRid(i, mdtTypeDef)); - } - - } - pMTD = m_rMTDs.Get(RidFromToken(tdEmit)); - if (pMTD->m_bSuppressMergeCheck != bSuppressMergeCheck) - { - CheckContinuableErrorEx(META_E_MD_INCONSISTENCY, pImportData, TokenFromRid(i, mdtTypeDef)); - } - } - else - { - // No, it doesn't. Copy it over. - bDuplicate = false; - IfFailGo(pMiniMdEmit->AddTypeDefRecord(&pRecEmit, (RID *)&tdEmit)); - - // make sure the index matches - _ASSERTE(((mdTypeDef)m_rMTDs.Count()) == tdEmit); - - IfNullGo(pMTD = m_rMTDs.Append()); - - pMTD->m_cMethods = 0; - pMTD->m_cFields = 0; - pMTD->m_cEvents = 0; - pMTD->m_cProperties = 0; - pMTD->m_bSuppressMergeCheck = bSuppressMergeCheck; - - tdEmit = TokenFromRid( tdEmit, mdtTypeDef ); - - // Set Full Qualified Name. - IfFailGo( CopyTypeDefPartially( pRecEmit, pMiniMdImport, pRecImport) ); - - // Create a NestedClass record if the class is a Nested class. - if (! IsNilToken(tdNester)) - { - IfFailGo(pMiniMdEmit->AddNestedClassRecord(&pNestedRec, &iNestedRec)); - - // copy over the information - IfFailGo( pMiniMdEmit->PutToken(TBL_NestedClass, NestedClassRec::COL_NestedClass, - pNestedRec, tdEmit)); - - // tdNester has already been remapped above to the Emit scope. - IfFailGo( pMiniMdEmit->PutToken(TBL_NestedClass, NestedClassRec::COL_EnclosingClass, - pNestedRec, tdNester)); - IfFailGo( pMiniMdEmit->AddNestedClassToHash(iNestedRec) ); - - } - } - - // record the token movement - tdImport = TokenFromRid(i, mdtTypeDef); - IfFailGo( pCurTkMap->InsertNotFound(tdImport, bDuplicate, tdEmit, &pTokenRec) ); - } - } - -ErrExit: - return hr; -} // HRESULT NEWMERGER::MergeTypeDefNamesOnly() - - -//***************************************************************************** -// Merge EnclosingType tables -//***************************************************************************** -HRESULT NEWMERGER::CopyTypeDefPartially( - TypeDefRec *pRecEmit, // [IN] the emit record to fill - CMiniMdRW *pMiniMdImport, // [IN] the importing scope - TypeDefRec *pRecImp) // [IN] the record to import - -{ - HRESULT hr; - LPCUTF8 szNameImp; - LPCUTF8 szNamespaceImp; - CMiniMdRW *pMiniMdEmit = GetMiniMdEmit(); - - IfFailGo(pMiniMdImport->getNameOfTypeDef(pRecImp, &szNameImp)); - IfFailGo(pMiniMdImport->getNamespaceOfTypeDef(pRecImp, &szNamespaceImp)); - - IfFailGo( pMiniMdEmit->PutString( TBL_TypeDef, TypeDefRec::COL_Name, pRecEmit, szNameImp) ); - IfFailGo( pMiniMdEmit->PutString( TBL_TypeDef, TypeDefRec::COL_Namespace, pRecEmit, szNamespaceImp) ); - - pRecEmit->SetFlags(pRecImp->GetFlags()); - - // Don't copy over the extends until TypeRef's remap is calculated - -ErrExit: - return hr; - -} // HRESULT NEWMERGER::CopyTypeDefPartially() - - -//***************************************************************************** -// Merge ModuleRef tables including ModuleRef to ModuleDef optimization -//***************************************************************************** -HRESULT NEWMERGER::MergeModuleRefs() -{ - HRESULT hr = NOERROR; - ModuleRefRec *pRecImport = NULL; - ModuleRefRec *pRecEmit = NULL; - CMiniMdRW *pMiniMdImport; - CMiniMdRW *pMiniMdEmit; - ULONG iCount; - ULONG i; - mdModuleRef mrEmit; - bool bDuplicate = false; - TOKENREC *pTokenRec; - LPCUTF8 szNameImp; - bool isModuleDef; - - MergeImportData *pImportData; - MergeImportData *pData; - MDTOKENMAP *pCurTkMap; - - pMiniMdEmit = GetMiniMdEmit(); - - for (pImportData = m_pImportDataList; pImportData != NULL; pImportData = pImportData->m_pNextImportData) - { - // for each import scope - pMiniMdImport = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - - // We know that the filter table is not null here. Tell PREFIX that we know it. - PREFIX_ASSUME( pMiniMdImport->GetFilterTable() != NULL ); - - // set the current MDTokenMap - pCurTkMap = pImportData->m_pMDTokenMap; - iCount = pMiniMdImport->getCountModuleRefs(); - - // loop through all ModuleRef - for (i = 1; i <= iCount; i++) - { - // only merge those ModuleRefs that are marked - if ( pMiniMdImport->GetFilterTable()->IsModuleRefMarked(TokenFromRid(i, mdtModuleRef)) == false) - continue; - - isModuleDef = false; - - // compare it with the emit scope - IfFailGo(pMiniMdImport->GetModuleRefRecord(i, &pRecImport)); - IfFailGo(pMiniMdImport->getNameOfModuleRef(pRecImport, &szNameImp)); - - // Only do the ModuleRef to ModuleDef optimization if ModuleRef's name is meaningful! - if ( szNameImp && szNameImp[0] != '\0') - { - - // Check to see if this ModuleRef has become the ModuleDef token - for (pData = m_pImportDataList; pData != NULL; pData = pData->m_pNextImportData) - { - CMiniMdRW *pMiniMd = &(pData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - ModuleRec *pRec; - LPCUTF8 szName; - - IfFailGo(pMiniMd->GetModuleRecord(MODULEDEFTOKEN, &pRec)); - IfFailGo(pMiniMd->getNameOfModule(pRec, &szName)); - if (szName && szName[0] != '\0' && strcmp(szNameImp, szName) == 0) - { - // We found an import Module for merging that has the same name as the ModuleRef - isModuleDef = true; - bDuplicate = true; - mrEmit = MODULEDEFTOKEN; // set the resulting token to ModuleDef Token - break; - } - } - } - - if (isModuleDef == false) - { - // does this ModuleRef already exist in the emit scope? - hr = ImportHelper::FindModuleRef(pMiniMdEmit, - szNameImp, - &mrEmit); - if (hr == S_OK) - { - // Yes, it does - bDuplicate = true; - } - else if (hr == CLDB_E_RECORD_NOTFOUND) - { - // No, it doesn't. Copy it over. - bDuplicate = false; - IfFailGo(pMiniMdEmit->AddModuleRefRecord(&pRecEmit, (RID*)&mrEmit)); - mrEmit = TokenFromRid(mrEmit, mdtModuleRef); - - // Set ModuleRef Name. - IfFailGo( pMiniMdEmit->PutString(TBL_ModuleRef, ModuleRefRec::COL_Name, pRecEmit, szNameImp) ); - } - else - IfFailGo(hr); - } - - // record the token movement - IfFailGo( pCurTkMap->InsertNotFound( - TokenFromRid(i, mdtModuleRef), - bDuplicate, - mrEmit, - &pTokenRec) ); - } - } - -ErrExit: - return hr; -} // HRESULT NEWMERGER::MergeModuleRefs() - - -//***************************************************************************** -// Merge AssemblyRef tables -//***************************************************************************** -HRESULT NEWMERGER::MergeAssemblyRefs() -{ - HRESULT hr = NOERROR; - AssemblyRefRec *pRecImport = NULL; - AssemblyRefRec *pRecEmit = NULL; - CMiniMdRW *pMiniMdImport; - CMiniMdRW *pMiniMdEmit; - mdAssemblyRef arEmit; - bool bDuplicate = false; - LPCUTF8 szTmp; - const void *pbTmp; - ULONG cbTmp; - ULONG iCount; - ULONG i; - ULONG iRecord; - TOKENREC *pTokenRec; - MergeImportData *pImportData; - MDTOKENMAP *pCurTkMap; - - pMiniMdEmit = GetMiniMdEmit(); - - for (pImportData = m_pImportDataList; pImportData != NULL; pImportData = pImportData->m_pNextImportData) - { - // for each import scope - pMiniMdImport = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - - // set the current MDTokenMap - pCurTkMap = pImportData->m_pMDTokenMap; - iCount = pMiniMdImport->getCountAssemblyRefs(); - - // loope through all the AssemblyRefs. - for (i = 1; i <= iCount; i++) - { - // Compare with the emit scope. - IfFailGo(pMiniMdImport->GetAssemblyRefRecord(i, &pRecImport)); - IfFailGo(pMiniMdImport->getPublicKeyOrTokenOfAssemblyRef(pRecImport, (const BYTE **)&pbTmp, &cbTmp)); - hr = CLDB_E_RECORD_NOTFOUND; - if (m_fDupCheck) - { - LPCSTR szAssemblyRefName; - LPCSTR szAssemblyRefLocale; - IfFailGo(pMiniMdImport->getNameOfAssemblyRef(pRecImport, &szAssemblyRefName)); - IfFailGo(pMiniMdImport->getLocaleOfAssemblyRef(pRecImport, &szAssemblyRefLocale)); - hr = ImportHelper::FindAssemblyRef( - pMiniMdEmit, - szAssemblyRefName, - szAssemblyRefLocale, - pbTmp, - cbTmp, - pRecImport->GetMajorVersion(), - pRecImport->GetMinorVersion(), - pRecImport->GetBuildNumber(), - pRecImport->GetRevisionNumber(), - pRecImport->GetFlags(), - &arEmit); - } - if (hr == S_OK) - { - // Yes, it does - bDuplicate = true; - - // <TODO>@FUTURE: more verification?</TODO> - } - else if (hr == CLDB_E_RECORD_NOTFOUND) - { - // No, it doesn't. Copy it over. - bDuplicate = false; - IfFailGo(pMiniMdEmit->AddAssemblyRefRecord(&pRecEmit, &iRecord)); - arEmit = TokenFromRid(iRecord, mdtAssemblyRef); - - pRecEmit->Copy(pRecImport); - - IfFailGo(pMiniMdImport->getPublicKeyOrTokenOfAssemblyRef(pRecImport, (const BYTE **)&pbTmp, &cbTmp)); - IfFailGo(pMiniMdEmit->PutBlob(TBL_AssemblyRef, AssemblyRefRec::COL_PublicKeyOrToken, - pRecEmit, pbTmp, cbTmp)); - - IfFailGo(pMiniMdImport->getNameOfAssemblyRef(pRecImport, &szTmp)); - IfFailGo(pMiniMdEmit->PutString(TBL_AssemblyRef, AssemblyRefRec::COL_Name, - pRecEmit, szTmp)); - - IfFailGo(pMiniMdImport->getLocaleOfAssemblyRef(pRecImport, &szTmp)); - IfFailGo(pMiniMdEmit->PutString(TBL_AssemblyRef, AssemblyRefRec::COL_Locale, - pRecEmit, szTmp)); - - IfFailGo(pMiniMdImport->getHashValueOfAssemblyRef(pRecImport, (const BYTE **)&pbTmp, &cbTmp)); - IfFailGo(pMiniMdEmit->PutBlob(TBL_AssemblyRef, AssemblyRefRec::COL_HashValue, - pRecEmit, pbTmp, cbTmp)); - - } - else - IfFailGo(hr); - - // record the token movement. - IfFailGo(pCurTkMap->InsertNotFound( - TokenFromRid(i, mdtAssemblyRef), - bDuplicate, - arEmit, - &pTokenRec)); - } - } - -ErrExit: - return hr; -} // HRESULT NEWMERGER::MergeAssemblyRefs() - - -//***************************************************************************** -// Merge TypeRef tables also performing TypeRef to TypeDef opitimization. ie. -// we will not introduce a TypeRef record if we can optimize it to a TypeDef. -//***************************************************************************** -HRESULT NEWMERGER::MergeTypeRefs() -{ - HRESULT hr = NOERROR; - TypeRefRec *pRecImport = NULL; - TypeRefRec *pRecEmit = NULL; - CMiniMdRW *pMiniMdImport; - CMiniMdRW *pMiniMdEmit; - ULONG iCount; - ULONG i; - mdTypeRef trEmit; - bool bDuplicate = false; - TOKENREC *pTokenRec; - bool isTypeDef; - - mdToken tkResImp; - mdToken tkResEmit; - LPCUTF8 szNameImp; - LPCUTF8 szNamespaceImp; - - MergeImportData *pImportData; - MDTOKENMAP *pCurTkMap; - - pMiniMdEmit = GetMiniMdEmit(); - - for (pImportData = m_pImportDataList; pImportData != NULL; pImportData = pImportData->m_pNextImportData) - { - // for each import scope - pMiniMdImport = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - - // We know that the filter table is not null here. Tell PREFIX that we know it. - PREFIX_ASSUME( pMiniMdImport->GetFilterTable() != NULL ); - - // set the current MDTokenMap - pCurTkMap = pImportData->m_pMDTokenMap; - iCount = pMiniMdImport->getCountTypeRefs(); - - // loop through all TypeRef - for (i = 1; i <= iCount; i++) - { - // only merge those TypeRefs that are marked - if ( pMiniMdImport->GetFilterTable()->IsTypeRefMarked(TokenFromRid(i, mdtTypeRef)) == false) - continue; - - isTypeDef = false; - - // compare it with the emit scope - IfFailGo(pMiniMdImport->GetTypeRefRecord(i, &pRecImport)); - tkResImp = pMiniMdImport->getResolutionScopeOfTypeRef(pRecImport); - IfFailGo(pMiniMdImport->getNamespaceOfTypeRef(pRecImport, &szNamespaceImp)); - IfFailGo(pMiniMdImport->getNameOfTypeRef(pRecImport, &szNameImp)); - if (!IsNilToken(tkResImp)) - { - IfFailGo(pCurTkMap->Remap(tkResImp, &tkResEmit)); - } - else - { - tkResEmit = tkResImp; - } - - // There are some interesting cases to consider here. - // 1) If the TypeRef's ResolutionScope is a nil token, or is the MODULEDEFTOKEN (current module), - // then the TypeRef refers to a type in the current scope, so we should find a corresponding - // TypeDef in the output scope. If we find the TypeDef, we'll remap this TypeRef token - // to that TypeDef token. - // If we don't find that TypeDef, or if "TypeRef to TypeDef" optimization is turned off, we'll - // create the TypeRef in the output scope. - // 2) If the TypeRef's ResolutionScope has been resolved to a TypeDef, then this TypeRef was part - // of a nested type definition. In that case, we'd better find a corresponding TypeDef - // or we have an error. - if (IsNilToken(tkResEmit) || tkResEmit == MODULEDEFTOKEN || TypeFromToken(tkResEmit) == mdtTypeDef) - { - hr = ImportHelper::FindTypeDefByName( - pMiniMdEmit, - szNamespaceImp, - szNameImp, - (TypeFromToken(tkResEmit) == mdtTypeDef) ? tkResEmit : mdTokenNil, - &trEmit); - if (hr == S_OK) - { - isTypeDef = true; - - // it really does not matter if we set the duplicate to true or false. - bDuplicate = true; - } - } - - // If the ResolutionScope was merged as a TypeDef, and this token wasn't found as TypeDef, send the error. - if (TypeFromToken(tkResEmit) == mdtTypeDef && !isTypeDef) - { - // Send the error notification. Use the "continuable error" callback, but even if linker says it is - // ok, don't continue. - CheckContinuableErrorEx(META_E_TYPEDEF_MISSING, pImportData, TokenFromRid(i, mdtTypeRef)); - IfFailGo(META_E_TYPEDEF_MISSING); - } - - // If this TypeRef cannot be optmized to a TypeDef or the Ref to Def optimization is turned off, do the following. - if (!isTypeDef || !((m_optimizeRefToDef & MDTypeRefToDef) == MDTypeRefToDef)) - { - // does this TypeRef already exist in the emit scope? - if ( m_fDupCheck && ImportHelper::FindTypeRefByName( - pMiniMdEmit, - tkResEmit, - szNamespaceImp, - szNameImp, - &trEmit) == S_OK ) - { - // Yes, it does - bDuplicate = true; - } - else - { - // No, it doesn't. Copy it over. - bDuplicate = false; - IfFailGo(pMiniMdEmit->AddTypeRefRecord(&pRecEmit, (RID*)&trEmit)); - trEmit = TokenFromRid(trEmit, mdtTypeRef); - - // Set ResolutionScope. tkResEmit has already been re-mapped. - IfFailGo(pMiniMdEmit->PutToken(TBL_TypeRef, TypeRefRec::COL_ResolutionScope, - pRecEmit, tkResEmit)); - - // Set Name. - IfFailGo(pMiniMdEmit->PutString(TBL_TypeRef, TypeRefRec::COL_Name, - pRecEmit, szNameImp)); - IfFailGo(pMiniMdEmit->AddNamedItemToHash(TBL_TypeRef, trEmit, szNameImp, 0)); - - // Set Namespace. - IfFailGo(pMiniMdEmit->PutString(TBL_TypeRef, TypeRefRec::COL_Namespace, - pRecEmit, szNamespaceImp)); - } - } - - // record the token movement - IfFailGo( pCurTkMap->InsertNotFound( - TokenFromRid(i, mdtTypeRef), - bDuplicate, - trEmit, - &pTokenRec) ); - } - } - -ErrExit: - return hr; -} // HRESULT NEWMERGER::MergeTypeRefs() - - -//***************************************************************************** -// copy over the remaining information of partially merged TypeDef records. Right now only -// extends field is delayed to here. The reason that we delay extends field is because we want -// to optimize TypeRef to TypeDef if possible. -//***************************************************************************** -HRESULT NEWMERGER::CompleteMergeTypeDefs() -{ - HRESULT hr = NOERROR; - TypeDefRec *pRecImport = NULL; - TypeDefRec *pRecEmit = NULL; - CMiniMdRW *pMiniMdImport; - CMiniMdRW *pMiniMdEmit; - ULONG iCount; - ULONG i; - TOKENREC *pTokenRec; - mdToken tkExtendsImp; - mdToken tkExtendsEmit; - - MergeImportData *pImportData; - MDTOKENMAP *pCurTkMap; - - pMiniMdEmit = GetMiniMdEmit(); - - for (pImportData = m_pImportDataList; pImportData != NULL; pImportData = pImportData->m_pNextImportData) - { - // for each import scope - pMiniMdImport = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - - // We know that the filter table is not null here. Tell PREFIX that we know it. - PREFIX_ASSUME( pMiniMdImport->GetFilterTable() != NULL ); - - // set the current MDTokenMap - pCurTkMap = pImportData->m_pMDTokenMap; - - iCount = pMiniMdImport->getCountTypeDefs(); - - // Merge the typedefs - for (i = 1; i <= iCount; i++) - { - // only merge those TypeDefs that are marked - if ( pMiniMdImport->GetFilterTable()->IsTypeDefMarked(TokenFromRid(i, mdtTypeDef)) == false) - continue; - - if ( !pCurTkMap->Find(TokenFromRid(i, mdtTypeDef), &pTokenRec) ) - { - _ASSERTE( !"bad state!"); - IfFailGo( META_E_BADMETADATA ); - } - - if (pTokenRec->m_isDuplicate == false) - { - // get the extends token from the import - IfFailGo(pMiniMdImport->GetTypeDefRecord(i, &pRecImport)); - tkExtendsImp = pMiniMdImport->getExtendsOfTypeDef(pRecImport); - - // map the extends token to an merged token - IfFailGo( pCurTkMap->Remap(tkExtendsImp, &tkExtendsEmit) ); - - // set the extends to the merged TypeDef records. - IfFailGo(pMiniMdEmit->GetTypeDefRecord(RidFromToken(pTokenRec->m_tkTo), &pRecEmit)); - IfFailGo(pMiniMdEmit->PutToken(TBL_TypeDef, TypeDefRec::COL_Extends, pRecEmit, tkExtendsEmit)); - } - else - { - // <TODO>@FUTURE: we can check to make sure the import extends maps to the one that is set to the emit scope. - // Otherwise, it is a error to report to linker.</TODO> - } - } - } -ErrExit: - return hr; -} // HRESULT NEWMERGER::CompleteMergeTypeDefs() - - -//***************************************************************************** -// merging TypeSpecs -//***************************************************************************** -HRESULT NEWMERGER::MergeTypeSpecs() -{ - HRESULT hr = NOERROR; - TypeSpecRec *pRecImport = NULL; - TypeSpecRec *pRecEmit = NULL; - CMiniMdRW *pMiniMdImport; - CMiniMdRW *pMiniMdEmit; - ULONG iCount; - ULONG i; - TOKENREC *pTokenRec; - mdTypeSpec tsImp; - mdTypeSpec tsEmit; - bool fDuplicate; - PCCOR_SIGNATURE pbSig; - ULONG cbSig; - ULONG cbEmit; - CQuickBytes qbSig; - - MergeImportData *pImportData; - MDTOKENMAP *pCurTkMap; - - pMiniMdEmit = GetMiniMdEmit(); - - for (pImportData = m_pImportDataList; pImportData != NULL; pImportData = pImportData->m_pNextImportData) - { - // for each import scope - pMiniMdImport = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - - // We know that the filter table is not null here. Tell PREFIX that we know it. - PREFIX_ASSUME( pMiniMdImport->GetFilterTable() != NULL ); - - // set the current MDTokenMap - pCurTkMap = pImportData->m_pMDTokenMap; - - iCount = pMiniMdImport->getCountTypeSpecs(); - - // loop through all TypeSpec - for (i = 1; i <= iCount; i++) - { - // only merge those TypeSpecs that are marked - if ( pMiniMdImport->GetFilterTable()->IsTypeSpecMarked(TokenFromRid(i, mdtTypeSpec)) == false) - continue; - - // compare it with the emit scope - IfFailGo(pMiniMdImport->GetTypeSpecRecord(i, &pRecImport)); - IfFailGo(pMiniMdImport->getSignatureOfTypeSpec(pRecImport, &pbSig, &cbSig)); - - // convert tokens contained in signature to new scope - IfFailGo(ImportHelper::MergeUpdateTokenInFieldSig( - NULL, // Assembly emit scope. - pMiniMdEmit, // The emit scope. - NULL, NULL, 0, // Import assembly information. - pMiniMdImport, // The scope to merge into the emit scope. - pbSig, // signature from the imported scope - pCurTkMap, // Internal token mapping structure. - &qbSig, // [OUT] translated signature - 0, // start from first byte of the signature - 0, // don't care how many bytes consumed - &cbEmit)); // number of bytes write to cbEmit - - hr = CLDB_E_RECORD_NOTFOUND; - if (m_fDupCheck) - hr = ImportHelper::FindTypeSpec( - pMiniMdEmit, - (PCOR_SIGNATURE) qbSig.Ptr(), - cbEmit, - &tsEmit ); - - if ( hr == S_OK ) - { - // find a duplicate - fDuplicate = true; - } - else - { - // copy over - fDuplicate = false; - IfFailGo(pMiniMdEmit->AddTypeSpecRecord(&pRecEmit, (ULONG *)&tsEmit)); - tsEmit = TokenFromRid(tsEmit, mdtTypeSpec); - IfFailGo( pMiniMdEmit->PutBlob( - TBL_TypeSpec, - TypeSpecRec::COL_Signature, - pRecEmit, - (PCOR_SIGNATURE)qbSig.Ptr(), - cbEmit)); - } - tsImp = TokenFromRid(i, mdtTypeSpec); - - // Record the token movement - IfFailGo( pCurTkMap->InsertNotFound(tsImp, fDuplicate, tsEmit, &pTokenRec) ); - } - } -ErrExit: - return hr; -} // HRESULT NEWMERGER::MergeTypeSpecs() - - -//***************************************************************************** -// merging Children of TypeDefs. This includes field, method, parameter, property, event -//***************************************************************************** -HRESULT NEWMERGER::MergeTypeDefChildren() -{ - HRESULT hr = NOERROR; - CMiniMdRW *pMiniMdImport; - CMiniMdRW *pMiniMdEmit; - ULONG iCount; - ULONG i; - mdTypeDef tdEmit; - mdTypeDef tdImport; - TOKENREC *pTokenRec; - -#if _DEBUG - TypeDefRec *pRecImport = NULL; - LPCUTF8 szNameImp; - LPCUTF8 szNamespaceImp; -#endif // _DEBUG - - MergeImportData *pImportData; - MDTOKENMAP *pCurTkMap; - - pMiniMdEmit = GetMiniMdEmit(); - - for (pImportData = m_pImportDataList; pImportData != NULL; pImportData = pImportData->m_pNextImportData) - { - // for each import scope - pMiniMdImport = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - - // We know that the filter table is not null here. Tell PREFIX that we know it. - PREFIX_ASSUME( pMiniMdImport->GetFilterTable() != NULL ); - - // set the current MDTokenMap - pCurTkMap = pImportData->m_pMDTokenMap; - iCount = pMiniMdImport->getCountTypeDefs(); - - // loop through all TypeDef again to merge/copy Methods, fields, events, and properties - // - for (i = 1; i <= iCount; i++) - { - // only merge those TypeDefs that are marked - if ( pMiniMdImport->GetFilterTable()->IsTypeDefMarked(TokenFromRid(i, mdtTypeDef)) == false) - continue; - -#if _DEBUG - IfFailGo(pMiniMdImport->GetTypeDefRecord(i, &pRecImport)); - IfFailGo(pMiniMdImport->getNameOfTypeDef(pRecImport, &szNameImp)); - IfFailGo(pMiniMdImport->getNamespaceOfTypeDef(pRecImport, &szNamespaceImp)); -#endif // _DEBUG - - // check to see if the typedef is duplicate or not - tdImport = TokenFromRid(i, mdtTypeDef); - if ( pCurTkMap->Find( tdImport, &pTokenRec) == false) - { - _ASSERTE( !"bad state!"); - IfFailGo( META_E_BADMETADATA ); - } - tdEmit = pTokenRec->m_tkTo; - if (pTokenRec->m_isDuplicate == false) - { - // now move all of the children records over - IfFailGo( CopyMethods(pImportData, tdImport, tdEmit) ); - IfFailGo( CopyFields(pImportData, tdImport, tdEmit) ); - - IfFailGo( CopyEvents(pImportData, tdImport, tdEmit) ); - - // Property has dependency on events - IfFailGo( CopyProperties(pImportData, tdImport, tdEmit) ); - - // Generic Params. - IfFailGo( CopyGenericParams(pImportData, tdImport, tdEmit) ); - } - else - { - // verify the children records - IfFailGo( VerifyMethods(pImportData, tdImport, tdEmit) ); - IfFailGo( VerifyFields(pImportData, tdImport, tdEmit) ); - IfFailGo( VerifyEvents(pImportData, tdImport, tdEmit) ); - - // property has dependency on events - IfFailGo( VerifyProperties(pImportData, tdImport, tdEmit) ); - - IfFailGo( VerifyGenericParams(pImportData, tdImport, tdEmit) ); - } - } - } -ErrExit: - return hr; -} // HRESULT NEWMERGER::MergeTypeDefChildren() - - -//******************************************************************************* -// Helper to copy an Method record -//******************************************************************************* -HRESULT NEWMERGER::CopyMethod( - MergeImportData *pImportData, // [IN] import scope - MethodRec *pRecImp, // [IN] the record to import - MethodRec *pRecEmit) // [IN] the emit record to fill -{ - HRESULT hr; - CMiniMdRW *pMiniMdImp = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - CMiniMdRW *pMiniMdEmit = GetMiniMdEmit(); - LPCUTF8 szName; - PCCOR_SIGNATURE pbSig; - ULONG cbSig; - ULONG cbEmit; - CQuickBytes qbSig; - MDTOKENMAP *pCurTkMap; - - pCurTkMap = pImportData->m_pMDTokenMap; - - // copy over the fix part of the record - pRecEmit->Copy(pRecImp); - - // copy over the name - IfFailGo(pMiniMdImp->getNameOfMethod(pRecImp, &szName)); - IfFailGo(pMiniMdEmit->PutString(TBL_Method, MethodRec::COL_Name, pRecEmit, szName)); - - // copy over the signature - IfFailGo(pMiniMdImp->getSignatureOfMethod(pRecImp, &pbSig, &cbSig)); - - // convert rid contained in signature to new scope - IfFailGo(ImportHelper::MergeUpdateTokenInSig( - NULL, // Assembly emit scope. - pMiniMdEmit, // The emit scope. - NULL, NULL, 0, // Import assembly scope information. - pMiniMdImp, // The scope to merge into the emit scope. - pbSig, // signature from the imported scope - pCurTkMap, // Internal token mapping structure. - &qbSig, // [OUT] translated signature - 0, // start from first byte of the signature - 0, // don't care how many bytes consumed - &cbEmit)); // number of bytes write to cbEmit - - IfFailGo(pMiniMdEmit->PutBlob(TBL_Method, MethodRec::COL_Signature, pRecEmit, qbSig.Ptr(), cbEmit)); - -ErrExit: - return hr; -} // HRESULT NEWMERGER::CopyMethod() - - -//******************************************************************************* -// Helper to copy an field record -//******************************************************************************* -HRESULT NEWMERGER::CopyField( - MergeImportData *pImportData, // [IN] import scope - FieldRec *pRecImp, // [IN] the record to import - FieldRec *pRecEmit) // [IN] the emit record to fill -{ - HRESULT hr; - CMiniMdRW *pMiniMdImp = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - CMiniMdRW *pMiniMdEmit = GetMiniMdEmit(); - LPCUTF8 szName; - PCCOR_SIGNATURE pbSig; - ULONG cbSig; - ULONG cbEmit; - CQuickBytes qbSig; - MDTOKENMAP *pCurTkMap; - - pCurTkMap = pImportData->m_pMDTokenMap; - - // copy over the fix part of the record - pRecEmit->SetFlags(pRecImp->GetFlags()); - - // copy over the name - IfFailGo(pMiniMdImp->getNameOfField(pRecImp, &szName)); - IfFailGo(pMiniMdEmit->PutString(TBL_Field, FieldRec::COL_Name, pRecEmit, szName)); - - // copy over the signature - IfFailGo(pMiniMdImp->getSignatureOfField(pRecImp, &pbSig, &cbSig)); - - // convert rid contained in signature to new scope - IfFailGo(ImportHelper::MergeUpdateTokenInSig( - NULL, // Emit assembly scope. - pMiniMdEmit, // The emit scope. - NULL, NULL, 0, // Import assembly scope information. - pMiniMdImp, // The scope to merge into the emit scope. - pbSig, // signature from the imported scope - pCurTkMap, // Internal token mapping structure. - &qbSig, // [OUT] translated signature - 0, // start from first byte of the signature - 0, // don't care how many bytes consumed - &cbEmit)); // number of bytes write to cbEmit - - IfFailGo(pMiniMdEmit->PutBlob(TBL_Field, FieldRec::COL_Signature, pRecEmit, qbSig.Ptr(), cbEmit)); - -ErrExit: - return hr; -} // HRESULT NEWMERGER::CopyField() - -//******************************************************************************* -// Helper to copy an field record -//******************************************************************************* -HRESULT NEWMERGER::CopyParam( - MergeImportData *pImportData, // [IN] import scope - ParamRec *pRecImp, // [IN] the record to import - ParamRec *pRecEmit) // [IN] the emit record to fill -{ - HRESULT hr; - CMiniMdRW *pMiniMdImp = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - CMiniMdRW *pMiniMdEmit = GetMiniMdEmit(); - LPCUTF8 szName; - MDTOKENMAP *pCurTkMap; - - pCurTkMap = pImportData->m_pMDTokenMap; - - // copy over the fix part of the record - pRecEmit->Copy(pRecImp); - - // copy over the name - IfFailGo(pMiniMdImp->getNameOfParam(pRecImp, &szName)); - IfFailGo(pMiniMdEmit->PutString(TBL_Param, ParamRec::COL_Name, pRecEmit, szName)); - -ErrExit: - return hr; -} // HRESULT NEWMERGER::CopyParam() - -//******************************************************************************* -// Helper to copy an Event record -//******************************************************************************* -HRESULT NEWMERGER::CopyEvent( - MergeImportData *pImportData, // [IN] import scope - EventRec *pRecImp, // [IN] the record to import - EventRec *pRecEmit) // [IN] the emit record to fill -{ - HRESULT hr = NOERROR; - CMiniMdRW *pMiniMdImp = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - CMiniMdRW *pMiniMdEmit = GetMiniMdEmit(); - mdToken tkEventTypeImp; - mdToken tkEventTypeEmit; // could be TypeDef or TypeRef - LPCUTF8 szName; - MDTOKENMAP *pCurTkMap; - - pCurTkMap = pImportData->m_pMDTokenMap; - - pRecEmit->SetEventFlags(pRecImp->GetEventFlags()); - - //move over the event name - IfFailGo(pMiniMdImp->getNameOfEvent(pRecImp, &szName)); - IfFailGo( pMiniMdEmit->PutString(TBL_Event, EventRec::COL_Name, pRecEmit, szName) ); - - // move over the EventType - tkEventTypeImp = pMiniMdImp->getEventTypeOfEvent(pRecImp); - if ( !IsNilToken(tkEventTypeImp) ) - { - IfFailGo( pCurTkMap->Remap(tkEventTypeImp, &tkEventTypeEmit) ); - IfFailGo(pMiniMdEmit->PutToken(TBL_Event, EventRec::COL_EventType, pRecEmit, tkEventTypeEmit)); - } - -ErrExit: - return hr; -} // HRESULT NEWMERGER::CopyEvent() - - -//******************************************************************************* -// Helper to copy a property record -//******************************************************************************* -HRESULT NEWMERGER::CopyProperty( - MergeImportData *pImportData, // [IN] import scope - PropertyRec *pRecImp, // [IN] the record to import - PropertyRec *pRecEmit) // [IN] the emit record to fill -{ - HRESULT hr = NOERROR; - CMiniMdRW *pMiniMdImp = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - CMiniMdRW *pMiniMdEmit = GetMiniMdEmit(); - LPCUTF8 szName; - PCCOR_SIGNATURE pbSig; - ULONG cbSig; - ULONG cbEmit; - CQuickBytes qbSig; - MDTOKENMAP *pCurTkMap; - - pCurTkMap = pImportData->m_pMDTokenMap; - - // move over the flag value - pRecEmit->SetPropFlags(pRecImp->GetPropFlags()); - - //move over the property name - IfFailGo(pMiniMdImp->getNameOfProperty(pRecImp, &szName)); - IfFailGo( pMiniMdEmit->PutString(TBL_Property, PropertyRec::COL_Name, pRecEmit, szName) ); - - // move over the type of the property - IfFailGo(pMiniMdImp->getTypeOfProperty(pRecImp, &pbSig, &cbSig)); - - // convert rid contained in signature to new scope - IfFailGo( ImportHelper::MergeUpdateTokenInSig( - NULL, // Assembly emit scope. - pMiniMdEmit, // The emit scope. - NULL, NULL, 0, // Import assembly scope information. - pMiniMdImp, // The scope to merge into the emit scope. - pbSig, // signature from the imported scope - pCurTkMap, // Internal token mapping structure. - &qbSig, // [OUT] translated signature - 0, // start from first byte of the signature - 0, // don't care how many bytes consumed - &cbEmit) ); // number of bytes write to cbEmit - - IfFailGo(pMiniMdEmit->PutBlob(TBL_Property, PropertyRec::COL_Type, pRecEmit, qbSig.Ptr(), cbEmit)); - -ErrExit: - return hr; -} // HRESULT NEWMERGER::CopyProperty() - - -//***************************************************************************** -// Copy MethodSemantics for an event or a property -//***************************************************************************** -HRESULT NEWMERGER::CopyMethodSemantics( - MergeImportData *pImportData, - mdToken tkImport, // Event or property in the import scope - mdToken tkEmit) // corresponding event or property in the emitting scope -{ - HRESULT hr = NOERROR; - MethodSemanticsRec *pRecImport = NULL; - MethodSemanticsRec *pRecEmit = NULL; - CMiniMdRW *pMiniMdImport = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - CMiniMdRW *pMiniMdEmit = GetMiniMdEmit(); - ULONG i; - ULONG msEmit; // MethodSemantics are just index not tokens - mdToken tkMethodImp; - mdToken tkMethodEmit; - MDTOKENMAP *pCurTkMap; - HENUMInternal hEnum; - - pCurTkMap = pImportData->m_pMDTokenMap; - - // copy over the associates - IfFailGo( pMiniMdImport->FindMethodSemanticsHelper(tkImport, &hEnum) ); - while (HENUMInternal::EnumNext(&hEnum, (mdToken *) &i)) - { - IfFailGo(pMiniMdImport->GetMethodSemanticsRecord(i, &pRecImport)); - IfFailGo(pMiniMdEmit->AddMethodSemanticsRecord(&pRecEmit, &msEmit)); - pRecEmit->SetSemantic(pRecImport->GetSemantic()); - - // set the MethodSemantics - tkMethodImp = pMiniMdImport->getMethodOfMethodSemantics(pRecImport); - IfFailGo( pCurTkMap->Remap(tkMethodImp, &tkMethodEmit) ); - IfFailGo( pMiniMdEmit->PutToken(TBL_MethodSemantics, MethodSemanticsRec::COL_Method, pRecEmit, tkMethodEmit)); - - // set the associate - _ASSERTE( pMiniMdImport->getAssociationOfMethodSemantics(pRecImport) == tkImport ); - IfFailGo( pMiniMdEmit->PutToken(TBL_MethodSemantics, MethodSemanticsRec::COL_Association, pRecEmit, tkEmit)); - - // no need to record the movement since it is not a token - IfFailGo( pMiniMdEmit->AddMethodSemanticsToHash(msEmit) ); - } -ErrExit: - HENUMInternal::ClearEnum(&hEnum); - return hr; -} // HRESULT NEWMERGER::CopyMethodSemantics() - - -//***************************************************************************** -// Copy Methods given a TypeDef -//***************************************************************************** -HRESULT NEWMERGER::CopyMethods( - MergeImportData *pImportData, - mdTypeDef tdImport, - mdTypeDef tdEmit) -{ - HRESULT hr = NOERROR; - MethodRec *pRecImport = NULL; - MethodRec *pRecEmit = NULL; - TypeDefRec *pTypeDefRec; - CMiniMdRW *pMiniMdImport; - CMiniMdRW *pMiniMdEmit; - ULONG ridStart, ridEnd; - ULONG i; - mdMethodDef mdEmit; - mdMethodDef mdImp; - TOKENREC *pTokenRec; - MDTOKENMAP *pCurTkMap; - - MergeTypeData *pMTD; - BOOL bSuppressMergeCheck; - mdCustomAttribute tkCA; - - pMiniMdEmit = GetMiniMdEmit(); - pMiniMdImport = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - pCurTkMap = pImportData->m_pMDTokenMap; - - IfFailGo(pMiniMdImport->GetTypeDefRecord(RidFromToken(tdImport), &pTypeDefRec)); - ridStart = pMiniMdImport->getMethodListOfTypeDef(pTypeDefRec); - IfFailGo(pMiniMdImport->getEndMethodListOfTypeDef(RidFromToken(tdImport), &ridEnd)); - - // We know that the filter table is not null here. Tell PREFIX that we know it. - PREFIX_ASSUME( pMiniMdImport->GetFilterTable() != NULL ); - - pMTD = m_rMTDs.Get(RidFromToken(tdEmit)); - - // make sure we didn't count the methods yet - _ASSERTE(pMTD->m_cMethods == 0); - - // loop through all Methods - for (i = ridStart; i < ridEnd; i++) - { - // compare it with the emit scope - IfFailGo(pMiniMdImport->GetMethodRid(i, (ULONG *)&mdImp)); - - // only merge those MethodDefs that are marked - if ( pMiniMdImport->GetFilterTable()->IsMethodMarked(TokenFromRid(mdImp, mdtMethodDef)) == false) - continue; - - IfFailGo(pMiniMdImport->GetMethodRecord(mdImp, &pRecImport)); - IfFailGo(pMiniMdEmit->AddMethodRecord(&pRecEmit, (RID *)&mdEmit)); - - // copy the method content over - IfFailGo( CopyMethod(pImportData, pRecImport, pRecEmit) ); - - IfFailGo( pMiniMdEmit->AddMethodToTypeDef(RidFromToken(tdEmit), mdEmit)); - - // record the token movement - mdImp = TokenFromRid(mdImp, mdtMethodDef); - mdEmit = TokenFromRid(mdEmit, mdtMethodDef); - IfFailGo( pMiniMdEmit->AddMemberDefToHash( - mdEmit, - tdEmit) ); - - IfFailGo( pCurTkMap->InsertNotFound(mdImp, false, mdEmit, &pTokenRec) ); - - // copy over the children - IfFailGo( CopyParams(pImportData, mdImp, mdEmit) ); - IfFailGo( CopyGenericParams(pImportData, mdImp, mdEmit) ); - - bSuppressMergeCheck = pMTD->m_bSuppressMergeCheck || - ((pImportData->m_tkSuppressMergeCheckCtor != mdTokenNil) && - (S_OK == ImportHelper::FindCustomAttributeByToken(pMiniMdImport, - mdImp, pImportData->m_tkSuppressMergeCheckCtor, NULL, 0, &tkCA))); - - - if (!bSuppressMergeCheck) { - pMTD->m_cMethods++; - } - } - - // make sure we don't count any methods if merge check is suppressed on the type - _ASSERTE(pMTD->m_cMethods == 0 || !pMTD->m_bSuppressMergeCheck); -ErrExit: - return hr; -} // HRESULT NEWMERGER::CopyMethods() - - -//***************************************************************************** -// Copy Fields given a TypeDef -//***************************************************************************** -HRESULT NEWMERGER::CopyFields( - MergeImportData *pImportData, - mdTypeDef tdImport, - mdTypeDef tdEmit) -{ - HRESULT hr = NOERROR; - FieldRec *pRecImport = NULL; - FieldRec *pRecEmit = NULL; - TypeDefRec *pTypeDefRec; - CMiniMdRW *pMiniMdImport; - CMiniMdRW *pMiniMdEmit; - ULONG ridStart, ridEnd; - ULONG i; - mdFieldDef fdEmit; - mdFieldDef fdImp; - bool bDuplicate; - TOKENREC *pTokenRec; - PCCOR_SIGNATURE pvSigBlob; - ULONG cbSigBlob; - MDTOKENMAP *pCurTkMap; - - MergeTypeData *pMTD; - BOOL bSuppressMergeCheck; - mdCustomAttribute tkCA; - - pMiniMdEmit = GetMiniMdEmit(); - pMiniMdImport = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - pCurTkMap = pImportData->m_pMDTokenMap; - - IfFailGo(pMiniMdImport->GetTypeDefRecord(RidFromToken(tdImport), &pTypeDefRec)); - ridStart = pMiniMdImport->getFieldListOfTypeDef(pTypeDefRec); - IfFailGo(pMiniMdImport->getEndFieldListOfTypeDef(RidFromToken(tdImport), &ridEnd)); - - // We know that the filter table is not null here. Tell PREFIX that we know it. - PREFIX_ASSUME( pMiniMdImport->GetFilterTable() != NULL ); - - pMTD = m_rMTDs.Get(RidFromToken(tdEmit)); - - // make sure we didn't count the methods yet - _ASSERTE(pMTD->m_cFields == 0); - - // loop through all FieldDef of a TypeDef - for (i = ridStart; i < ridEnd; i++) - { - // compare it with the emit scope - IfFailGo(pMiniMdImport->GetFieldRid(i, (ULONG *)&fdImp)); - - // only merge those FieldDefs that are marked - if ( pMiniMdImport->GetFilterTable()->IsFieldMarked(TokenFromRid(fdImp, mdtFieldDef)) == false) - continue; - - - IfFailGo(pMiniMdImport->GetFieldRecord(fdImp, &pRecImport)); - bDuplicate = false; - IfFailGo(pMiniMdEmit->AddFieldRecord(&pRecEmit, (RID *)&fdEmit)); - - // copy the field content over - IfFailGo( CopyField(pImportData, pRecImport, pRecEmit) ); - - IfFailGo( pMiniMdEmit->AddFieldToTypeDef(RidFromToken(tdEmit), fdEmit)); - - // record the token movement - fdImp = TokenFromRid(fdImp, mdtFieldDef); - fdEmit = TokenFromRid(fdEmit, mdtFieldDef); - IfFailGo(pMiniMdEmit->getSignatureOfField(pRecEmit, &pvSigBlob, &cbSigBlob)); - IfFailGo( pMiniMdEmit->AddMemberDefToHash( - fdEmit, - tdEmit) ); - - IfFailGo( pCurTkMap->InsertNotFound(fdImp, false, fdEmit, &pTokenRec) ); - - // count the number of fields that didn't suppress merge check - // non-static fields doesn't inherite the suppress merge check attribute from the type - bSuppressMergeCheck = - (IsFdStatic(pRecEmit->GetFlags()) && pMTD->m_bSuppressMergeCheck) || - ((pImportData->m_tkSuppressMergeCheckCtor != mdTokenNil) && - (S_OK == ImportHelper::FindCustomAttributeByToken(pMiniMdImport, - fdImp, pImportData->m_tkSuppressMergeCheckCtor, NULL, 0, &tkCA))); - - if (!bSuppressMergeCheck) { - pMTD->m_cFields++; - } - } - -ErrExit: - return hr; -} // HRESULT NEWMERGER::CopyFields() - - -//***************************************************************************** -// Copy Events given a TypeDef -//***************************************************************************** -HRESULT NEWMERGER::CopyEvents( - MergeImportData *pImportData, - mdTypeDef tdImport, - mdTypeDef tdEmit) -{ - HRESULT hr = NOERROR; - CMiniMdRW *pMiniMdImport = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - CMiniMdRW *pMiniMdEmit = GetMiniMdEmit(); - RID ridEventMap; - EventMapRec *pEventMapRec; - EventRec *pRecImport; - EventRec *pRecEmit; - ULONG ridStart; - ULONG ridEnd; - ULONG i; - mdEvent evImp; - mdEvent evEmit; - TOKENREC *pTokenRec; - ULONG iEventMap; - EventMapRec *pEventMap; - MDTOKENMAP *pCurTkMap; - - MergeTypeData *pMTD; - BOOL bSuppressMergeCheck; - mdCustomAttribute tkCA; - - // We know that the filter table is not null here. Tell PREFIX that we know it. - PREFIX_ASSUME( pMiniMdImport->GetFilterTable() != NULL ); - - pCurTkMap = pImportData->m_pMDTokenMap; - - pMTD = m_rMTDs.Get(RidFromToken(tdEmit)); - - // make sure we didn't count the events yet - _ASSERTE(pMTD->m_cEvents == 0); - - IfFailGo(pMiniMdImport->FindEventMapFor(RidFromToken(tdImport), &ridEventMap)); - if (!InvalidRid(ridEventMap)) - { - IfFailGo(pMiniMdImport->GetEventMapRecord(ridEventMap, &pEventMapRec)); - ridStart = pMiniMdImport->getEventListOfEventMap(pEventMapRec); - IfFailGo(pMiniMdImport->getEndEventListOfEventMap(ridEventMap, &ridEnd)); - - if (ridEnd > ridStart) - { - // If there is any event, create the eventmap record in the emit scope - // Create new record. - IfFailGo(pMiniMdEmit->AddEventMapRecord(&pEventMap, &iEventMap)); - - // Set parent. - IfFailGo(pMiniMdEmit->PutToken(TBL_EventMap, EventMapRec::COL_Parent, pEventMap, tdEmit)); - } - - for (i = ridStart; i < ridEnd; i++) - { - // get the real event rid - IfFailGo(pMiniMdImport->GetEventRid(i, (ULONG *)&evImp)); - - // only merge those Events that are marked - if ( pMiniMdImport->GetFilterTable()->IsEventMarked(TokenFromRid(evImp, mdtEvent)) == false) - continue; - - IfFailGo(pMiniMdImport->GetEventRecord(evImp, &pRecImport)); - IfFailGo(pMiniMdEmit->AddEventRecord(&pRecEmit, (RID *)&evEmit)); - - // copy the event record over - IfFailGo( CopyEvent(pImportData, pRecImport, pRecEmit) ); - - // Add Event to the EventMap. - IfFailGo( pMiniMdEmit->AddEventToEventMap(iEventMap, evEmit) ); - - // record the token movement - evImp = TokenFromRid(evImp, mdtEvent); - evEmit = TokenFromRid(evEmit, mdtEvent); - - IfFailGo( pCurTkMap->InsertNotFound(evImp, false, evEmit, &pTokenRec) ); - - // copy over the method semantics - IfFailGo( CopyMethodSemantics(pImportData, evImp, evEmit) ); - - bSuppressMergeCheck = pMTD->m_bSuppressMergeCheck || - ((pImportData->m_tkSuppressMergeCheckCtor != mdTokenNil) && - (S_OK == ImportHelper::FindCustomAttributeByToken(pMiniMdImport, - evImp, pImportData->m_tkSuppressMergeCheckCtor, NULL, 0, &tkCA))); - - if (!bSuppressMergeCheck) { - pMTD->m_cEvents++; - } - } - } - - // make sure we don't count any events if merge check is suppressed on the type - _ASSERTE(pMTD->m_cEvents == 0 || !pMTD->m_bSuppressMergeCheck); -ErrExit: - return hr; -} // HRESULT NEWMERGER::CopyEvents() - - -//***************************************************************************** -// Copy Properties given a TypeDef -//***************************************************************************** -HRESULT NEWMERGER::CopyProperties( - MergeImportData *pImportData, - mdTypeDef tdImport, - mdTypeDef tdEmit) -{ - HRESULT hr = NOERROR; - CMiniMdRW *pMiniMdImport = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - CMiniMdRW *pMiniMdEmit = GetMiniMdEmit(); - RID ridPropertyMap; - PropertyMapRec *pPropertyMapRec; - PropertyRec *pRecImport; - PropertyRec *pRecEmit; - ULONG ridStart; - ULONG ridEnd; - ULONG i; - mdProperty prImp; - mdProperty prEmit; - TOKENREC *pTokenRec; - ULONG iPropertyMap; - PropertyMapRec *pPropertyMap; - MDTOKENMAP *pCurTkMap; - - MergeTypeData *pMTD; - BOOL bSuppressMergeCheck; - mdCustomAttribute tkCA; - - // We know that the filter table is not null here. Tell PREFIX that we know it. - PREFIX_ASSUME( pMiniMdImport->GetFilterTable() != NULL ); - - pCurTkMap = pImportData->m_pMDTokenMap; - - pMTD = m_rMTDs.Get(RidFromToken(tdEmit)); - - // make sure we didn't count the properties yet - _ASSERTE(pMTD->m_cProperties == 0); - - IfFailGo(pMiniMdImport->FindPropertyMapFor(RidFromToken(tdImport), &ridPropertyMap)); - if (!InvalidRid(ridPropertyMap)) - { - IfFailGo(pMiniMdImport->GetPropertyMapRecord(ridPropertyMap, &pPropertyMapRec)); - ridStart = pMiniMdImport->getPropertyListOfPropertyMap(pPropertyMapRec); - IfFailGo(pMiniMdImport->getEndPropertyListOfPropertyMap(ridPropertyMap, &ridEnd)); - - if (ridEnd > ridStart) - { - // If there is any event, create the PropertyMap record in the emit scope - // Create new record. - IfFailGo(pMiniMdEmit->AddPropertyMapRecord(&pPropertyMap, &iPropertyMap)); - - // Set parent. - IfFailGo(pMiniMdEmit->PutToken(TBL_PropertyMap, PropertyMapRec::COL_Parent, pPropertyMap, tdEmit)); - } - - for (i = ridStart; i < ridEnd; i++) - { - // get the property rid - IfFailGo(pMiniMdImport->GetPropertyRid(i, (ULONG *)&prImp)); - - // only merge those Properties that are marked - if ( pMiniMdImport->GetFilterTable()->IsPropertyMarked(TokenFromRid(prImp, mdtProperty)) == false) - continue; - - - IfFailGo(pMiniMdImport->GetPropertyRecord(prImp, &pRecImport)); - IfFailGo(pMiniMdEmit->AddPropertyRecord(&pRecEmit, (RID *)&prEmit)); - - // copy the property record over - IfFailGo( CopyProperty(pImportData, pRecImport, pRecEmit) ); - - // Add Property to the PropertyMap. - IfFailGo( pMiniMdEmit->AddPropertyToPropertyMap(iPropertyMap, prEmit) ); - - // record the token movement - prImp = TokenFromRid(prImp, mdtProperty); - prEmit = TokenFromRid(prEmit, mdtProperty); - - IfFailGo( pCurTkMap->InsertNotFound(prImp, false, prEmit, &pTokenRec) ); - - // copy over the method semantics - IfFailGo( CopyMethodSemantics(pImportData, prImp, prEmit) ); - - bSuppressMergeCheck = pMTD->m_bSuppressMergeCheck || - ((pImportData->m_tkSuppressMergeCheckCtor != mdTokenNil) && - (S_OK == ImportHelper::FindCustomAttributeByToken(pMiniMdImport, - prImp, pImportData->m_tkSuppressMergeCheckCtor, NULL, 0, &tkCA))); - - if (!bSuppressMergeCheck) { - pMTD->m_cProperties++; - } - } - } - - // make sure we don't count any properties if merge check is suppressed on the type - _ASSERTE(pMTD->m_cProperties == 0 || !pMTD->m_bSuppressMergeCheck); - -ErrExit: - return hr; -} // HRESULT NEWMERGER::CopyProperties() - - -//***************************************************************************** -// Copy Parameters given a TypeDef -//***************************************************************************** -HRESULT NEWMERGER::CopyParams( - MergeImportData *pImportData, - mdMethodDef mdImport, - mdMethodDef mdEmit) -{ - HRESULT hr = NOERROR; - ParamRec *pRecImport = NULL; - ParamRec *pRecEmit = NULL; - MethodRec *pMethodRec; - CMiniMdRW *pMiniMdImport; - CMiniMdRW *pMiniMdEmit; - ULONG ridStart, ridEnd; - ULONG i; - mdParamDef pdEmit; - mdParamDef pdImp; - TOKENREC *pTokenRec; - MDTOKENMAP *pCurTkMap; - - pMiniMdEmit = GetMiniMdEmit(); - pMiniMdImport = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - pCurTkMap = pImportData->m_pMDTokenMap; - - - IfFailGo(pMiniMdImport->GetMethodRecord(RidFromToken(mdImport), &pMethodRec)); - ridStart = pMiniMdImport->getParamListOfMethod(pMethodRec); - IfFailGo(pMiniMdImport->getEndParamListOfMethod(RidFromToken(mdImport), &ridEnd)); - - // We know that the filter table is not null here. Tell PREFIX that we know it. - PREFIX_ASSUME( pMiniMdImport->GetFilterTable() != NULL ); - - // loop through all InterfaceImpl - for (i = ridStart; i < ridEnd; i++) - { - // Get the param rid - IfFailGo(pMiniMdImport->GetParamRid(i, (ULONG *)&pdImp)); - - // only merge those Params that are marked - if ( pMiniMdImport->GetFilterTable()->IsParamMarked(TokenFromRid(pdImp, mdtParamDef)) == false) - continue; - - - IfFailGo(pMiniMdImport->GetParamRecord(pdImp, &pRecImport)); - IfFailGo(pMiniMdEmit->AddParamRecord(&pRecEmit, (RID *)&pdEmit)); - - // copy the Parameter record over - IfFailGo( CopyParam(pImportData, pRecImport, pRecEmit) ); - - // warning!! warning!! - // We cannot add paramRec to method list until it is fully set. - // AddParamToMethod will use the ulSequence in the record - IfFailGo( pMiniMdEmit->AddParamToMethod(RidFromToken(mdEmit), pdEmit)); - - // record the token movement - pdImp = TokenFromRid(pdImp, mdtParamDef); - pdEmit = TokenFromRid(pdEmit, mdtParamDef); - - IfFailGo( pCurTkMap->InsertNotFound(pdImp, false, pdEmit, &pTokenRec) ); - } - -ErrExit: - return hr; -} // HRESULT NEWMERGER::CopyParams() - - -//***************************************************************************** -// Copy GenericParams given a TypeDef -//***************************************************************************** -HRESULT NEWMERGER::CopyGenericParams( - MergeImportData *pImportData, - mdToken tkImport, - mdToken tkEmit) -{ - HRESULT hr = NOERROR; - CMiniMdRW *pMiniMdImport; - CMiniMdRW *pMiniMdEmit; - TOKENREC *pTokenRec; - GenericParamRec *pRecImport = NULL; - GenericParamRec *pRecEmit = NULL; - MDTOKENMAP *pCurTkMap; - HENUMInternal hEnum; - mdGenericParam gpImport; - mdGenericParam gpEmit; - LPCSTR szGenericParamName; - - pMiniMdImport = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - pMiniMdEmit = GetMiniMdEmit(); - pCurTkMap = pImportData->m_pMDTokenMap; - - IfFailGo( pMiniMdImport->FindGenericParamHelper(tkImport, &hEnum) ); - - while (HENUMInternal::EnumNext(&hEnum, (mdToken *) &gpImport)) - { - // Get the import GenericParam record - _ASSERTE(TypeFromToken(gpImport) == mdtGenericParam); - IfFailGo(pMiniMdImport->GetGenericParamRecord(RidFromToken(gpImport), &pRecImport)); - - // Create new emit record. - IfFailGo(pMiniMdEmit->AddGenericParamRecord(&pRecEmit, (RID *)&gpEmit)); - - // copy the GenericParam content - pRecEmit->SetNumber( pRecImport->GetNumber()); - pRecEmit->SetFlags( pRecImport->GetFlags()); - - IfFailGo( pMiniMdEmit->PutToken(TBL_GenericParam, GenericParamRec::COL_Owner, pRecEmit, tkEmit)); - - IfFailGo(pMiniMdImport->getNameOfGenericParam(pRecImport, &szGenericParamName)); - IfFailGo( pMiniMdEmit->PutString(TBL_GenericParam, GenericParamRec::COL_Name, pRecEmit, szGenericParamName)); - - // record the token movement - gpImport = TokenFromRid(gpImport, mdtGenericParam); - gpEmit = TokenFromRid(gpEmit, mdtGenericParam); - - IfFailGo( pCurTkMap->InsertNotFound(gpImport, false, gpEmit, &pTokenRec) ); - - // copy over any constraints - IfFailGo( CopyGenericParamConstraints(pImportData, gpImport, gpEmit) ); - } - -ErrExit: - return hr; -} // HRESULT NEWMERGER::CopyGenericParams() - - -//***************************************************************************** -// Copy GenericParamConstraints given a GenericParam -//***************************************************************************** -HRESULT NEWMERGER::CopyGenericParamConstraints( - MergeImportData *pImportData, - mdGenericParamConstraint tkImport, - mdGenericParamConstraint tkEmit) -{ - HRESULT hr = NOERROR; - CMiniMdRW *pMiniMdImport; - CMiniMdRW *pMiniMdEmit; - TOKENREC *pTokenRec; - GenericParamConstraintRec *pRecImport = NULL; - GenericParamConstraintRec *pRecEmit = NULL; - MDTOKENMAP *pCurTkMap; - HENUMInternal hEnum; - mdGenericParamConstraint gpImport; - mdGenericParamConstraint gpEmit; - mdToken tkConstraint; - - pMiniMdImport = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - pMiniMdEmit = GetMiniMdEmit(); - pCurTkMap = pImportData->m_pMDTokenMap; - - IfFailGo( pMiniMdImport->FindGenericParamConstraintHelper(tkImport, &hEnum) ); - - while (HENUMInternal::EnumNext(&hEnum, (mdToken *) &gpImport)) - { - // Get the import GenericParam record - _ASSERTE(TypeFromToken(gpImport) == mdtGenericParamConstraint); - IfFailGo(pMiniMdImport->GetGenericParamConstraintRecord(RidFromToken(gpImport), &pRecImport)); - - // Translate the constraint before creating new record. - tkConstraint = pMiniMdImport->getConstraintOfGenericParamConstraint(pRecImport); - if (pCurTkMap->Find(tkConstraint, &pTokenRec) == false) - { - // This should never fire unless the TypeDefs/Refs weren't merged - // before this code runs. - _ASSERTE(!"GenericParamConstraint Constraint not found in MERGER::CopyGenericParamConstraints. Bad state!"); - IfFailGo( META_E_BADMETADATA ); - } - tkConstraint = pTokenRec->m_tkTo; - - // Create new emit record. - IfFailGo(pMiniMdEmit->AddGenericParamConstraintRecord(&pRecEmit, (RID *)&gpEmit)); - - // copy the GenericParamConstraint content - IfFailGo( pMiniMdEmit->PutToken(TBL_GenericParamConstraint, GenericParamConstraintRec::COL_Owner, pRecEmit, tkEmit)); - - IfFailGo( pMiniMdEmit->PutToken(TBL_GenericParamConstraint, GenericParamConstraintRec::COL_Constraint, pRecEmit, tkConstraint)); - } - -ErrExit: - return hr; -} // HRESULT NEWMERGER::CopyGenericParamConstraints() - - -//***************************************************************************** -// Verify GenericParams given a TypeDef -//***************************************************************************** -HRESULT NEWMERGER::VerifyGenericParams( - MergeImportData *pImportData, - mdToken tkImport, - mdToken tkEmit) -{ - HRESULT hr = NOERROR; - CMiniMdRW *pMiniMdImport; - CMiniMdRW *pMiniMdEmit; - TOKENREC *pTokenRec; - MDTOKENMAP *pCurTkMap; - HENUMInternal hEnumImport; // Enumerator for import scope. - HENUMInternal hEnumEmit; // Enumerator for emit scope. - ULONG cImport, cEmit; // Count of import & emit records. - ULONG i; // Enumerating records in import scope. - ULONG iEmit; // Tracking records in emit scope. - mdGenericParam gpImport; // Import scope GenericParam token. - mdGenericParam gpEmit; // Emit scope GenericParam token. - GenericParamRec *pRecImport = NULL; - GenericParamRec *pRecEmit = NULL; - LPCSTR szNameImport; // Name of param in import scope. - LPCSTR szNameEmit; // Name of param in emit scope. - - pMiniMdImport = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - pMiniMdEmit = GetMiniMdEmit(); - pCurTkMap = pImportData->m_pMDTokenMap; - - // Get enumerators for the input and output scopes. - IfFailGo(pMiniMdImport->FindGenericParamHelper(tkImport, &hEnumImport)); - IfFailGo(pMiniMdEmit->FindGenericParamHelper(tkEmit, &hEnumEmit)); - - // The counts should be the same. - IfFailGo(HENUMInternal::GetCount(&hEnumImport, &cImport)); - IfFailGo(HENUMInternal::GetCount(&hEnumEmit, &cEmit)); - - if (cImport != cEmit) - { - CheckContinuableErrorEx(META_E_GENERICPARAM_INCONSISTENT, pImportData, tkImport); - // If we are here, the linker says this error is OK. - } - - for (i=iEmit=0; i<cImport; ++i) - { - // Get the import GenericParam record - IfFailGo(HENUMInternal::GetElement(&hEnumImport, i, &gpImport)); - _ASSERTE(TypeFromToken(gpImport) == mdtGenericParam); - IfFailGo(pMiniMdImport->GetGenericParamRecord(RidFromToken(gpImport), &pRecImport)); - - // Find the emit record. If the import and emit scopes are ordered the same - // this is easy; otherwise go looking for it. - // Get the "next" emit record. - if (iEmit < cEmit) - { - IfFailGo(HENUMInternal::GetElement(&hEnumEmit, iEmit, &gpEmit)); - _ASSERTE(TypeFromToken(gpEmit) == mdtGenericParam); - IfFailGo(pMiniMdEmit->GetGenericParamRecord(RidFromToken(gpEmit), &pRecEmit)); - } - - // If the import and emit sequence numbers don't match, go looking. - // Also, if we would have walked off end of array, go looking. - if (iEmit >= cEmit || pRecImport->GetNumber() != pRecEmit->GetNumber()) - { - for (iEmit=0; iEmit<cEmit; ++iEmit) - { - IfFailGo( HENUMInternal::GetElement(&hEnumEmit, iEmit, &gpEmit)); - _ASSERTE(TypeFromToken(gpEmit) == mdtGenericParam); - IfFailGo(pMiniMdEmit->GetGenericParamRecord(RidFromToken(gpEmit), &pRecEmit)); - - // The one we want? - if (pRecImport->GetNumber() == pRecEmit->GetNumber()) - break; - } - if (iEmit >= cEmit) - goto Error; // Didn't find it - } - - // Check that these "n'th" GenericParam records match. - - // Flags. - if (pRecImport->GetFlags() != pRecEmit->GetFlags()) - goto Error; - - // Name. - IfFailGo(pMiniMdImport->getNameOfGenericParam(pRecImport, &szNameImport)); - IfFailGo(pMiniMdEmit->getNameOfGenericParam(pRecEmit, &szNameEmit)); - if (strcmp(szNameImport, szNameEmit) != 0) - goto Error; - - // Verify any constraints. - gpImport = TokenFromRid(gpImport, mdtGenericParam); - gpEmit = TokenFromRid(gpEmit, mdtGenericParam); - hr = VerifyGenericParamConstraints(pImportData, gpImport, gpEmit); - - if (SUCCEEDED(hr)) - { - // record the token movement - IfFailGo( pCurTkMap->InsertNotFound(gpImport, true, gpEmit, &pTokenRec) ); - } - else - { -Error: - // inconsistent in GenericParams - hr = S_OK; // discard old error; new error will be returned from CheckContinuableError - CheckContinuableErrorEx(META_E_GENERICPARAM_INCONSISTENT, pImportData, tkImport); - } - } - -ErrExit: - return hr; -} // HRESULT NEWMERGER::VerifyGenericParams() - - -//***************************************************************************** -// Verify GenericParamConstraints given a GenericParam -//***************************************************************************** -HRESULT NEWMERGER::VerifyGenericParamConstraints( - MergeImportData *pImportData, // The import scope. - mdGenericParam gpImport, // Import GenericParam. - mdGenericParam gpEmit) // Emit GenericParam. -{ - HRESULT hr = NOERROR; - CMiniMdRW *pMiniMdImport; - CMiniMdRW *pMiniMdEmit; - TOKENREC *pTokenRec; - HENUMInternal hEnumImport; // Enumerator for import scope. - HENUMInternal hEnumEmit; // Enumerator for emit scope. - ULONG cImport, cEmit; // Count of import & emit records. - ULONG i; // Enumerating records in import scope. - ULONG iEmit; // Tracking records in emit scope. - GenericParamConstraintRec *pRecImport = NULL; - GenericParamConstraintRec *pRecEmit = NULL; - MDTOKENMAP *pCurTkMap; - mdToken tkConstraintImport = mdTokenNil; - mdToken tkConstraintEmit = mdTokenNil; - - pMiniMdImport = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - pMiniMdEmit = GetMiniMdEmit(); - pCurTkMap = pImportData->m_pMDTokenMap; - - // Get enumerators for the input and output scopes. - IfFailGo(pMiniMdImport->FindGenericParamConstraintHelper(gpImport, &hEnumImport)); - IfFailGo(pMiniMdEmit->FindGenericParamConstraintHelper(gpEmit, &hEnumEmit)); - - // The counts should be the same. - IfFailGo(HENUMInternal::GetCount(&hEnumImport, &cImport)); - IfFailGo(HENUMInternal::GetCount(&hEnumEmit, &cEmit)); - - if (cImport != cEmit) - IfFailGo(META_E_GENERICPARAM_INCONSISTENT); // Different numbers of constraints. - - for (i=iEmit=0; i<cImport; ++i) - { - // Get the import GenericParam record - IfFailGo( HENUMInternal::GetElement(&hEnumImport, i, &gpImport)); - _ASSERTE(TypeFromToken(gpImport) == mdtGenericParamConstraint); - IfFailGo(pMiniMdImport->GetGenericParamConstraintRecord(RidFromToken(gpImport), &pRecImport)); - - // Get the constraint. - tkConstraintImport = pMiniMdImport->getConstraintOfGenericParamConstraint(pRecImport); - if (pCurTkMap->Find(tkConstraintImport, &pTokenRec) == false) - { - // This should never fire unless the TypeDefs/Refs weren't merged - // before this code runs. - _ASSERTE(!"GenericParamConstraint Constraint not found in MERGER::VerifyGenericParamConstraints. Bad state!"); - IfFailGo( META_E_BADMETADATA ); - } - tkConstraintImport = pTokenRec->m_tkTo; - - // Find the emit record. If the import and emit scopes are ordered the same - // this is easy; otherwise go looking for it. - // Get the "next" emit record. - if (iEmit < cEmit) - { - IfFailGo( HENUMInternal::GetElement(&hEnumEmit, iEmit, &gpEmit)); - _ASSERTE(TypeFromToken(gpEmit) == mdtGenericParamConstraint); - IfFailGo(pMiniMdEmit->GetGenericParamConstraintRecord(RidFromToken(gpEmit), &pRecEmit)); - tkConstraintEmit = pMiniMdEmit->getConstraintOfGenericParamConstraint(pRecEmit); - } - - // If the import and emit constraints don't match, go looking. - if (iEmit >= cEmit || tkConstraintEmit != tkConstraintImport) - { - for (iEmit=0; iEmit<cEmit; ++iEmit) - { - IfFailGo( HENUMInternal::GetElement(&hEnumEmit, iEmit, &gpEmit)); - _ASSERTE(TypeFromToken(gpEmit) == mdtGenericParamConstraint); - IfFailGo(pMiniMdEmit->GetGenericParamConstraintRecord(RidFromToken(gpEmit), &pRecEmit)); - tkConstraintEmit = pMiniMdEmit->getConstraintOfGenericParamConstraint(pRecEmit); - - // The one we want? - if (tkConstraintEmit == tkConstraintImport) - break; - } - if (iEmit >= cEmit) - { - IfFailGo(META_E_GENERICPARAM_INCONSISTENT); // Didn't find the constraint - } - } - } - -ErrExit: - return hr; -} // HRESULT NEWMERGER::VerifyGenericParamConstraints() - - -//***************************************************************************** -// Verify Methods -//***************************************************************************** -HRESULT NEWMERGER::VerifyMethods( - MergeImportData *pImportData, - mdTypeDef tdImport, - mdTypeDef tdEmit) -{ - HRESULT hr = NOERROR; - CMiniMdRW *pMiniMdImport; - CMiniMdRW *pMiniMdEmit; - MethodRec *pRecImp; - MethodRec *pRecEmit; - ULONG ridStart; - ULONG ridEnd; - ULONG i; - - TypeDefRec *pTypeDefRec; - LPCUTF8 szName; - PCCOR_SIGNATURE pbSig; - ULONG cbSig; - ULONG cbEmit; - CQuickBytes qbSig; - TOKENREC *pTokenRec; - mdMethodDef mdImp; - mdMethodDef mdEmit; - MDTOKENMAP *pCurTkMap; - - MergeTypeData *pMTD; - BOOL bSuppressMergeCheck; - ULONG cImport = 0; // count of non-merge check suppressed methods - mdCustomAttribute tkCA; - - pMiniMdEmit = GetMiniMdEmit(); - pMiniMdImport = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - pCurTkMap = pImportData->m_pMDTokenMap; - - // We know that the filter table is not null here. Tell PREFIX that we know it. - PREFIX_ASSUME( pMiniMdImport->GetFilterTable() != NULL ); - - // Get a count of records in the import scope; prepare to enumerate them. - IfFailGo(pMiniMdImport->GetTypeDefRecord(RidFromToken(tdImport), &pTypeDefRec)); - ridStart = pMiniMdImport->getMethodListOfTypeDef(pTypeDefRec); - IfFailGo(pMiniMdImport->getEndMethodListOfTypeDef(RidFromToken(tdImport), &ridEnd)); - - pMTD = m_rMTDs.Get(RidFromToken(tdEmit)); - - // loop through all Methods of the TypeDef - for (i = ridStart; i < ridEnd; i++) - { - IfFailGo(pMiniMdImport->GetMethodRid(i, (ULONG *)&mdImp)); - - // only verify those Methods that are marked - if ( pMiniMdImport->GetFilterTable()->IsMethodMarked(TokenFromRid(mdImp, mdtMethodDef)) == false) - continue; - - IfFailGo(pMiniMdImport->GetMethodRecord(mdImp, &pRecImp)); - - if (m_fDupCheck == FALSE && tdImport == pImportData->m_pRegMetaImport->m_tdModule) // TokenFromRid(1, mdtTypeDef)) - { - // No dup check. This is the scenario that we only have one import scope. Just copy over the - // globals. - goto CopyMethodLabel; - } - - IfFailGo(pMiniMdImport->getNameOfMethod(pRecImp, &szName)); - IfFailGo(pMiniMdImport->getSignatureOfMethod(pRecImp, &pbSig, &cbSig)); - - mdImp = TokenFromRid(mdImp, mdtMethodDef); - - if ( IsMdPrivateScope( pRecImp->GetFlags() ) ) - { - // Trigger additive merge - goto CopyMethodLabel; - } - - // convert rid contained in signature to new scope - IfFailGo(ImportHelper::MergeUpdateTokenInSig( - NULL, // Assembly emit scope. - pMiniMdEmit, // The emit scope. - NULL, NULL, 0, // Import assembly scope information. - pMiniMdImport, // The scope to merge into the emit scope. - pbSig, // signature from the imported scope - pCurTkMap, // Internal token mapping structure. - &qbSig, // [OUT] translated signature - 0, // start from first byte of the signature - 0, // don't care how many bytes consumed - &cbEmit)); // number of bytes write to cbEmit - - hr = ImportHelper::FindMethod( - pMiniMdEmit, - tdEmit, - szName, - (const COR_SIGNATURE *)qbSig.Ptr(), - cbEmit, - &mdEmit); - - bSuppressMergeCheck = pMTD->m_bSuppressMergeCheck || - ((pImportData->m_tkSuppressMergeCheckCtor != mdTokenNil) && - (S_OK == ImportHelper::FindCustomAttributeByToken(pMiniMdImport, - mdImp, pImportData->m_tkSuppressMergeCheckCtor, NULL, 0, &tkCA))); - - if (bSuppressMergeCheck || (tdImport == pImportData->m_pRegMetaImport->m_tdModule)) - { - // global functions! Make sure that we move over the non-duplicate global function - // declaration - // - if (hr == S_OK) - { - // found the duplicate - IfFailGo( VerifyMethod(pImportData, mdImp, mdEmit) ); - } - else - { -CopyMethodLabel: - // not a duplicate! Copy over the - IfFailGo(pMiniMdEmit->AddMethodRecord(&pRecEmit, (RID *)&mdEmit)); - - // copy the method content over - IfFailGo( CopyMethod(pImportData, pRecImp, pRecEmit) ); - - IfFailGo( pMiniMdEmit->AddMethodToTypeDef(RidFromToken(tdEmit), mdEmit)); - - // record the token movement - mdEmit = TokenFromRid(mdEmit, mdtMethodDef); - IfFailGo( pMiniMdEmit->AddMemberDefToHash( - mdEmit, - tdEmit) ); - - mdImp = TokenFromRid(mdImp, mdtMethodDef); - IfFailGo( pCurTkMap->InsertNotFound(mdImp, false, mdEmit, &pTokenRec) ); - - // copy over the children - IfFailGo( CopyParams(pImportData, mdImp, mdEmit) ); - IfFailGo( CopyGenericParams(pImportData, mdImp, mdEmit) ); - - } - } - else - { - if (hr == S_OK) - { - // Good! We are supposed to find a duplicate - IfFailGo( VerifyMethod(pImportData, mdImp, mdEmit) ); - } - else - { - // Oops! The typedef is duplicated but the method is not!! - hr = S_OK; // discard old error; new error will be returned from CheckContinuableError - CheckContinuableErrorEx(META_E_METHD_NOT_FOUND, pImportData, mdImp); - } - - cImport++; - } - } - - // The counts should be the same, unless this is <module> - if (cImport != pMTD->m_cMethods && tdImport != pImportData->m_pRegMetaImport->m_tdModule) - { - CheckContinuableErrorEx(META_E_METHOD_COUNTS, pImportData, tdImport); - // If we are here, the linker says this error is OK. - } -ErrExit: - return hr; -} // HRESULT NEWMERGER::VerifyMethods() - - -//***************************************************************************** -// verify a duplicated method -//***************************************************************************** -HRESULT NEWMERGER::VerifyMethod( - MergeImportData *pImportData, - mdMethodDef mdImp, // [IN] the emit record to fill - mdMethodDef mdEmit) // [IN] the record to import -{ - HRESULT hr; - MethodRec *pRecImp; - MethodRec *pRecEmit; - TOKENREC *pTokenRec; - CMiniMdRW *pMiniMdImport; - CMiniMdRW *pMiniMdEmit; - MDTOKENMAP *pCurTkMap; - - pMiniMdEmit = GetMiniMdEmit(); - pMiniMdImport = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - pCurTkMap = pImportData->m_pMDTokenMap; - - IfFailGo( pCurTkMap->InsertNotFound(mdImp, true, mdEmit, &pTokenRec) ); - - IfFailGo(pMiniMdImport->GetMethodRecord(RidFromToken(mdImp), &pRecImp)); - - // We need to make sure that the impl flags are propagated . - // Rules are: if the first method has miForwardRef flag set but the new method does not, - // we want to disable the miForwardRef flag. If the one found in the emit scope does not have - // miForwardRef set and the second one doesn't either, we want to make sure that the rest of - // impl flags are the same. - // - if ( !IsMiForwardRef( pRecImp->GetImplFlags() ) ) - { - IfFailGo(pMiniMdEmit->GetMethodRecord(RidFromToken(mdEmit), &pRecEmit)); - if (!IsMiForwardRef(pRecEmit->GetImplFlags())) - { - // make sure the rest of ImplFlags are the same - if (pRecEmit->GetImplFlags() != pRecImp->GetImplFlags()) - { - // inconsistent in implflags - CheckContinuableErrorEx(META_E_METHDIMPL_INCONSISTENT, pImportData, mdImp); - } - } - else - { - // propagate the importing ImplFlags - pRecEmit->SetImplFlags(pRecImp->GetImplFlags()); - } - } - - // verify the children - IfFailGo( VerifyParams(pImportData, mdImp, mdEmit) ); - IfFailGo( VerifyGenericParams(pImportData, mdImp, mdEmit) ); - -ErrExit: - return hr; -} // HRESULT NEWMERGER::VerifyMethod() - - -//***************************************************************************** -// Verify Fields -//***************************************************************************** -HRESULT NEWMERGER::VerifyFields( - MergeImportData *pImportData, - mdTypeDef tdImport, - mdTypeDef tdEmit) -{ - HRESULT hr = NOERROR; - CMiniMdRW *pMiniMdImport; - CMiniMdRW *pMiniMdEmit; - FieldRec *pRecImp; - FieldRec *pRecEmit; - mdFieldDef fdImp; - mdFieldDef fdEmit; - ULONG ridStart; - ULONG ridEnd; - ULONG i; - - TypeDefRec *pTypeDefRec; - LPCUTF8 szName; - PCCOR_SIGNATURE pbSig; - ULONG cbSig; - ULONG cbEmit; - CQuickBytes qbSig; - TOKENREC *pTokenRec; - MDTOKENMAP *pCurTkMap; - - MergeTypeData *pMTD; - BOOL bSuppressMergeCheck; - ULONG cImport = 0; // count of non-merge check suppressed fields - mdCustomAttribute tkCA; - - pMiniMdEmit = GetMiniMdEmit(); - pMiniMdImport = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - pCurTkMap = pImportData->m_pMDTokenMap; - - // We know that the filter table is not null here. Tell PREFIX that we know it. - PREFIX_ASSUME( pMiniMdImport->GetFilterTable() != NULL ); - - // Get a count of records in the import scope; prepare to enumerate them. - IfFailGo(pMiniMdImport->GetTypeDefRecord(RidFromToken(tdImport), &pTypeDefRec)); - ridStart = pMiniMdImport->getFieldListOfTypeDef(pTypeDefRec); - IfFailGo(pMiniMdImport->getEndFieldListOfTypeDef(RidFromToken(tdImport), &ridEnd)); - - pMTD = m_rMTDs.Get(RidFromToken(tdEmit)); - - // loop through all fields of the TypeDef - for (i = ridStart; i < ridEnd; i++) - { - IfFailGo(pMiniMdImport->GetFieldRid(i, (ULONG *)&fdImp)); - - // only verify those fields that are marked - if ( pMiniMdImport->GetFilterTable()->IsFieldMarked(TokenFromRid(fdImp, mdtFieldDef)) == false) - continue; - - IfFailGo(pMiniMdImport->GetFieldRecord(fdImp, &pRecImp)); - - if (m_fDupCheck == FALSE && tdImport == pImportData->m_pRegMetaImport->m_tdModule) - { - // No dup check. This is the scenario that we only have one import scope. Just copy over the - // globals. - goto CopyFieldLabel; - } - - IfFailGo(pMiniMdImport->getNameOfField(pRecImp, &szName)); - IfFailGo(pMiniMdImport->getSignatureOfField(pRecImp, &pbSig, &cbSig)); - - if ( IsFdPrivateScope(pRecImp->GetFlags())) - { - // Trigger additive merge - fdImp = TokenFromRid(fdImp, mdtFieldDef); - goto CopyFieldLabel; - } - - // convert rid contained in signature to new scope - IfFailGo(ImportHelper::MergeUpdateTokenInSig( - NULL, // Assembly emit scope. - pMiniMdEmit, // The emit scope. - NULL, NULL, 0, // Import assembly scope information. - pMiniMdImport, // The scope to merge into the emit scope. - pbSig, // signature from the imported scope - pCurTkMap, // Internal token mapping structure. - &qbSig, // [OUT] translated signature - 0, // start from first byte of the signature - 0, // don't care how many bytes consumed - &cbEmit)); // number of bytes write to cbEmit - - hr = ImportHelper::FindField( - pMiniMdEmit, - tdEmit, - szName, - (const COR_SIGNATURE *)qbSig.Ptr(), - cbEmit, - &fdEmit); - - fdImp = TokenFromRid(fdImp, mdtFieldDef); - - bSuppressMergeCheck = - (IsFdStatic(pRecImp->GetFlags()) && pMTD->m_bSuppressMergeCheck) || - ((pImportData->m_tkSuppressMergeCheckCtor != mdTokenNil) && - (S_OK == ImportHelper::FindCustomAttributeByToken(pMiniMdImport, - fdImp, pImportData->m_tkSuppressMergeCheckCtor, NULL, 0, &tkCA))); - - if (bSuppressMergeCheck || (tdImport == pImportData->m_pRegMetaImport->m_tdModule)) - { - // global data! Make sure that we move over the non-duplicate global function - // declaration - // - if (hr == S_OK) - { - // found the duplicate - IfFailGo( pCurTkMap->InsertNotFound(fdImp, true, fdEmit, &pTokenRec) ); - } - else - { -CopyFieldLabel: - // not a duplicate! Copy over the - IfFailGo(pMiniMdEmit->AddFieldRecord(&pRecEmit, (RID *)&fdEmit)); - - // copy the field record over - IfFailGo( CopyField(pImportData, pRecImp, pRecEmit) ); - - IfFailGo( pMiniMdEmit->AddFieldToTypeDef(RidFromToken(tdEmit), fdEmit)); - - // record the token movement - fdEmit = TokenFromRid(fdEmit, mdtFieldDef); - IfFailGo( pMiniMdEmit->AddMemberDefToHash( - fdEmit, - tdEmit) ); - - fdImp = TokenFromRid(fdImp, mdtFieldDef); - IfFailGo( pCurTkMap->InsertNotFound(fdImp, false, fdEmit, &pTokenRec) ); - } - } - else - { - if (hr == S_OK) - { - // Good! We are supposed to find a duplicate - IfFailGo( pCurTkMap->InsertNotFound(fdImp, true, fdEmit, &pTokenRec) ); - } - else - { - // Oops! The typedef is duplicated but the field is not!! - hr = S_OK; // discard old error; new error will be returned from CheckContinuableError - CheckContinuableErrorEx(META_E_FIELD_NOT_FOUND, pImportData, fdImp); - } - - cImport++; - } - } - - // The counts should be the same, unless this is <module> - if (cImport != pMTD->m_cFields && tdImport != pImportData->m_pRegMetaImport->m_tdModule) - { - CheckContinuableErrorEx(META_E_FIELD_COUNTS, pImportData, tdImport); - // If we are here, the linker says this error is OK. - } - -ErrExit: - return hr; -} // HRESULT NEWMERGER::VerifyFields() - - -//***************************************************************************** -// Verify Events -//***************************************************************************** -HRESULT NEWMERGER::VerifyEvents( - MergeImportData *pImportData, - mdTypeDef tdImport, - mdTypeDef tdEmit) -{ - HRESULT hr = NOERROR; - CMiniMdRW *pMiniMdImport; - CMiniMdRW *pMiniMdEmit; - RID ridEventMap, ridEventMapEmit; - EventMapRec *pEventMapRec; - EventRec *pRecImport; - ULONG ridStart; - ULONG ridEnd; - ULONG i; - mdEvent evImport; - mdEvent evEmit; - TOKENREC *pTokenRec; - LPCUTF8 szName; - mdToken tkType; - MDTOKENMAP *pCurTkMap; - - EventMapRec *pEventMapEmit; - EventRec *pRecEmit; - MergeTypeData *pMTD; - BOOL bSuppressMergeCheck; - ULONG cImport = 0; // count of non-merge check suppressed events - mdCustomAttribute tkCA; - - pMiniMdEmit = GetMiniMdEmit(); - pMiniMdImport = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - pCurTkMap = pImportData->m_pMDTokenMap; - - // We know that the filter table is not null here. Tell PREFIX that we know it. - PREFIX_ASSUME( pMiniMdImport->GetFilterTable() != NULL ); - - IfFailGo(pMiniMdImport->FindEventMapFor(RidFromToken(tdImport), &ridEventMap)); - if (!InvalidRid(ridEventMap)) - { - // Get a count of records already in emit scope. - IfFailGo(pMiniMdEmit->FindEventMapFor(RidFromToken(tdEmit), &ridEventMapEmit)); - - if (InvalidRid(ridEventMapEmit)) { - // If there is any event, create the eventmap record in the emit scope - // Create new record. - IfFailGo(pMiniMdEmit->AddEventMapRecord(&pEventMapEmit, &ridEventMapEmit)); - - // Set parent. - IfFailGo(pMiniMdEmit->PutToken(TBL_EventMap, EventMapRec::COL_Parent, pEventMapEmit, tdEmit)); - } - - // Get a count of records in the import scope; prepare to enumerate them. - IfFailGo(pMiniMdImport->GetEventMapRecord(ridEventMap, &pEventMapRec)); - ridStart = pMiniMdImport->getEventListOfEventMap(pEventMapRec); - IfFailGo(pMiniMdImport->getEndEventListOfEventMap(ridEventMap, &ridEnd)); - - pMTD = m_rMTDs.Get(RidFromToken(tdEmit)); - - for (i = ridStart; i < ridEnd; i++) - { - // get the property rid - IfFailGo(pMiniMdImport->GetEventRid(i, (ULONG *)&evImport)); - - // only verify those Events that are marked - if ( pMiniMdImport->GetFilterTable()->IsEventMarked(TokenFromRid(evImport, mdtEvent)) == false) - continue; - - IfFailGo(pMiniMdImport->GetEventRecord(evImport, &pRecImport)); - IfFailGo(pMiniMdImport->getNameOfEvent(pRecImport, &szName)); - tkType = pMiniMdImport->getEventTypeOfEvent( pRecImport ); - IfFailGo( pCurTkMap->Remap(tkType, &tkType) ); - evImport = TokenFromRid( evImport, mdtEvent); - - hr = ImportHelper::FindEvent( - pMiniMdEmit, - tdEmit, - szName, - &evEmit); - - bSuppressMergeCheck = pMTD->m_bSuppressMergeCheck || - ((pImportData->m_tkSuppressMergeCheckCtor != mdTokenNil) && - (S_OK == ImportHelper::FindCustomAttributeByToken(pMiniMdImport, - evImport, pImportData->m_tkSuppressMergeCheckCtor, NULL, 0, &tkCA))); - - if (bSuppressMergeCheck) - { - - if (hr == S_OK ) - { - // Good. We found the matching event when we have a duplicate typedef - IfFailGo( pCurTkMap->InsertNotFound(evImport, true, evEmit, &pTokenRec) ); - } - else - { - // not a duplicate! Copy over the - IfFailGo(pMiniMdEmit->AddEventRecord(&pRecEmit, (RID *)&evEmit)); - - // copy the event record over - IfFailGo( CopyEvent(pImportData, pRecImport, pRecEmit) ); - - // Add Event to the EventMap. - IfFailGo( pMiniMdEmit->AddEventToEventMap(ridEventMapEmit, evEmit) ); - - // record the token movement - evEmit = TokenFromRid(evEmit, mdtEvent); - - IfFailGo( pCurTkMap->InsertNotFound(evImport, false, evEmit, &pTokenRec) ); - - // copy over the method semantics - IfFailGo( CopyMethodSemantics(pImportData, evImport, evEmit) ); - } - } - else - { - if (hr == S_OK ) - { - // Good. We found the matching event when we have a duplicate typedef - IfFailGo( pCurTkMap->InsertNotFound(evImport, true, evEmit, &pTokenRec) ); - } - else - { - // Oops! The typedef is duplicated but the event is not!! - hr = S_OK; // discard old error; new error will be returned from CheckContinuableError - CheckContinuableErrorEx(META_E_EVENT_NOT_FOUND, pImportData, evImport); - - } - - cImport++; - } - } - - // The counts should be the same, unless this is <module> - if (cImport != pMTD->m_cEvents && tdImport != pImportData->m_pRegMetaImport->m_tdModule) - { - CheckContinuableErrorEx(META_E_EVENT_COUNTS, pImportData, tdImport); - // If we are here, the linker says this error is OK. - } - } -ErrExit: - return hr; -} // HRESULT NEWMERGER::VerifyEvents() - - -//***************************************************************************** -// Verify Properties -//***************************************************************************** -HRESULT NEWMERGER::VerifyProperties( - MergeImportData *pImportData, - mdTypeDef tdImport, - mdTypeDef tdEmit) -{ - HRESULT hr = NOERROR; - CMiniMdRW *pMiniMdImport; - CMiniMdRW *pMiniMdEmit; - RID ridPropertyMap, ridPropertyMapEmit; - PropertyMapRec *pPropertyMapRec; - PropertyRec *pRecImport; - ULONG ridStart; - ULONG ridEnd; - ULONG i; - mdProperty prImp; - mdProperty prEmit; - TOKENREC *pTokenRec; - LPCUTF8 szName; - PCCOR_SIGNATURE pbSig; - ULONG cbSig; - ULONG cbEmit; - CQuickBytes qbSig; - MDTOKENMAP *pCurTkMap; - - PropertyMapRec *pPropertyMapEmit; - PropertyRec *pRecEmit; - MergeTypeData *pMTD; - BOOL bSuppressMergeCheck; - ULONG cImport = 0; // count of non-merge check suppressed properties - mdCustomAttribute tkCA; - - pMiniMdEmit = GetMiniMdEmit(); - pMiniMdImport = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - pCurTkMap = pImportData->m_pMDTokenMap; - - // We know that the filter table is not null here. Tell PREFIX that we know it. - PREFIX_ASSUME( pMiniMdImport->GetFilterTable() != NULL ); - - IfFailGo(pMiniMdImport->FindPropertyMapFor(RidFromToken(tdImport), &ridPropertyMap)); - if (!InvalidRid(ridPropertyMap)) - { - // Get a count of records already in emit scope. - IfFailGo(pMiniMdEmit->FindPropertyMapFor(RidFromToken(tdEmit), &ridPropertyMapEmit)); - - if (InvalidRid(ridPropertyMapEmit)) - { - // If there is any event, create the PropertyMap record in the emit scope - // Create new record. - IfFailGo(pMiniMdEmit->AddPropertyMapRecord(&pPropertyMapEmit, &ridPropertyMapEmit)); - - // Set parent. - IfFailGo(pMiniMdEmit->PutToken(TBL_PropertyMap, PropertyMapRec::COL_Parent, pPropertyMapEmit, tdEmit)); - } - - // Get a count of records in the import scope; prepare to enumerate them. - IfFailGo(pMiniMdImport->GetPropertyMapRecord(ridPropertyMap, &pPropertyMapRec)); - ridStart = pMiniMdImport->getPropertyListOfPropertyMap(pPropertyMapRec); - IfFailGo(pMiniMdImport->getEndPropertyListOfPropertyMap(ridPropertyMap, &ridEnd)); - - pMTD = m_rMTDs.Get(RidFromToken(tdEmit)); - - for (i = ridStart; i < ridEnd; i++) - { - // get the property rid - IfFailGo(pMiniMdImport->GetPropertyRid(i, (ULONG *)&prImp)); - - // only verify those Properties that are marked - if ( pMiniMdImport->GetFilterTable()->IsPropertyMarked(TokenFromRid(prImp, mdtProperty)) == false) - continue; - - IfFailGo(pMiniMdImport->GetPropertyRecord(prImp, &pRecImport)); - IfFailGo(pMiniMdImport->getNameOfProperty(pRecImport, &szName)); - IfFailGo(pMiniMdImport->getTypeOfProperty(pRecImport, &pbSig, &cbSig)); - prImp = TokenFromRid( prImp, mdtProperty); - - // convert rid contained in signature to new scope - IfFailGo( ImportHelper::MergeUpdateTokenInSig( - NULL, // Emit assembly. - pMiniMdEmit, // The emit scope. - NULL, NULL, 0, // Import assembly scope information. - pMiniMdImport, // The scope to merge into the emit scope. - pbSig, // signature from the imported scope - pCurTkMap, // Internal token mapping structure. - &qbSig, // [OUT] translated signature - 0, // start from first byte of the signature - 0, // don't care how many bytes consumed - &cbEmit) ); // number of bytes write to cbEmit - - hr = ImportHelper::FindProperty( - pMiniMdEmit, - tdEmit, - szName, - (PCCOR_SIGNATURE) qbSig.Ptr(), - cbEmit, - &prEmit); - - bSuppressMergeCheck = pMTD->m_bSuppressMergeCheck || - ((pImportData->m_tkSuppressMergeCheckCtor != mdTokenNil) && - (S_OK == ImportHelper::FindCustomAttributeByToken(pMiniMdImport, - prImp, pImportData->m_tkSuppressMergeCheckCtor, NULL, 0, &tkCA))); - - if (bSuppressMergeCheck) - { - if (hr == S_OK) - { - // Good. We found the matching property when we have a duplicate typedef - IfFailGo( pCurTkMap->InsertNotFound(prImp, true, prEmit, &pTokenRec) ); - } - else - { - IfFailGo(pMiniMdEmit->AddPropertyRecord(&pRecEmit, (RID *)&prEmit)); - - // copy the property record over - IfFailGo( CopyProperty(pImportData, pRecImport, pRecEmit) ); - - // Add Property to the PropertyMap. - IfFailGo( pMiniMdEmit->AddPropertyToPropertyMap(ridPropertyMapEmit, prEmit) ); - - // record the token movement - prEmit = TokenFromRid(prEmit, mdtProperty); - - IfFailGo( pCurTkMap->InsertNotFound(prImp, false, prEmit, &pTokenRec) ); - - // copy over the method semantics - IfFailGo( CopyMethodSemantics(pImportData, prImp, prEmit) ); - } - } - else - { - if (hr == S_OK) - { - // Good. We found the matching property when we have a duplicate typedef - IfFailGo( pCurTkMap->InsertNotFound(prImp, true, prEmit, &pTokenRec) ); - } - else - { - hr = S_OK; // discard old error; new error will be returned from CheckContinuableError - CheckContinuableErrorEx(META_E_PROP_NOT_FOUND, pImportData, prImp); - } - - cImport++; - } - } - - // The counts should be the same, unless this is <module> - if (cImport != pMTD->m_cProperties && tdImport != pImportData->m_pRegMetaImport->m_tdModule) - { - CheckContinuableErrorEx(META_E_PROPERTY_COUNTS, pImportData, tdImport); - // If we are here, the linker says this error is OK. - } - } -ErrExit: - return hr; -} // HRESULT NEWMERGER::VerifyProperties() - - -//***************************************************************************** -// Verify Parameters given a Method -//***************************************************************************** -HRESULT NEWMERGER::VerifyParams( - MergeImportData *pImportData, - mdMethodDef mdImport, - mdMethodDef mdEmit) -{ - HRESULT hr = NOERROR; - ParamRec *pRecImport = NULL; - ParamRec *pRecEmit = NULL; - MethodRec *pMethodRec; - CMiniMdRW *pMiniMdImport; - CMiniMdRW *pMiniMdEmit; - ULONG ridStart, ridEnd; - ULONG ridStartEmit, ridEndEmit; - ULONG cImport, cEmit; - ULONG i, j; - mdParamDef pdEmit = 0; - mdParamDef pdImp; - TOKENREC *pTokenRec; - MDTOKENMAP *pCurTkMap; - - pMiniMdEmit = GetMiniMdEmit(); - pMiniMdImport = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - pCurTkMap = pImportData->m_pMDTokenMap; - - // We know that the filter table is not null here. Tell PREFIX that we know it. - PREFIX_ASSUME( pMiniMdImport->GetFilterTable() != NULL ); - - // Get count of params in import scope; prepare to enumerate. - IfFailGo(pMiniMdImport->GetMethodRecord(RidFromToken(mdImport), &pMethodRec)); - ridStart = pMiniMdImport->getParamListOfMethod(pMethodRec); - IfFailGo(pMiniMdImport->getEndParamListOfMethod(RidFromToken(mdImport), &ridEnd)); - cImport = ridEnd - ridStart; - - // Get count of params in emit scope; prepare to enumerate. - IfFailGo(pMiniMdEmit->GetMethodRecord(RidFromToken(mdEmit), &pMethodRec)); - ridStartEmit = pMiniMdEmit->getParamListOfMethod(pMethodRec); - IfFailGo(pMiniMdEmit->getEndParamListOfMethod(RidFromToken(mdEmit), &ridEndEmit)); - cEmit = ridEndEmit - ridStartEmit; - - // The counts should be the same. - if (cImport != cEmit) - { - // That is, unless this is <module>, so get the method's parent. - mdTypeDef tdImport; - IfFailGo(pMiniMdImport->FindParentOfMethodHelper(mdImport, &tdImport)); - if (tdImport != pImportData->m_pRegMetaImport->m_tdModule) - CheckContinuableErrorEx(META_E_PARAM_COUNTS, pImportData, mdImport); - // If we are here, the linker says this error is OK. - } - - // loop through all Parameters - for (i = ridStart; i < ridEnd; i++) - { - // Get the importing param row - IfFailGo(pMiniMdImport->GetParamRid(i, (ULONG *)&pdImp)); - - // only verify those Params that are marked - if ( pMiniMdImport->GetFilterTable()->IsParamMarked(TokenFromRid(pdImp, mdtParamDef)) == false) - continue; - - - IfFailGo(pMiniMdImport->GetParamRecord(pdImp, &pRecImport)); - pdImp = TokenFromRid(pdImp, mdtParamDef); - - // It turns out when we merge a typelib with itself, the emit and import scope - // has different sequence of parameter - // - // find the corresponding emit param row - for (j = ridStartEmit; j < ridEndEmit; j++) - { - IfFailGo(pMiniMdEmit->GetParamRid(j, (ULONG *)&pdEmit)); - IfFailGo(pMiniMdEmit->GetParamRecord(pdEmit, &pRecEmit)); - if (pRecEmit->GetSequence() == pRecImport->GetSequence()) - break; - } - - if (j == ridEndEmit) - { - // did not find the corresponding parameter in the emiting scope - hr = S_OK; // discard old error; new error will be returned from CheckContinuableError - CheckContinuableErrorEx(META_S_PARAM_MISMATCH, pImportData, pdImp); - } - - else - { - _ASSERTE( pRecEmit->GetSequence() == pRecImport->GetSequence() ); - - pdEmit = TokenFromRid(pdEmit, mdtParamDef); - - // record the token movement -#ifdef WE_DONT_NEED_TO_CHECK_NAMES__THEY_DONT_AFFECT_ANYTHING - LPCUTF8 szNameImp; - LPCUTF8 szNameEmit; - IfFailGo(pMiniMdImport->getNameOfParam(pRecImport, &szNameImp)); - IfFailGo(pMiniMdEmit->getNameOfParam(pRecEmit, &szNameEmit)); - if (szNameImp && szNameEmit && strcmp(szNameImp, szNameEmit) != 0) - { - // parameter name doesn't match - CheckContinuableErrorEx(META_S_PARAM_MISMATCH, pImportData, pdImp); - } -#endif - if (pRecEmit->GetFlags() != pRecImport->GetFlags()) - { - // flags doesn't match - CheckContinuableErrorEx(META_S_PARAM_MISMATCH, pImportData, pdImp); - } - - // record token movement. This is a duplicate. - IfFailGo( pCurTkMap->InsertNotFound(pdImp, true, pdEmit, &pTokenRec) ); - } - } - -ErrExit: - return hr; -} // HRESULT NEWMERGER::VerifyParams() - - -//***************************************************************************** -// merging MemberRef -//***************************************************************************** -HRESULT NEWMERGER::MergeMemberRefs( ) -{ - HRESULT hr = NOERROR; - MemberRefRec *pRecImport = NULL; - MemberRefRec *pRecEmit = NULL; - CMiniMdRW *pMiniMdImport; - CMiniMdRW *pMiniMdEmit; - ULONG iCount; - ULONG i; - mdMemberRef mrEmit; - mdMemberRef mrImp; - bool bDuplicate = false; - TOKENREC *pTokenRec; - mdToken tkParentImp; - mdToken tkParentEmit; - - LPCUTF8 szNameImp; - PCCOR_SIGNATURE pbSig; - ULONG cbSig; - ULONG cbEmit; - CQuickBytes qbSig; - - bool isRefOptimizedToDef; - - MergeImportData *pImportData; - MDTOKENMAP *pCurTkMap; - - pMiniMdEmit = GetMiniMdEmit(); - - for (pImportData = m_pImportDataList; pImportData != NULL; pImportData = pImportData->m_pNextImportData) - { - // for each import scope - pMiniMdImport = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - - // We know that the filter table is not null here. Tell PREFIX that we know it. - PREFIX_ASSUME( pMiniMdImport->GetFilterTable() != NULL ); - - // set the current MDTokenMap - pCurTkMap = pImportData->m_pMDTokenMap; - - iCount = pMiniMdImport->getCountMemberRefs(); - - // loop through all MemberRef - for (i = 1; i <= iCount; i++) - { - - // only merge those MemberRefs that are marked - if ( pMiniMdImport->GetFilterTable()->IsMemberRefMarked(TokenFromRid(i, mdtMemberRef)) == false) - continue; - - isRefOptimizedToDef = false; - - // compare it with the emit scope - IfFailGo(pMiniMdImport->GetMemberRefRecord(i, &pRecImport)); - IfFailGo(pMiniMdImport->getNameOfMemberRef(pRecImport, &szNameImp)); - IfFailGo(pMiniMdImport->getSignatureOfMemberRef(pRecImport, &pbSig, &cbSig)); - tkParentImp = pMiniMdImport->getClassOfMemberRef(pRecImport); - - IfFailGo( pCurTkMap->Remap(tkParentImp, &tkParentEmit) ); - - // convert rid contained in signature to new scope - IfFailGo(ImportHelper::MergeUpdateTokenInSig( - NULL, // Assembly emit scope. - pMiniMdEmit, // The emit scope. - NULL, NULL, 0, // Import assembly information. - pMiniMdImport, // The scope to merge into the emit scope. - pbSig, // signature from the imported scope - pCurTkMap, // Internal token mapping structure. - &qbSig, // [OUT] translated signature - 0, // start from first byte of the signature - 0, // don't care how many bytes consumed - &cbEmit)); // number of bytes write to cbEmit - - // We want to know if we can optimize this MemberRef to a FieldDef or MethodDef - if (TypeFromToken(tkParentEmit) == mdtTypeDef && RidFromToken(tkParentEmit) != 0) - { - // The parent of this MemberRef has been successfully optimized to a TypeDef. Then this MemberRef should be - // be able to optimized to a MethodDef or FieldDef unless one of the parent in the inheritance hierachy - // is through TypeRef. Then this MemberRef stay as MemberRef. If This is a VarArg calling convention, then - // we will remap the MemberRef's parent to a MethodDef or stay as TypeRef. - // - mdToken tkParent = tkParentEmit; - mdToken tkMethDefOrFieldDef; - PCCOR_SIGNATURE pbSigTmp = (const COR_SIGNATURE *) qbSig.Ptr(); - - while (TypeFromToken(tkParent) == mdtTypeDef && RidFromToken(tkParent) != 0) - { - TypeDefRec *pRec; - hr = ImportHelper::FindMember(pMiniMdEmit, tkParent, szNameImp, pbSigTmp, cbEmit, &tkMethDefOrFieldDef); - if (hr == S_OK) - { - // We have found a match!! - if (isCallConv(CorSigUncompressCallingConv(pbSigTmp), IMAGE_CEE_CS_CALLCONV_VARARG)) - { - // The found MethodDef token will replace this MemberRef's parent token - _ASSERTE(TypeFromToken(tkMethDefOrFieldDef) == mdtMethodDef); - tkParentEmit = tkMethDefOrFieldDef; - break; - } - else - { - // The found MethodDef/FieldDef token will replace this MemberRef token and we won't introduce a MemberRef - // record. - // - mrEmit = tkMethDefOrFieldDef; - isRefOptimizedToDef = true; - bDuplicate = true; - break; - } - } - - // now walk up to the parent class of tkParent and try to resolve this MemberRef - IfFailGo(pMiniMdEmit->GetTypeDefRecord(RidFromToken(tkParent), &pRec)); - tkParent = pMiniMdEmit->getExtendsOfTypeDef(pRec); - } - - // When we exit the loop, there are several possibilities: - // 1. We found a MethodDef/FieldDef to replace the MemberRef - // 2. We found a MethodDef matches the MemberRef but the MemberRef is VarArg, thus we want to use the MethodDef in the - // parent column but not replacing it. - // 3. We exit because we run out the TypeDef on the parent chain. If it is because we encounter a TypeRef, this TypeRef will - // replace the parent column of the MemberRef. Or we encounter nil token! (This can be unresolved global MemberRef or - // compiler error to put an undefined MemberRef. In this case, we should just use the old tkParentEmit - // on the parent column for the MemberRef. - - if (TypeFromToken(tkParent) == mdtTypeRef && RidFromToken(tkParent) != 0) - { - // we had walked up the parent's chain to resolve it but we have not been successful and got stopped by a TypeRef. - // Then we will use this TypeRef as the parent of the emit MemberRef record - // - tkParentEmit = tkParent; - } - } - else if ((TypeFromToken(tkParentEmit) == mdtMethodDef && - !isCallConv(CorSigUncompressCallingConv(pbSig), IMAGE_CEE_CS_CALLCONV_VARARG)) || - (TypeFromToken(tkParentEmit) == mdtFieldDef)) - { - // If the MemberRef's parent is already a non-vararg MethodDef or FieldDef, we can also - // safely drop the MemberRef - mrEmit = tkParentEmit; - isRefOptimizedToDef = true; - bDuplicate = true; - } - - // If the Ref cannot be optimized to a Def or MemberRef to Def optmization is turned off, do the following. - if (isRefOptimizedToDef == false || !((m_optimizeRefToDef & MDMemberRefToDef) == MDMemberRefToDef)) - { - // does this MemberRef already exist in the emit scope? - if ( m_fDupCheck && ImportHelper::FindMemberRef( - pMiniMdEmit, - tkParentEmit, - szNameImp, - (const COR_SIGNATURE *) qbSig.Ptr(), - cbEmit, - &mrEmit) == S_OK ) - { - // Yes, it does - bDuplicate = true; - } - else - { - // No, it doesn't. Copy it over. - bDuplicate = false; - IfFailGo(pMiniMdEmit->AddMemberRefRecord(&pRecEmit, (RID *)&mrEmit)); - mrEmit = TokenFromRid( mrEmit, mdtMemberRef ); - - // Copy over the MemberRef context - IfFailGo(pMiniMdEmit->PutString(TBL_MemberRef, MemberRefRec::COL_Name, pRecEmit, szNameImp)); - IfFailGo(pMiniMdEmit->PutToken(TBL_MemberRef, MemberRefRec::COL_Class, pRecEmit, tkParentEmit)); - IfFailGo(pMiniMdEmit->PutBlob(TBL_MemberRef, MemberRefRec::COL_Signature, pRecEmit, - qbSig.Ptr(), cbEmit)); - IfFailGo(pMiniMdEmit->AddMemberRefToHash(mrEmit) ); - } - } - // record the token movement - mrImp = TokenFromRid(i, mdtMemberRef); - IfFailGo( pCurTkMap->InsertNotFound(mrImp, bDuplicate, mrEmit, &pTokenRec) ); - } - } - - -ErrExit: - return hr; -} // HRESULT NEWMERGER::MergeMemberRefs() - - -//***************************************************************************** -// merge interface impl -//***************************************************************************** -HRESULT NEWMERGER::MergeInterfaceImpls( ) -{ - HRESULT hr = NOERROR; - InterfaceImplRec *pRecImport = NULL; - InterfaceImplRec *pRecEmit = NULL; - CMiniMdRW *pMiniMdImport; - CMiniMdRW *pMiniMdEmit; - ULONG iCount; - ULONG i; - mdTypeDef tkParent; - mdInterfaceImpl iiEmit; - bool bDuplicate; - TOKENREC *pTokenRec; - - MergeImportData *pImportData; - MDTOKENMAP *pCurTkMap; - - pMiniMdEmit = GetMiniMdEmit(); - - for (pImportData = m_pImportDataList; pImportData != NULL; pImportData = pImportData->m_pNextImportData) - { - // for each import scope - pMiniMdImport = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - - // We know that the filter table is not null here. Tell PREFIX that we know it. - PREFIX_ASSUME( pMiniMdImport->GetFilterTable() != NULL ); - - // set the current MDTokenMap - pCurTkMap = pImportData->m_pMDTokenMap; - iCount = pMiniMdImport->getCountInterfaceImpls(); - - // loop through all InterfaceImpl - for (i = 1; i <= iCount; i++) - { - // only merge those InterfaceImpls that are marked - if ( pMiniMdImport->GetFilterTable()->IsInterfaceImplMarked(TokenFromRid(i, mdtInterfaceImpl)) == false) - continue; - - // compare it with the emit scope - IfFailGo(pMiniMdImport->GetInterfaceImplRecord(i, &pRecImport)); - tkParent = pMiniMdImport->getClassOfInterfaceImpl(pRecImport); - - // does this TypeRef already exist in the emit scope? - if ( pCurTkMap->Find(tkParent, &pTokenRec) ) - { - if ( pTokenRec->m_isDuplicate ) - { - // parent in the emit scope - mdToken tkParentEmit; - mdToken tkInterface; - - // remap the typedef token - tkParentEmit = pTokenRec->m_tkTo; - - // remap the implemented interface token - tkInterface = pMiniMdImport->getInterfaceOfInterfaceImpl(pRecImport); - IfFailGo( pCurTkMap->Remap( tkInterface, &tkInterface) ); - - // Set duplicate flag - bDuplicate = true; - - // find the corresponding interfaceimpl in the emit scope - if ( ImportHelper::FindInterfaceImpl(pMiniMdEmit, tkParentEmit, tkInterface, &iiEmit) != S_OK ) - { - // bad state!! We have a duplicate typedef but the interface impl is not the same!! - - // continuable error - CheckContinuableErrorEx( - META_E_INTFCEIMPL_NOT_FOUND, - pImportData, - TokenFromRid(i, mdtInterfaceImpl)); - - iiEmit = mdTokenNil; - } - } - else - { - // No, it doesn't. Copy it over. - bDuplicate = false; - IfFailGo(pMiniMdEmit->AddInterfaceImplRecord(&pRecEmit, (RID *)&iiEmit)); - - // copy the interfaceimp record over - IfFailGo( CopyInterfaceImpl( pRecEmit, pImportData, pRecImport) ); - } - } - else - { - _ASSERTE( !"bad state!"); - IfFailGo( META_E_BADMETADATA ); - } - - // record the token movement - IfFailGo( pCurTkMap->InsertNotFound( - TokenFromRid(i, mdtInterfaceImpl), - bDuplicate, - TokenFromRid( iiEmit, mdtInterfaceImpl ), - &pTokenRec) ); - } - } - - -ErrExit: - return hr; -} // HRESULT NEWMERGER::MergeInterfaceImpls() - - -//***************************************************************************** -// merge all of the constant for field, property, and parameter -//***************************************************************************** -HRESULT NEWMERGER::MergeConstants() -{ - HRESULT hr = NOERROR; - ConstantRec *pRecImport = NULL; - ConstantRec *pRecEmit = NULL; - CMiniMdRW *pMiniMdImport; - CMiniMdRW *pMiniMdEmit; - ULONG iCount; - ULONG i; - ULONG csEmit; // constant value is not a token - mdToken tkParentImp; - TOKENREC *pTokenRec; - void const *pValue; - ULONG cbBlob; -#if _DEBUG - ULONG typeParent; -#endif // _DEBUG - - MergeImportData *pImportData; - MDTOKENMAP *pCurTkMap; - - pMiniMdEmit = GetMiniMdEmit(); - - for (pImportData = m_pImportDataList; pImportData != NULL; pImportData = pImportData->m_pNextImportData) - { - // for each import scope - pMiniMdImport = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - - // We know that the filter table is not null here. Tell PREFIX that we know it. - PREFIX_ASSUME( pMiniMdImport->GetFilterTable() != NULL ); - - // set the current MDTokenMap - pCurTkMap = pImportData->m_pMDTokenMap; - iCount = pMiniMdImport->getCountConstants(); - - // loop through all Constants - for (i = 1; i <= iCount; i++) - { - // compare it with the emit scope - IfFailGo(pMiniMdImport->GetConstantRecord(i, &pRecImport)); - tkParentImp = pMiniMdImport->getParentOfConstant(pRecImport); - - // only move those constant over if their parents are marked - // If MDTOKENMAP::Find returns false, we don't need to copy the constant value over - if ( pCurTkMap->Find(tkParentImp, &pTokenRec) ) - { - // If the parent is duplicated, no need to move over the constant value - if ( !pTokenRec->m_isDuplicate ) - { - IfFailGo(pMiniMdEmit->AddConstantRecord(&pRecEmit, &csEmit)); - pRecEmit->SetType(pRecImport->GetType()); - - // set the parent - IfFailGo( pMiniMdEmit->PutToken(TBL_Constant, ConstantRec::COL_Parent, pRecEmit, pTokenRec->m_tkTo) ); - - // move over the constant blob value - IfFailGo(pMiniMdImport->getValueOfConstant(pRecImport, (const BYTE **)&pValue, &cbBlob)); - IfFailGo( pMiniMdEmit->PutBlob(TBL_Constant, ConstantRec::COL_Value, pRecEmit, pValue, cbBlob) ); - IfFailGo( pMiniMdEmit->AddConstantToHash(csEmit) ); - } - else - { - // <TODO>@FUTURE: more verification on the duplicate??</TODO> - } - } -#if _DEBUG - // Include this block only under Debug build. The reason is that - // the linker chooses all the errors that we report (such as unmatched MethodDef or FieldDef) - // as a continuable error. It is likely to hit this else while the tkparentImp is marked if there - // is any error reported earlier!! - else - { - typeParent = TypeFromToken(tkParentImp); - if (typeParent == mdtFieldDef) - { - // FieldDef should not be marked. - if ( pMiniMdImport->GetFilterTable()->IsFieldMarked(tkParentImp) == false) - continue; - } - else if (typeParent == mdtParamDef) - { - // ParamDef should not be marked. - if ( pMiniMdImport->GetFilterTable()->IsParamMarked(tkParentImp) == false) - continue; - } - else - { - _ASSERTE(typeParent == mdtProperty); - // Property should not be marked. - if ( pMiniMdImport->GetFilterTable()->IsPropertyMarked(tkParentImp) == false) - continue; - } - - // If we come to here, we have a constant whose parent is marked but we could not - // find it in the map!! Bad state. - - _ASSERTE(!"Ignore this error if you have seen error reported earlier! Otherwise bad token map or bad metadata!"); - } -#endif // _DEBUG - // Note that we don't need to record the token movement since constant is not a valid token kind. - } - } - -ErrExit: - return hr; -} // HRESULT NEWMERGER::MergeConstants() - - -//***************************************************************************** -// Merge field marshal information -//***************************************************************************** -HRESULT NEWMERGER::MergeFieldMarshals() -{ - HRESULT hr = NOERROR; - FieldMarshalRec *pRecImport = NULL; - FieldMarshalRec *pRecEmit = NULL; - CMiniMdRW *pMiniMdImport; - CMiniMdRW *pMiniMdEmit; - ULONG iCount; - ULONG i; - ULONG fmEmit; // FieldMarhsal is not a token - mdToken tkParentImp; - TOKENREC *pTokenRec; - void const *pValue; - ULONG cbBlob; -#if _DEBUG - ULONG typeParent; -#endif // _DEBUG - - MergeImportData *pImportData; - MDTOKENMAP *pCurTkMap; - - pMiniMdEmit = GetMiniMdEmit(); - - for (pImportData = m_pImportDataList; pImportData != NULL; pImportData = pImportData->m_pNextImportData) - { - // for each import scope - pMiniMdImport = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - - // We know that the filter table is not null here. Tell PREFIX that we know it. - PREFIX_ASSUME( pMiniMdImport->GetFilterTable() != NULL ); - - // set the current MDTokenMap - pCurTkMap = pImportData->m_pMDTokenMap; - iCount = pMiniMdImport->getCountFieldMarshals(); - - // loop through all TypeRef - for (i = 1; i <= iCount; i++) - { - // compare it with the emit scope - IfFailGo(pMiniMdImport->GetFieldMarshalRecord(i, &pRecImport)); - tkParentImp = pMiniMdImport->getParentOfFieldMarshal(pRecImport); - - // We want to merge only those field marshals that parents are marked. - // Find will return false if the parent is not marked - // - if ( pCurTkMap->Find(tkParentImp, &pTokenRec) ) - { - // If the parent is duplicated, no need to move over the constant value - if ( !pTokenRec->m_isDuplicate ) - { - IfFailGo(pMiniMdEmit->AddFieldMarshalRecord(&pRecEmit, &fmEmit)); - - // set the parent - IfFailGo( pMiniMdEmit->PutToken( - TBL_FieldMarshal, - FieldMarshalRec::COL_Parent, - pRecEmit, - pTokenRec->m_tkTo) ); - - // move over the constant blob value - IfFailGo(pMiniMdImport->getNativeTypeOfFieldMarshal(pRecImport, (const BYTE **)&pValue, &cbBlob)); - IfFailGo( pMiniMdEmit->PutBlob(TBL_FieldMarshal, FieldMarshalRec::COL_NativeType, pRecEmit, pValue, cbBlob) ); - IfFailGo( pMiniMdEmit->AddFieldMarshalToHash(fmEmit) ); - - } - else - { - // <TODO>@FUTURE: more verification on the duplicate??</TODO> - } - } -#if _DEBUG - else - { - typeParent = TypeFromToken(tkParentImp); - - if (typeParent == mdtFieldDef) - { - // FieldDefs should not be marked - if ( pMiniMdImport->GetFilterTable()->IsFieldMarked(tkParentImp) == false) - continue; - } - else - { - _ASSERTE(typeParent == mdtParamDef); - // ParamDefs should not be marked - if ( pMiniMdImport->GetFilterTable()->IsParamMarked(tkParentImp) == false) - continue; - } - - // If we come to here, that is we have a FieldMarshal whose parent is marked and we don't find it - // in the map!!! - - // either bad lookup map or bad metadata - _ASSERTE(!"Ignore this assert if you have seen error reported earlier. Otherwise, it is bad state!"); - } -#endif // _DEBUG - } - // Note that we don't need to record the token movement since FieldMarshal is not a valid token kind. - } - -ErrExit: - return hr; -} // HRESULT NEWMERGER::MergeFieldMarshals() - - -//***************************************************************************** -// Merge class layout information -//***************************************************************************** -HRESULT NEWMERGER::MergeClassLayouts() -{ - HRESULT hr = NOERROR; - ClassLayoutRec *pRecImport = NULL; - ClassLayoutRec *pRecEmit = NULL; - CMiniMdRW *pMiniMdImport; - CMiniMdRW *pMiniMdEmit; - ULONG iCount; - ULONG i; - ULONG iRecord; // class layout is not a token - mdToken tkParentImp; - TOKENREC *pTokenRec; - RID ridClassLayout; - - MergeImportData *pImportData; - MDTOKENMAP *pCurTkMap; - - pMiniMdEmit = GetMiniMdEmit(); - - for (pImportData = m_pImportDataList; pImportData != NULL; pImportData = pImportData->m_pNextImportData) - { - // for each import scope - pMiniMdImport = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - - // We know that the filter table is not null here. Tell PREFIX that we know it. - PREFIX_ASSUME( pMiniMdImport->GetFilterTable() != NULL ); - - // set the current MDTokenMap - pCurTkMap = pImportData->m_pMDTokenMap; - iCount = pMiniMdImport->getCountClassLayouts(); - - // loop through all TypeRef - for (i = 1; i <= iCount; i++) - { - // compare it with the emit scope - IfFailGo(pMiniMdImport->GetClassLayoutRecord(i, &pRecImport)); - tkParentImp = pMiniMdImport->getParentOfClassLayout(pRecImport); - - // only merge those TypeDefs that are marked - if ( pMiniMdImport->GetFilterTable()->IsTypeDefMarked(tkParentImp) == false) - continue; - - if ( pCurTkMap->Find(tkParentImp, &pTokenRec) ) - { - if ( !pTokenRec->m_isDuplicate ) - { - // If the parent is not duplicated, just copy over the classlayout information - IfFailGo(pMiniMdEmit->AddClassLayoutRecord(&pRecEmit, &iRecord)); - - // copy over the fix part information - pRecEmit->Copy(pRecImport); - IfFailGo( pMiniMdEmit->PutToken(TBL_ClassLayout, ClassLayoutRec::COL_Parent, pRecEmit, pTokenRec->m_tkTo)); - IfFailGo( pMiniMdEmit->AddClassLayoutToHash(iRecord) ); - } - else - { - - IfFailGo(pMiniMdEmit->FindClassLayoutHelper(pTokenRec->m_tkTo, &ridClassLayout)); - - if (InvalidRid(ridClassLayout)) - { - // class is duplicated but not class layout info - CheckContinuableErrorEx(META_E_CLASS_LAYOUT_INCONSISTENT, pImportData, tkParentImp); - } - else - { - IfFailGo(pMiniMdEmit->GetClassLayoutRecord(RidFromToken(ridClassLayout), &pRecEmit)); - if (pMiniMdImport->getPackingSizeOfClassLayout(pRecImport) != pMiniMdEmit->getPackingSizeOfClassLayout(pRecEmit) || - pMiniMdImport->getClassSizeOfClassLayout(pRecImport) != pMiniMdEmit->getClassSizeOfClassLayout(pRecEmit) ) - { - CheckContinuableErrorEx(META_E_CLASS_LAYOUT_INCONSISTENT, pImportData, tkParentImp); - } - } - } - } - else - { - // bad lookup map - _ASSERTE( !"bad state!"); - IfFailGo( META_E_BADMETADATA ); - } - // no need to record the index movement. Classlayout is not a token. - } - } -ErrExit: - return hr; -} // HRESULT NEWMERGER::MergeClassLayouts() - -//***************************************************************************** -// Merge field layout information -//***************************************************************************** -HRESULT NEWMERGER::MergeFieldLayouts() -{ - HRESULT hr = NOERROR; - FieldLayoutRec *pRecImport = NULL; - FieldLayoutRec *pRecEmit = NULL; - CMiniMdRW *pMiniMdImport; - CMiniMdRW *pMiniMdEmit; - ULONG iCount; - ULONG i; - ULONG iRecord; // field layout2 is not a token. - mdToken tkFieldImp; - TOKENREC *pTokenRec; - - MergeImportData *pImportData; - MDTOKENMAP *pCurTkMap; - - pMiniMdEmit = GetMiniMdEmit(); - - for (pImportData = m_pImportDataList; pImportData != NULL; pImportData = pImportData->m_pNextImportData) - { - // for each import scope - pMiniMdImport = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - - // We know that the filter table is not null here. Tell PREFIX that we know it. - PREFIX_ASSUME( pMiniMdImport->GetFilterTable() != NULL ); - - // set the current MDTokenMap - pCurTkMap = pImportData->m_pMDTokenMap; - iCount = pMiniMdImport->getCountFieldLayouts(); - - // loop through all FieldLayout records. - for (i = 1; i <= iCount; i++) - { - // compare it with the emit scope - IfFailGo(pMiniMdImport->GetFieldLayoutRecord(i, &pRecImport)); - tkFieldImp = pMiniMdImport->getFieldOfFieldLayout(pRecImport); - - // only merge those FieldDefs that are marked - if ( pMiniMdImport->GetFilterTable()->IsFieldMarked(tkFieldImp) == false) - continue; - - if ( pCurTkMap->Find(tkFieldImp, &pTokenRec) ) - { - if ( !pTokenRec->m_isDuplicate ) - { - // If the Field is not duplicated, just copy over the FieldLayout information - IfFailGo(pMiniMdEmit->AddFieldLayoutRecord(&pRecEmit, &iRecord)); - - // copy over the fix part information - pRecEmit->Copy(pRecImport); - IfFailGo( pMiniMdEmit->PutToken(TBL_FieldLayout, FieldLayoutRec::COL_Field, pRecEmit, pTokenRec->m_tkTo)); - IfFailGo( pMiniMdEmit->AddFieldLayoutToHash(iRecord) ); - } - else - { - // <TODO>@FUTURE: more verification??</TODO> - } - } - else - { - // bad lookup map - _ASSERTE( !"bad state!"); - IfFailGo( META_E_BADMETADATA ); - } - // no need to record the index movement. fieldlayout2 is not a token. - } - } - -ErrExit: - return hr; -} // HRESULT NEWMERGER::MergeFieldLayouts() - - -//***************************************************************************** -// Merge field RVAs -//***************************************************************************** -HRESULT NEWMERGER::MergeFieldRVAs() -{ - HRESULT hr = NOERROR; - FieldRVARec *pRecImport = NULL; - FieldRVARec *pRecEmit = NULL; - CMiniMdRW *pMiniMdImport; - CMiniMdRW *pMiniMdEmit; - ULONG iCount; - ULONG i; - ULONG iRecord; // FieldRVA is not a token. - mdToken tkFieldImp; - TOKENREC *pTokenRec; - - MergeImportData *pImportData; - MDTOKENMAP *pCurTkMap; - - pMiniMdEmit = GetMiniMdEmit(); - - for (pImportData = m_pImportDataList; pImportData != NULL; pImportData = pImportData->m_pNextImportData) - { - // for each import scope - pMiniMdImport = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - - // We know that the filter table is not null here. Tell PREFIX that we know it. - PREFIX_ASSUME( pMiniMdImport->GetFilterTable() != NULL ); - - // set the current MDTokenMap - pCurTkMap = pImportData->m_pMDTokenMap; - iCount = pMiniMdImport->getCountFieldRVAs(); - - // loop through all FieldRVA records. - for (i = 1; i <= iCount; i++) - { - // compare it with the emit scope - IfFailGo(pMiniMdImport->GetFieldRVARecord(i, &pRecImport)); - tkFieldImp = pMiniMdImport->getFieldOfFieldRVA(pRecImport); - - // only merge those FieldDefs that are marked - if ( pMiniMdImport->GetFilterTable()->IsFieldMarked(TokenFromRid(tkFieldImp, mdtFieldDef)) == false) - continue; - - if ( pCurTkMap->Find(tkFieldImp, &pTokenRec) ) - { - if ( !pTokenRec->m_isDuplicate ) - { - // If the Field is not duplicated, just copy over the FieldRVA information - IfFailGo(pMiniMdEmit->AddFieldRVARecord(&pRecEmit, &iRecord)); - - // copy over the fix part information - pRecEmit->Copy(pRecImport); - IfFailGo( pMiniMdEmit->PutToken(TBL_FieldRVA, FieldRVARec::COL_Field, pRecEmit, pTokenRec->m_tkTo)); - IfFailGo( pMiniMdEmit->AddFieldRVAToHash(iRecord) ); - } - else - { - // <TODO>@FUTURE: more verification??</TODO> - } - } - else - { - // bad lookup map - _ASSERTE( !"bad state!"); - IfFailGo( META_E_BADMETADATA ); - } - // no need to record the index movement. FieldRVA is not a token. - } - } - -ErrExit: - return hr; -} // HRESULT NEWMERGER::MergeFieldRVAs() - - -//***************************************************************************** -// Merge MethodImpl information -//***************************************************************************** -HRESULT NEWMERGER::MergeMethodImpls() -{ - HRESULT hr = NOERROR; - MethodImplRec *pRecImport = NULL; - MethodImplRec *pRecEmit = NULL; - CMiniMdRW *pMiniMdImport; - CMiniMdRW *pMiniMdEmit; - ULONG iCount; - ULONG i; - RID iRecord; - mdTypeDef tkClassImp; - mdToken tkBodyImp; - mdToken tkDeclImp; - TOKENREC *pTokenRecClass; - mdToken tkBodyEmit; - mdToken tkDeclEmit; - - MergeImportData *pImportData; - MDTOKENMAP *pCurTkMap; - - pMiniMdEmit = GetMiniMdEmit(); - - for (pImportData = m_pImportDataList; pImportData != NULL; pImportData = pImportData->m_pNextImportData) - { - // for each import scope - pMiniMdImport = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - - // We know that the filter table is not null here. Tell PREFIX that we know it. - PREFIX_ASSUME( pMiniMdImport->GetFilterTable() != NULL ); - - // set the current MDTokenMap - pCurTkMap = pImportData->m_pMDTokenMap; - iCount = pMiniMdImport->getCountMethodImpls(); - - // loop through all the MethodImpls. - for (i = 1; i <= iCount; i++) - { - // only merge those MethodImpls that are marked. - if ( pMiniMdImport->GetFilterTable()->IsMethodImplMarked(i) == false) - continue; - - // compare it with the emit scope - IfFailGo(pMiniMdImport->GetMethodImplRecord(i, &pRecImport)); - tkClassImp = pMiniMdImport->getClassOfMethodImpl(pRecImport); - tkBodyImp = pMiniMdImport->getMethodBodyOfMethodImpl(pRecImport); - tkDeclImp = pMiniMdImport->getMethodDeclarationOfMethodImpl(pRecImport); - - if ( pCurTkMap->Find(tkClassImp, &pTokenRecClass)) - { - // If the TypeDef is duplicated, no need to move over the MethodImpl record. - if ( !pTokenRecClass->m_isDuplicate ) - { - // Create a new record and set the data. - - // <TODO>@FUTURE: We might want to consider changing the error for the remap into a continuable error. - // Because we probably can continue merging for more data...</TODO> - - IfFailGo( pCurTkMap->Remap(tkBodyImp, &tkBodyEmit) ); - IfFailGo( pCurTkMap->Remap(tkDeclImp, &tkDeclEmit) ); - IfFailGo(pMiniMdEmit->AddMethodImplRecord(&pRecEmit, &iRecord)); - IfFailGo( pMiniMdEmit->PutToken(TBL_MethodImpl, MethodImplRec::COL_Class, pRecEmit, pTokenRecClass->m_tkTo) ); - IfFailGo( pMiniMdEmit->PutToken(TBL_MethodImpl, MethodImplRec::COL_MethodBody, pRecEmit, tkBodyEmit) ); - IfFailGo( pMiniMdEmit->PutToken(TBL_MethodImpl, MethodImplRec::COL_MethodDeclaration, pRecEmit, tkDeclEmit) ); - IfFailGo( pMiniMdEmit->AddMethodImplToHash(iRecord) ); - } - else - { - // <TODO>@FUTURE: more verification on the duplicate??</TODO> - } - // No need to record the token movement, MethodImpl is not a token. - } - else - { - // either bad lookup map or bad metadata - _ASSERTE(!"bad state"); - IfFailGo( META_E_BADMETADATA ); - } - } - } -ErrExit: - return hr; -} // HRESULT NEWMERGER::MergeMethodImpls() - - -//***************************************************************************** -// Merge PInvoke -//***************************************************************************** -HRESULT NEWMERGER::MergePinvoke() -{ - HRESULT hr = NOERROR; - ImplMapRec *pRecImport = NULL; - ImplMapRec *pRecEmit = NULL; - CMiniMdRW *pMiniMdImport; - CMiniMdRW *pMiniMdEmit; - ULONG iCount; - ULONG i; - mdModuleRef mrImp; - mdModuleRef mrEmit; - mdMethodDef mdImp; - RID mdImplMap; - TOKENREC *pTokenRecMR; - TOKENREC *pTokenRecMD; - - USHORT usMappingFlags; - LPCUTF8 szImportName; - - MergeImportData *pImportData; - MDTOKENMAP *pCurTkMap; - - pMiniMdEmit = GetMiniMdEmit(); - - for (pImportData = m_pImportDataList; pImportData != NULL; pImportData = pImportData->m_pNextImportData) - { - // for each import scope - pMiniMdImport = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - - // We know that the filter table is not null here. Tell PREFIX that we know it. - PREFIX_ASSUME( pMiniMdImport->GetFilterTable() != NULL ); - - // set the current MDTokenMap - pCurTkMap = pImportData->m_pMDTokenMap; - iCount = pMiniMdImport->getCountImplMaps(); - - // loop through all ImplMaps - for (i = 1; i <= iCount; i++) - { - // compare it with the emit scope - IfFailGo(pMiniMdImport->GetImplMapRecord(i, &pRecImport)); - - // Get the MethodDef token in the new space. - mdImp = pMiniMdImport->getMemberForwardedOfImplMap(pRecImport); - - // only merge those MethodDefs that are marked - if ( pMiniMdImport->GetFilterTable()->IsMethodMarked(mdImp) == false) - continue; - - // Get the ModuleRef token in the new space. - mrImp = pMiniMdImport->getImportScopeOfImplMap(pRecImport); - - // map the token to the new scope - if (pCurTkMap->Find(mrImp, &pTokenRecMR) == false) - { - // This should never fire unless the module refs weren't merged - // before this code ran. - _ASSERTE(!"Parent ModuleRef not found in MERGER::MergePinvoke. Bad state!"); - IfFailGo( META_E_BADMETADATA ); - } - - // If the ModuleRef has been remapped to the "module token", we need to undo that - // for the pinvokeimpl. A pinvoke can only have a ModuleRef for the ImportScope. - mrEmit = pTokenRecMR->m_tkTo; - if (mrEmit == MODULEDEFTOKEN) - { // Yes, the ModuleRef has been remapped to the module token. So, - // find the ModuleRef in the output scope; if it is not found, add - // it. - ModuleRefRec *pModRefImport; - LPCUTF8 szNameImp; - IfFailGo(pMiniMdImport->GetModuleRefRecord(RidFromToken(mrImp), &pModRefImport)); - IfFailGo(pMiniMdImport->getNameOfModuleRef(pModRefImport, &szNameImp)); - - // does this ModuleRef already exist in the emit scope? - hr = ImportHelper::FindModuleRef(pMiniMdEmit, - szNameImp, - &mrEmit); - - if (hr == CLDB_E_RECORD_NOTFOUND) - { // No, it doesn't. Copy it over. - ModuleRefRec *pModRefEmit; - IfFailGo(pMiniMdEmit->AddModuleRefRecord(&pModRefEmit, (RID*)&mrEmit)); - mrEmit = TokenFromRid(mrEmit, mdtModuleRef); - - // Set ModuleRef Name. - IfFailGo( pMiniMdEmit->PutString(TBL_ModuleRef, ModuleRefRec::COL_Name, pModRefEmit, szNameImp) ); - } - else - IfFailGo(hr); - } - - - if (pCurTkMap->Find(mdImp, &pTokenRecMD) == false) - { - // This should never fire unless the method defs weren't merged - // before this code ran. - _ASSERTE(!"Parent MethodDef not found in MERGER::MergePinvoke. Bad state!"); - IfFailGo( META_E_BADMETADATA ); - } - - - // Get copy of rest of data. - usMappingFlags = pMiniMdImport->getMappingFlagsOfImplMap(pRecImport); - IfFailGo(pMiniMdImport->getImportNameOfImplMap(pRecImport, &szImportName)); - - // If the method associated with PInvokeMap is not duplicated, then don't bother to look up the - // duplicated PInvokeMap information. - if (pTokenRecMD->m_isDuplicate == true) - { - // Does the correct ImplMap entry exist in the emit scope? - IfFailGo(pMiniMdEmit->FindImplMapHelper(pTokenRecMD->m_tkTo, &mdImplMap)); - } - else - { - mdImplMap = mdTokenNil; - } - if (!InvalidRid(mdImplMap)) - { - // Verify that the rest of the data is identical, else it's an error. - IfFailGo(pMiniMdEmit->GetImplMapRecord(mdImplMap, &pRecEmit)); - _ASSERTE(pMiniMdEmit->getMemberForwardedOfImplMap(pRecEmit) == pTokenRecMD->m_tkTo); - LPCSTR szImplMapImportName; - IfFailGo(pMiniMdEmit->getImportNameOfImplMap(pRecEmit, &szImplMapImportName)); - if (pMiniMdEmit->getImportScopeOfImplMap(pRecEmit) != mrEmit || - pMiniMdEmit->getMappingFlagsOfImplMap(pRecEmit) != usMappingFlags || - strcmp(szImplMapImportName, szImportName)) - { - // Mismatched p-invoke entries are found. - _ASSERTE(!"Mismatched P-invoke entries during merge. Bad State!"); - IfFailGo(E_FAIL); - } - } - else - { - IfFailGo(pMiniMdEmit->AddImplMapRecord(&pRecEmit, &mdImplMap)); - - // Copy rest of data. - IfFailGo( pMiniMdEmit->PutToken(TBL_ImplMap, ImplMapRec::COL_MemberForwarded, pRecEmit, pTokenRecMD->m_tkTo) ); - IfFailGo( pMiniMdEmit->PutToken(TBL_ImplMap, ImplMapRec::COL_ImportScope, pRecEmit, mrEmit) ); - IfFailGo( pMiniMdEmit->PutString(TBL_ImplMap, ImplMapRec::COL_ImportName, pRecEmit, szImportName) ); - pRecEmit->SetMappingFlags(usMappingFlags); - IfFailGo( pMiniMdEmit->AddImplMapToHash(mdImplMap) ); - } - } - } - - -ErrExit: - return hr; -} // HRESULT NEWMERGER::MergePinvoke() - - -//***************************************************************************** -// Merge StandAloneSigs -//***************************************************************************** -HRESULT NEWMERGER::MergeStandAloneSigs() -{ - HRESULT hr = NOERROR; - StandAloneSigRec *pRecImport = NULL; - StandAloneSigRec *pRecEmit = NULL; - CMiniMdRW *pMiniMdImport; - CMiniMdRW *pMiniMdEmit; - ULONG iCount; - ULONG i; - TOKENREC *pTokenRec; - mdSignature saImp; - mdSignature saEmit; - bool fDuplicate; - PCCOR_SIGNATURE pbSig; - ULONG cbSig; - ULONG cbEmit; - CQuickBytes qbSig; - PCOR_SIGNATURE rgSig; - - MergeImportData *pImportData; - MDTOKENMAP *pCurTkMap; - - pMiniMdEmit = GetMiniMdEmit(); - - for (pImportData = m_pImportDataList; pImportData != NULL; pImportData = pImportData->m_pNextImportData) - { - // for each import scope - pMiniMdImport = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - - // We know that the filter table is not null here. Tell PREFIX that we know it. - PREFIX_ASSUME( pMiniMdImport->GetFilterTable() != NULL ); - - // set the current MDTokenMap - pCurTkMap = pImportData->m_pMDTokenMap; - iCount = pMiniMdImport->getCountStandAloneSigs(); - - // loop through all Signatures - for (i = 1; i <= iCount; i++) - { - // only merge those Signatures that are marked - if ( pMiniMdImport->GetFilterTable()->IsSignatureMarked(TokenFromRid(i, mdtSignature)) == false) - continue; - - // compare it with the emit scope - IfFailGo(pMiniMdImport->GetStandAloneSigRecord(i, &pRecImport)); - IfFailGo(pMiniMdImport->getSignatureOfStandAloneSig(pRecImport, &pbSig, &cbSig)); - - // This is a signature containing the return type after count of args - // convert rid contained in signature to new scope - IfFailGo(ImportHelper::MergeUpdateTokenInSig( - NULL, // Assembly emit scope. - pMiniMdEmit, // The emit scope. - NULL, NULL, 0, // Assembly import scope info. - pMiniMdImport, // The scope to merge into the emit scope. - pbSig, // signature from the imported scope - pCurTkMap, // Internal token mapping structure. - &qbSig, // [OUT] translated signature - 0, // start from first byte of the signature - 0, // don't care how many bytes consumed - &cbEmit)); // number of bytes write to cbEmit - rgSig = ( PCOR_SIGNATURE ) qbSig.Ptr(); - - hr = ImportHelper::FindStandAloneSig( - pMiniMdEmit, - rgSig, - cbEmit, - &saEmit ); - if ( hr == S_OK ) - { - // find a duplicate - fDuplicate = true; - } - else - { - // copy over - fDuplicate = false; - IfFailGo(pMiniMdEmit->AddStandAloneSigRecord(&pRecEmit, (ULONG *)&saEmit)); - saEmit = TokenFromRid(saEmit, mdtSignature); - IfFailGo( pMiniMdEmit->PutBlob(TBL_StandAloneSig, StandAloneSigRec::COL_Signature, pRecEmit, rgSig, cbEmit)); - } - saImp = TokenFromRid(i, mdtSignature); - - // Record the token movement - IfFailGo( pCurTkMap->InsertNotFound(saImp, fDuplicate, saEmit, &pTokenRec) ); - } - } - -ErrExit: - return hr; -} // HRESULT NEWMERGER::MergeStandAloneSigs() - -//***************************************************************************** -// Merge MethodSpecs -//***************************************************************************** -HRESULT NEWMERGER::MergeMethodSpecs() -{ - HRESULT hr = NOERROR; - CMiniMdRW *pMiniMdImport; - CMiniMdRW *pMiniMdEmit; - ULONG iCount; - ULONG i; - mdToken tk; - ULONG iRecord; - - MergeImportData *pImportData; - MDTOKENMAP *pCurTkMap; - - pMiniMdEmit = GetMiniMdEmit(); - - for (pImportData = m_pImportDataList; pImportData != NULL; pImportData = pImportData->m_pNextImportData) - { - // for each import scope - pMiniMdImport = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - - // We know that the filter table is not null here. Tell PREFIX that we know it. - PREFIX_ASSUME( pMiniMdImport->GetFilterTable() != NULL ); - - // set the current MDTokenMap - pCurTkMap = pImportData->m_pMDTokenMap; - - // Loop through all MethodSpec - iCount = pMiniMdImport->getCountMethodSpecs(); - for (i=1; i<=iCount; ++i) - { - MethodSpecRec *pRecImport; - MethodSpecRec *pRecEmit; - TOKENREC *pTokenRecMethod; - TOKENREC *pTokenRecMethodNew; - PCCOR_SIGNATURE pvSig; - ULONG cbSig; - CQuickBytes qbSig; - ULONG cbEmit; - - // Only copy marked records. - if (!pMiniMdImport->GetFilterTable()->IsMethodSpecMarked(i)) - continue; - - IfFailGo(pMiniMdImport->GetMethodSpecRecord(i, &pRecImport)); - tk = pMiniMdImport->getMethodOfMethodSpec(pRecImport); - - // Map the token to the new scope. - if (pCurTkMap->Find(tk, &pTokenRecMethod) == false) - { - // This should never fire unless the TypeDefs/Refs weren't merged - // before this code runs. - _ASSERTE(!"MethodSpec method not found in MERGER::MergeGenericsInfo. Bad state!"); - IfFailGo( META_E_BADMETADATA ); - } - // Copy to output scope. - IfFailGo(pMiniMdEmit->AddMethodSpecRecord(&pRecEmit, &iRecord)); - IfFailGo( pMiniMdEmit->PutToken(TBL_MethodSpec, MethodSpecRec::COL_Method, pRecEmit, pTokenRecMethod->m_tkTo)); - - // Copy the signature, translating any embedded tokens. - IfFailGo(pMiniMdImport->getInstantiationOfMethodSpec(pRecImport, &pvSig, &cbSig)); - - // ...convert rid contained in signature to new scope - IfFailGo(ImportHelper::MergeUpdateTokenInSig( - NULL, // Assembly emit scope. - pMiniMdEmit, // The emit scope. - NULL, NULL, 0, // Import assembly scope information. - pMiniMdImport, // The scope to merge into the emit scope. - pvSig, // signature from the imported scope - pCurTkMap, // Internal token mapping structure. - &qbSig, // [OUT] translated signature - 0, // start from first byte of the signature - 0, // don't care how many bytes consumed - &cbEmit)); // number of bytes write to cbEmit - - // ...persist the converted signature - IfFailGo( pMiniMdEmit->PutBlob(TBL_MethodSpec, MethodSpecRec::COL_Instantiation, pRecEmit, qbSig.Ptr(), cbEmit) ); - - IfFailGo( pCurTkMap->InsertNotFound(TokenFromRid(i, mdtMethodSpec), false, - TokenFromRid(iRecord, mdtMethodSpec), &pTokenRecMethodNew) ); - } - } - - ErrExit: - return hr; -} // HRESULT NEWMERGER::MergeMethodSpecs() - -//***************************************************************************** -// Merge DeclSecuritys -//***************************************************************************** -HRESULT NEWMERGER::MergeDeclSecuritys() -{ - HRESULT hr = NOERROR; - DeclSecurityRec *pRecImport = NULL; - DeclSecurityRec *pRecEmit = NULL; - CMiniMdRW *pMiniMdImport; - CMiniMdRW *pMiniMdEmit; - ULONG iCount; - ULONG i; - mdToken tkParentImp; - TOKENREC *pTokenRec; - void const *pValue; - ULONG cbBlob; - mdPermission pmImp; - mdPermission pmEmit; - bool fDuplicate; - - MergeImportData *pImportData; - MDTOKENMAP *pCurTkMap; - - pMiniMdEmit = GetMiniMdEmit(); - - for (pImportData = m_pImportDataList; pImportData != NULL; pImportData = pImportData->m_pNextImportData) - { - // for each import scope - pMiniMdImport = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - - // We know that the filter table is not null here. Tell PREFIX that we know it. - PREFIX_ASSUME( pMiniMdImport->GetFilterTable() != NULL ); - - // set the current MDTokenMap - pCurTkMap = pImportData->m_pMDTokenMap; - iCount = pMiniMdImport->getCountDeclSecuritys(); - - // loop through all DeclSecurity - for (i = 1; i <= iCount; i++) - { - // only merge those DeclSecurities that are marked - if ( pMiniMdImport->GetFilterTable()->IsDeclSecurityMarked(TokenFromRid(i, mdtPermission)) == false) - continue; - - // compare it with the emit scope - IfFailGo(pMiniMdImport->GetDeclSecurityRecord(i, &pRecImport)); - tkParentImp = pMiniMdImport->getParentOfDeclSecurity(pRecImport); - if ( pCurTkMap->Find(tkParentImp, &pTokenRec) ) - { - if ( !pTokenRec->m_isDuplicate ) - { - // If the parent is not duplicated, just copy over the custom value - goto CopyPermission; - } - else - { - // Try to see if the Permission is there in the emit scope or not. - // If not, move it over still - if ( ImportHelper::FindPermission( - pMiniMdEmit, - pTokenRec->m_tkTo, - pRecImport->GetAction(), - &pmEmit) == S_OK ) - { - // found a match - // <TODO>@FUTURE: more verification??</TODO> - fDuplicate = true; - } - else - { - // Parent is duplicated but the Permission is not. Still copy over the - // Permission. -CopyPermission: - fDuplicate = false; - IfFailGo(pMiniMdEmit->AddDeclSecurityRecord(&pRecEmit, (ULONG *)&pmEmit)); - pmEmit = TokenFromRid(pmEmit, mdtPermission); - - pRecEmit->Copy(pRecImport); - - // set the parent - IfFailGo( pMiniMdEmit->PutToken( - TBL_DeclSecurity, - DeclSecurityRec::COL_Parent, - pRecEmit, - pTokenRec->m_tkTo) ); - - // move over the CustomAttribute blob value - IfFailGo(pMiniMdImport->getPermissionSetOfDeclSecurity(pRecImport, (const BYTE **)&pValue, &cbBlob)); - IfFailGo(pMiniMdEmit->PutBlob( - TBL_DeclSecurity, - DeclSecurityRec::COL_PermissionSet, - pRecEmit, - pValue, - cbBlob)); - } - } - pmEmit = TokenFromRid(pmEmit, mdtPermission); - pmImp = TokenFromRid(i, mdtPermission); - - // Record the token movement - IfFailGo( pCurTkMap->InsertNotFound(pmImp, fDuplicate, pmEmit, &pTokenRec) ); - } - else - { - // bad lookup map - _ASSERTE(!"bad state"); - IfFailGo( META_E_BADMETADATA ); - } - } - } - -ErrExit: - return hr; -} // HRESULT NEWMERGER::MergeDeclSecuritys() - - -//***************************************************************************** -// Merge Strings -//***************************************************************************** -HRESULT NEWMERGER::MergeStrings() -{ - HRESULT hr = NOERROR; - CMiniMdRW *pMiniMdImport; - CMiniMdRW *pMiniMdEmit; - TOKENREC *pTokenRec; - - MergeImportData *pImportData; - MDTOKENMAP *pCurTkMap; - - pMiniMdEmit = GetMiniMdEmit(); - - for (pImportData = m_pImportDataList; pImportData != NULL; pImportData = pImportData->m_pNextImportData) - { - // for each import scope - pMiniMdImport = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - - // We know that the filter table is not null here. Tell PREFIX that we know it. - PREFIX_ASSUME( pMiniMdImport->GetFilterTable() != NULL ); - - // set the current MDTokenMap - pCurTkMap = pImportData->m_pMDTokenMap; - - for (UINT32 nIndex = 0; ;) - { - MetaData::DataBlob userString; - UINT32 nNextIndex; - UINT32 nEmitIndex; - - hr = pMiniMdImport->GetUserStringAndNextIndex( - nIndex, - &userString, - &nNextIndex); - IfFailGo(hr); - if (hr == S_FALSE) - { // We reached the last user string - hr = S_OK; - break; - } - _ASSERTE(hr == S_OK); - - // Skip empty strings - if (userString.IsEmpty()) - { - nIndex = nNextIndex; - continue; - } - - if (pMiniMdImport->GetFilterTable()->IsUserStringMarked(TokenFromRid(nIndex, mdtString)) == false) - { - // Process next user string in the heap - nIndex = nNextIndex; - continue; - } - - IfFailGo(pMiniMdEmit->PutUserString( - userString, - &nEmitIndex)); - - IfFailGo(pCurTkMap->InsertNotFound( - TokenFromRid(nIndex, mdtString), - false, - TokenFromRid(nEmitIndex, mdtString), - &pTokenRec)); - - // Process next user string in the heap - nIndex = nNextIndex; - } - } -ErrExit: - return hr; -} // HRESULT NEWMERGER::MergeStrings() - -// Helper method to merge the module-level security critical attributes -// Strips all module-level security critical attribute [that won't be ultimately needed] -// Returns: -// FAILED(hr): Failure occurred retrieving metadata or parsing scopes -// S_OK: Attribute should be merged into final output scope -// S_FALSE: Attribute should be ignored/dropped from output scope -HRESULT NEWMERGER::MergeSecurityCriticalModuleLevelAttributes( - MergeImportData* pImportData, // import scope - mdToken tkParentImp, // parent token with attribute - TOKENREC* pTypeRec, // token record of attribute ctor - mdToken mrSecurityTreatAsSafeAttributeCtor, // 'generic' TAS attribute token - mdToken mrSecurityTransparentAttributeCtor, // 'generic' Transparent attribute token - mdToken mrSecurityCriticalExplicitAttributeCtor, // 'generic' Critical attribute token - mdToken mrSecurityCriticalEverythingAttributeCtor) -{ - HRESULT hr = S_OK; - - // if ANY assembly-level critical attributes were specified, then we'll output - // one assembly-level Critical(Explicit) attribute only - // AND if this scope has tags - if (ISSCS_Unknown != pImportData->m_isscsSecurityCriticalStatus) - { - _ASSERTE(ISSCS_Unknown != m_isscsSecurityCritical); - // drop only assembly-level attributes - TypeRefRec* pTypeRefRec; - // metadata emitter - CMiniMdRW* pMiniMdImport = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - - // if compiler is generating a module - then this will be a module token - LPCSTR szTypeRefName; - if (tkParentImp == MODULEDEFTOKEN || - // otherwise, if merging assemblies, we have a fake type ref called MODULE_CA_LOCATION - (TypeFromToken(tkParentImp) == mdtTypeRef && - (IsAttributeFromNamespace(pMiniMdImport, tkParentImp, - COR_COMPILERSERVICE_NAMESPACE, COR_MSCORLIB_NAME, - &pTypeRefRec) == S_OK) && - (pMiniMdImport->getNameOfTypeRef(pTypeRefRec, &szTypeRefName) == S_OK) && - (strcmp(MODULE_CA_TYPENAME, szTypeRefName) == 0))) - { - // drop the TAS attribute (unless all scopes have TAS) - if ( pTypeRec->m_tkTo == mrSecurityTreatAsSafeAttributeCtor ) - { - if ((m_isscsSecurityCriticalAllScopes & ISSCS_SecurityTreatAsSafe) == - ISSCS_SecurityTreatAsSafe) - { - _ASSERTE((pImportData->m_isscsSecurityCriticalStatus & ISSCS_SecurityTreatAsSafe) == - ISSCS_SecurityTreatAsSafe); - return S_OK; - } - return S_FALSE; - } - // drop the Transparent attribute (unless all scopes have Transparent) - else if (pTypeRec->m_tkTo == mrSecurityTransparentAttributeCtor) - { - if ((m_isscsSecurityCriticalAllScopes & ISSCS_SecurityTransparent) == - ISSCS_SecurityTransparent) - { - _ASSERTE((pImportData->m_isscsSecurityCriticalStatus & ISSCS_SecurityTransparent) == - ISSCS_SecurityTransparent); - return S_OK; - } - return S_FALSE; - } - else if (pTypeRec->m_tkTo == mrSecurityCriticalExplicitAttributeCtor) - { - // if NOT Critical Everything, then leave the Critical.Explicit attribute - // the Critical.Explicit attribute will be used as the final global attribute - if ((m_isscsSecurityCriticalAllScopes & ISSCS_SecurityCriticalEverything) != - ISSCS_SecurityCriticalEverything) - { - _ASSERTE((pImportData->m_isscsSecurityCriticalStatus & ISSCS_SecurityCriticalExplicit) == - ISSCS_SecurityCriticalExplicit); - return S_OK; - } - else - { - // drop this attribute - return S_FALSE; - } - } - else if (pTypeRec->m_tkTo == mrSecurityCriticalEverythingAttributeCtor) - { - // OPTIMIZATION: if all attributes are Critical.Everything, - // then leave the global Critical attribute - if ((m_isscsSecurityCriticalAllScopes & ISSCS_SecurityCriticalEverything) == - ISSCS_SecurityCriticalEverything) - { - _ASSERTE((pImportData->m_isscsSecurityCriticalStatus & ISSCS_SecurityCriticalEverything) == - ISSCS_SecurityCriticalEverything); - return S_OK; - } - else - { - // drop this attribute - return S_FALSE; - } - } - } - } - - return hr; -} // NEWMERGER::MergeSecurityCriticalModuleLevelAttributes - -// HELPER: Retrieve the meta-data info related to SecurityCritical -HRESULT NEWMERGER::RetrieveStandardSecurityCriticalMetaData( - mdAssemblyRef& tkMscorlib, - mdTypeRef& securityEnum, - BYTE*& rgSigBytesSecurityCriticalEverythingCtor, - DWORD& dwSigEverythingSize, - BYTE*& rgSigBytesSecurityCriticalExplicitCtor, - DWORD& dwSigExplicitSize) -{ - HRESULT hr = S_OK; - - CMiniMdRW* emit = GetMiniMdEmit(); - - // get typeref for mscorlib - BYTE pbMscorlibToken[] = COR_MSCORLIB_TYPEREF; - BYTE* pCurr = rgSigBytesSecurityCriticalEverythingCtor; - - IfFailGo(ImportHelper::FindAssemblyRef(emit, - COR_MSCORLIB_NAME, - NULL, - pbMscorlibToken, - sizeof(pbMscorlibToken), - asm_rmj, - asm_rmm, - asm_rup, - asm_rpt, - 0, - &tkMscorlib)); - - IfFailGo(m_pRegMetaEmit->DefineTypeRefByName(tkMscorlib, - COR_SECURITYCRITICALSCOPE_ENUM_W, - &securityEnum)); - - // build the constructor sig that takes SecurityCriticalScope argument - if (rgSigBytesSecurityCriticalEverythingCtor) - { - *pCurr++ = IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS; - *pCurr++ = COR_SECURITYCRITICAL_CTOR_ARGCOUNT_SCOPE_EVERYTHING; // one argument to constructor - *pCurr++ = ELEMENT_TYPE_VOID; - *pCurr++ = ELEMENT_TYPE_VALUETYPE; - pCurr += CorSigCompressToken(securityEnum, pCurr); - dwSigEverythingSize = (DWORD)(pCurr - rgSigBytesSecurityCriticalEverythingCtor); - _ASSERTE(dwSigEverythingSize <= COR_SECURITYCRITICAL_CTOR_SCOPE_SIG_MAX_SIZE); - } - - // if Explicit ctor is requested - if (rgSigBytesSecurityCriticalExplicitCtor) - { - // build the constructor sig that has NO arguments - pCurr = rgSigBytesSecurityCriticalExplicitCtor; - *pCurr++ = IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS; - *pCurr++ = COR_SECURITYCRITICAL_CTOR_ARGCOUNT_NO_SCOPE; // no arguments to constructor - *pCurr++ = ELEMENT_TYPE_VOID; - dwSigExplicitSize = (DWORD)(pCurr - rgSigBytesSecurityCriticalExplicitCtor); - _ASSERTE(dwSigExplicitSize <= COR_SECURITYCRITICAL_CTOR_NO_SCOPE_SIG_MAX_SIZE); - } - -ErrExit: - return hr; -} // NEWMERGER::RetrieveStandardSecurityCriticalMetaData - -//***************************************************************************** -// Merge CustomAttributes -//***************************************************************************** -HRESULT NEWMERGER::MergeCustomAttributes() -{ - - HRESULT hr = NOERROR; - CustomAttributeRec *pRecImport = NULL; - CustomAttributeRec *pRecEmit = NULL; - CMiniMdRW *pMiniMdImport; - CMiniMdRW *pMiniMdEmit; - ULONG iCount; - ULONG i; - mdToken tkParentImp; // Token of attributed object (parent). - TOKENREC *pTokenRec; // Parent's remap. - mdToken tkType; // Token of attribute's type. - TOKENREC *pTypeRec; // Type's remap. - void const *pValue; // The actual value. - ULONG cbBlob; // Size of the value. - mdToken cvImp; - mdToken cvEmit; - bool fDuplicate; - - MergeImportData *pImportData; - MDTOKENMAP *pCurTkMap; - - TypeRefRec *pTypeRefRec; - ULONG cTypeRefRecs; - mdToken mrSuppressMergeCheckAttributeCtor = mdTokenNil; - mdToken mrSecurityCriticalExplicitAttributeCtor = mdTokenNil; - mdToken mrSecurityCriticalEverythingAttributeCtor = mdTokenNil; - mdToken mrSecurityTransparentAttributeCtor = mdTokenNil; - mdToken mrSecurityTreatAsSafeAttributeCtor = mdTokenNil; - - pMiniMdEmit = GetMiniMdEmit(); - - // Find out the TypeRef referring to our library's System.CompilerServices.SuppressMergeCheckAttribute, - // System.Security.SecurityCriticalAttribute, System.Security.SecurityTransparentAttribute, and - // System.Security.SecurityTreatAsSafeAttibute - cTypeRefRecs = pMiniMdEmit->getCountTypeRefs(); - - { // retrieve global attribute TypeRefs - - mdAssemblyRef tkMscorlib = mdTokenNil; - mdTypeRef securityEnum = mdTokenNil; - - NewArrayHolder<BYTE> rgSigBytesSecurityCriticalEverythingCtor(new (nothrow)BYTE[COR_SECURITYCRITICAL_CTOR_SCOPE_SIG_MAX_SIZE]); - BYTE* pSigBytesSecurityCriticalEverythingCtor = rgSigBytesSecurityCriticalEverythingCtor.GetValue(); - IfFailGo((pSigBytesSecurityCriticalEverythingCtor == NULL)?E_OUTOFMEMORY:S_OK); - DWORD dwSigEverythingSize = 0; - - NewArrayHolder<BYTE> rgSigBytesSecurityCriticalExplicitCtor(new (nothrow)BYTE[COR_SECURITYCRITICAL_CTOR_NO_SCOPE_SIG_MAX_SIZE]); - BYTE* pSigBytesSecurityCriticalExplicitCtor = rgSigBytesSecurityCriticalExplicitCtor.GetValue(); - IfFailGo((pSigBytesSecurityCriticalExplicitCtor == NULL)?E_OUTOFMEMORY:S_OK); - DWORD dwSigExplicitSize = 0; - - // retrieve security critical metadata info if necessary - if(ISSCS_Unknown != m_isscsSecurityCritical) - { - - hr = RetrieveStandardSecurityCriticalMetaData( - tkMscorlib, - securityEnum, - pSigBytesSecurityCriticalEverythingCtor, - dwSigEverythingSize, - pSigBytesSecurityCriticalExplicitCtor, - dwSigExplicitSize); - - } - - // Search for the TypeRef. - for (i = 1; i <= cTypeRefRecs; i++) - { - mdToken tkTmp = TokenFromRid(i,mdtTypeRef); - - if (IsAttributeFromNamespace(pMiniMdEmit, tkTmp, - COR_COMPILERSERVICE_NAMESPACE, COR_MSCORLIB_NAME, - &pTypeRefRec) == S_OK) - { - LPCSTR szNameOfTypeRef; - IfFailGo(pMiniMdEmit->getNameOfTypeRef(pTypeRefRec, &szNameOfTypeRef)); - if (strcmp(szNameOfTypeRef, COR_SUPPRESS_MERGE_CHECK_ATTRIBUTE) == 0) - { - hr = ImportHelper::FindMemberRef( - pMiniMdEmit, tkTmp, - COR_CTOR_METHOD_NAME, - NULL, 0, - &mrSuppressMergeCheckAttributeCtor); - if (S_OK == hr) continue; - } - } - else - // if we are merging security critical attributes, then look for transparent-related attributes - if ((ISSCS_Unknown != m_isscsSecurityCritical) && - (IsAttributeFromNamespace(pMiniMdEmit, tkTmp, - COR_SECURITYCRITICAL_ATTRIBUTE_NAMESPACE, COR_MSCORLIB_NAME, - &pTypeRefRec) == S_OK)) - { - LPCSTR szNameOfTypeRef; - IfFailGo(pMiniMdEmit->getNameOfTypeRef(pTypeRefRec, &szNameOfTypeRef)); - - // look for the SecurityCritical attribute - if (strcmp(szNameOfTypeRef, COR_SECURITYCRITICAL_ATTRIBUTE) == 0) - { - // since the SecurityCritical attribute can be either - // parameterless constructor or SecurityCriticalScope constructor, we - // look for both - hr = ImportHelper::FindMemberRef( - pMiniMdEmit, tkTmp, - COR_CTOR_METHOD_NAME, - rgSigBytesSecurityCriticalEverythingCtor.GetValue(), dwSigEverythingSize, - &mrSecurityCriticalEverythingAttributeCtor); - if (S_OK == hr) continue; - hr = ImportHelper::FindMemberRef( - pMiniMdEmit, tkTmp, - COR_CTOR_METHOD_NAME, - rgSigBytesSecurityCriticalExplicitCtor.GetValue(), dwSigExplicitSize, - &mrSecurityCriticalExplicitAttributeCtor); - if (S_OK == hr) continue; - } - else - // look for the SecurityTransparent attribute - if (strcmp(szNameOfTypeRef, COR_SECURITYTRANSPARENT_ATTRIBUTE) == 0) - { - hr = ImportHelper::FindMemberRef( - pMiniMdEmit, tkTmp, - COR_CTOR_METHOD_NAME, - NULL, 0, - &mrSecurityTransparentAttributeCtor); - if (S_OK == hr) continue; - } - else - // look for the SecurityTreatAsSafe attribute - if (strcmp(szNameOfTypeRef, COR_SECURITYTREATASSAFE_ATTRIBUTE) == 0) - { - hr = ImportHelper::FindMemberRef( - pMiniMdEmit, tkTmp, - COR_CTOR_METHOD_NAME, - NULL, 0, - &mrSecurityTreatAsSafeAttributeCtor); - if (S_OK == hr) continue; - } - } - hr = S_OK; // ignore failures since the attribute may not be used - } - } - - // Loop over every module scope - for (pImportData = m_pImportDataList; pImportData != NULL; pImportData = pImportData->m_pNextImportData) - { - // for each import scope - pMiniMdImport = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - - // We know that the filter table is not null here. Tell PREFIX that we know it. - PREFIX_ASSUME( pMiniMdImport->GetFilterTable() != NULL ); - - // set the current MDTokenMap - pCurTkMap = pImportData->m_pMDTokenMap; - iCount = pMiniMdImport->getCountCustomAttributes(); - - // loop through all CustomAttribute - for (i = 1; i <= iCount; i++) - { - // compare it with the emit scope - IfFailGo(pMiniMdImport->GetCustomAttributeRecord(i, &pRecImport)); - tkParentImp = pMiniMdImport->getParentOfCustomAttribute(pRecImport); - tkType = pMiniMdImport->getTypeOfCustomAttribute(pRecImport); - IfFailGo(pMiniMdImport->getValueOfCustomAttribute(pRecImport, (const BYTE **)&pValue, &cbBlob)); - - // only merge those CustomAttributes that are marked - if ( pMiniMdImport->GetFilterTable()->IsCustomAttributeMarked(TokenFromRid(i, mdtCustomAttribute)) == false) - continue; - - // Check the type of the CustomAttribute. If it is not marked, then we don't need to move over the CustomAttributes. - // This will only occur for compiler defined discardable CAs during linking. - // - if ( pMiniMdImport->GetFilterTable()->IsTokenMarked(tkType) == false) - continue; - - if ( pCurTkMap->Find(tkParentImp, &pTokenRec) ) - { - // If the From token type is different from the To token's type, we have optimized the ref to def. - // In this case, we are dropping the CA associated with the Ref tokens. - // - if (TypeFromToken(tkParentImp) == TypeFromToken(pTokenRec->m_tkTo)) - { - - // If tkParentImp is a MemberRef and it is also mapped to a MemberRef in the merged scope with a MethodDef - // parent, then it is a MemberRef optimized to a MethodDef. We are keeping the MemberRef because it is a - // vararg call. So we can drop CAs on this MemberRef. - if (TypeFromToken(tkParentImp) == mdtMemberRef) - { - MemberRefRec *pTempRec; - IfFailGo(pMiniMdEmit->GetMemberRefRecord(RidFromToken(pTokenRec->m_tkTo), &pTempRec)); - if (TypeFromToken(pMiniMdEmit->getClassOfMemberRef(pTempRec)) == mdtMethodDef) - continue; - } - - - if (! pCurTkMap->Find(tkType, &pTypeRec) ) - { - _ASSERTE(!"CustomAttribute Type not found in output scope"); - IfFailGo(META_E_BADMETADATA); - } - - // Determine if we need to copy or ignore security-critical-related attributes - hr = MergeSecurityCriticalModuleLevelAttributes( - pImportData, tkParentImp, pTypeRec, - mrSecurityTreatAsSafeAttributeCtor, mrSecurityTransparentAttributeCtor, - mrSecurityCriticalExplicitAttributeCtor, - mrSecurityCriticalEverythingAttributeCtor); - IfFailGo(hr); - // S_FALSE means skip attribute - if (hr == S_FALSE) continue; - // S_OK means consider copying attribute - - // if it's the SuppressMergeCheckAttribute, don't copy it - if ( pTypeRec->m_tkTo == mrSuppressMergeCheckAttributeCtor ) - { - continue; - } - - if ( pTokenRec->m_isDuplicate) - { - // Try to see if the custom value is there in the emit scope or not. - // If not, move it over still - hr = ImportHelper::FindCustomAttributeByToken( - pMiniMdEmit, - pTokenRec->m_tkTo, - pTypeRec->m_tkTo, - pValue, - cbBlob, - &cvEmit); - - if ( hr == S_OK ) - { - // found a match - // <TODO>@FUTURE: more verification??</TODO> - fDuplicate = true; - } - else - { - TypeRefRec *pAttributeTypeRefRec; - // We need to allow additive merge on TypeRef for CustomAttributes because compiler - // could build module but not assembly. They are hanging of Assembly level CAs on a bogus - // TypeRef. - // Also allow additive merge for CAs from CompilerServices and Microsoft.VisualC - if (tkParentImp == MODULEDEFTOKEN - || TypeFromToken(tkParentImp) == mdtTypeRef - || (IsAttributeFromNamespace(pMiniMdImport, tkType, - COR_COMPILERSERVICE_NAMESPACE, COR_MSCORLIB_NAME, - &pAttributeTypeRefRec) == S_OK) - || (IsAttributeFromNamespace(pMiniMdImport, tkType, - COR_MISCBITS_NAMESPACE, COR_MISCBITS_NAMESPACE, - &pAttributeTypeRefRec) == S_OK)) - { - // clear the error - hr = NOERROR; - - // custom value of module token! Copy over the custom value - goto CopyCustomAttribute; - } - - // another case to support additive merge if the CA on MehtodDef is - // HandleProcessCorruptedStateExceptionsAttribute - if ( TypeFromToken(tkParentImp) == mdtMethodDef && tkType == pImportData->m_tkHandleProcessCorruptedStateCtor) - { - // clear the error - hr = NOERROR; - - // custom value of module token! Copy over the custom value - goto CopyCustomAttribute; - } - CheckContinuableErrorEx(META_E_MD_INCONSISTENCY, pImportData, TokenFromRid(i, mdtCustomAttribute)); - } - } - else - { -CopyCustomAttribute: - if ((m_dwMergeFlags & DropMemberRefCAs) && TypeFromToken(pTokenRec->m_tkTo) == mdtMemberRef) - { - // CustomAttributes associated with MemberRef. If the parent of MemberRef is a MethodDef or FieldDef, drop - // the custom attribute. - MemberRefRec *pMemberRefRec; - IfFailGo(pMiniMdEmit->GetMemberRefRecord(RidFromToken(pTokenRec->m_tkTo), &pMemberRefRec)); - mdToken mrParent = pMiniMdEmit->getClassOfMemberRef(pMemberRefRec); - if (TypeFromToken(mrParent) == mdtMethodDef || TypeFromToken(mrParent) == mdtFieldDef) - { - // Don't bother to copy over - continue; - } - } - - // Parent is duplicated but the custom value is not. Still copy over the - // custom value. - fDuplicate = false; - IfFailGo(pMiniMdEmit->AddCustomAttributeRecord(&pRecEmit, (ULONG *)&cvEmit)); - cvEmit = TokenFromRid(cvEmit, mdtCustomAttribute); - - // set the parent - IfFailGo( pMiniMdEmit->PutToken(TBL_CustomAttribute, CustomAttributeRec::COL_Parent, pRecEmit, pTokenRec->m_tkTo) ); - // set the type - IfFailGo( pMiniMdEmit->PutToken(TBL_CustomAttribute, CustomAttributeRec::COL_Type, pRecEmit, pTypeRec->m_tkTo)); - - // move over the CustomAttribute blob value - IfFailGo(pMiniMdImport->getValueOfCustomAttribute(pRecImport, (const BYTE **)&pValue, &cbBlob)); - - IfFailGo( pMiniMdEmit->PutBlob(TBL_CustomAttribute, CustomAttributeRec::COL_Value, pRecEmit, pValue, cbBlob)); - IfFailGo( pMiniMdEmit->AddCustomAttributesToHash(cvEmit) ); - } - cvEmit = TokenFromRid(cvEmit, mdtCustomAttribute); - cvImp = TokenFromRid(i, mdtCustomAttribute); - - // Record the token movement - IfFailGo( pCurTkMap->InsertNotFound(cvImp, pTokenRec->m_isDuplicate, cvEmit, &pTokenRec) ); - } - } - else - { - - // either bad lookup map or bad metadata - _ASSERTE(!"Bad state"); - IfFailGo( META_E_BADMETADATA ); - } - } - } - -ErrExit: - return hr; -} // HRESULT NEWMERGER::MergeCustomAttributes() - -//******************************************************************************* -// Helper to check if input scope has assembly-level security transparent awareness (either SecurityTransparent or SecurityCritical) -// SIDE EFFECT: pImportData->m_isscsSecurityCriticalStatus will be explicitly set [same value as return value] -// SecurityCritical.Explicit attribute injection occurs for all scopes that have tags (e.g. NOT ISSCS_Unknown) -// If the tagged scopes are all SecurityCritical.Everything, then the final attribute should be SecurityCritical.Everything -// anyway. Otherwise, at least one SecurityCritical.Explicit tag will be used/injected -//******************************************************************************* -InputScopeSecurityCriticalStatus NEWMERGER::CheckInputScopeIsCritical(MergeImportData* pImportData, HRESULT& hr) -{ - hr = S_OK; - - // the attribute should be in a known state no matter how we return from this function - // default to no attribute explicitly specified - pImportData->m_isscsSecurityCriticalStatus = ISSCS_Unknown; - - mdTypeRef fakeModuleTypeRef = mdTokenNil; - mdAssemblyRef tkMscorlib = mdTokenNil; - - // TODO: Should we remove the ability to disable merging critical attributes? - if (g_fRefShouldMergeCriticalChecked == FALSE) - { - // shouldn't require thread safety lock - g_fRefShouldMergeCritical = (CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_MergeCriticalAttributes) != 0); - g_fRefShouldMergeCriticalChecked = TRUE; - } - - // return no merge needed, if the merge critical attribute setting is not enabled. - if (!g_fRefShouldMergeCritical) return ISSCS_Unknown; - - // get typeref for mscorlib - BYTE pbMscorlibToken[] = COR_MSCORLIB_TYPEREF; - - CMiniMdRW* pImportedMiniMd = &pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd; - - if (S_OK != ImportHelper::FindAssemblyRef(pImportedMiniMd, - COR_MSCORLIB_NAME, - NULL, - pbMscorlibToken, - sizeof(pbMscorlibToken), - asm_rmj, - asm_rmm, - asm_rup, - asm_rpt, - 0, - &tkMscorlib)) - { - // there isn't an mscorlib ref here... we can't have the security critical attribute - return ISSCS_Unknown; - } - - if (S_OK != ImportHelper::FindTypeRefByName(pImportedMiniMd, - tkMscorlib, - COR_COMPILERSERVICE_NAMESPACE, - MODULE_CA_TYPENAME, - &fakeModuleTypeRef)) - { - // for now let use the fake module ref as the assembly def - fakeModuleTypeRef = 0x000001; - } - - // Check the input scope for TreatAsSafe - if (S_OK == ImportHelper::GetCustomAttributeByName(pImportedMiniMd, - fakeModuleTypeRef, // This is the assembly def token - COR_SECURITYTREATASSAFE_ATTRIBUTE_FULL, - NULL, - NULL)) - { - pImportData->m_isscsSecurityCriticalStatus |= ISSCS_SecurityTreatAsSafe; - } - - // Check the input scope for security transparency awareness - // For example, the assembly is marked SecurityTransparent, SecurityCritical(Explicit), or SecurityCritical(Everything) - - - const void *pbData = NULL; // [OUT] Put pointer to data here. - ULONG cbData = 0; // number of bytes in pbData - - // Check if the SecurityTransparent attribute is present - if (S_OK == ImportHelper::GetCustomAttributeByName(pImportedMiniMd, - fakeModuleTypeRef, // This is the assembly def token - COR_SECURITYTRANSPARENT_ATTRIBUTE_FULL, - NULL, - NULL)) - { - pImportData->m_isscsSecurityCriticalStatus |= ISSCS_SecurityTransparent; - } - else - // Check if the SecurityCritical attribute is present - if (S_OK == ImportHelper::GetCustomAttributeByName(pImportedMiniMd, - fakeModuleTypeRef, // This is the assembly def token - COR_SECURITYCRITICAL_ATTRIBUTE_FULL, - &pbData, - &cbData)) - { - // find out if critical everything or explicit - - // default to critical - pImportData->m_isscsSecurityCriticalStatus = ISSCS_SecurityCritical; - - BYTE rgSecurityCriticalEverythingCtorValue[] = COR_SECURITYCRITICAL_ATTRIBUTE_VALUE_EVERYTHING; - // if value is non-0 (i.e. 1), then mark as SecurityCritical everything, otherwise, explicit - if (NULL != pbData && cbData == 8 && - memcmp(rgSecurityCriticalEverythingCtorValue, pbData, cbData) == 0) - { - pImportData->m_isscsSecurityCriticalStatus |= ISSCS_SecurityCriticalEverything; - } - else - { - pImportData->m_isscsSecurityCriticalStatus |= ISSCS_SecurityCriticalExplicit; - } - } - - return pImportData->m_isscsSecurityCriticalStatus; -} // HRESULT NEWMERGER::CheckInputScopeIsCritical() - -//******************************************************************************* -// Helper to merge security critical annotations across assemblies and types -//******************************************************************************* -HRESULT NEWMERGER::MergeSecurityCriticalAttributes() -{ - // if no assembly-level critical attributes were specified, then none are needed, - // and no need to do special attribute merging - if (ISSCS_Unknown == m_isscsSecurityCritical) - { - return S_OK; - } - // or if the global-scope already has TAS/Critical.Everything, then ignore individual type fixes - else if ((ISSCS_SECURITYCRITICAL_LEGACY & m_isscsSecurityCriticalAllScopes) == ISSCS_SECURITYCRITICAL_LEGACY) - { - return S_OK; - } - - HRESULT hr = S_OK; - - CMiniMdRW* emit = GetMiniMdEmit(); - // The attribute we want to decorate all of the types with has not been defined. - mdMemberRef tkSecurityCriticalEverythingAttribute = mdTokenNil; - mdMemberRef tkSecurityTreatAsSafeAttribute = mdTokenNil; - mdMemberRef tkSecuritySafeCriticalAttribute = mdTokenNil; - - mdAssemblyRef tkMscorlib = mdTokenNil; - mdTypeRef fakeModuleTypeRef = mdTokenNil; - mdTypeRef securityEnum = mdTokenNil; - - DWORD dwSigSize; - BYTE* rgSigBytesSecurityCriticalExplicitCtor = 0; - DWORD dwSigSize_TEMP; - - BYTE rgSigBytesTreatAsSafeCtor[] = {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 0x00, ELEMENT_TYPE_VOID}; - - BYTE rgSecurityCriticalEverythingCtorValue[] = COR_SECURITYCRITICAL_ATTRIBUTE_VALUE_EVERYTHING; - - - mdTypeRef tkSecurityCriticalEverythingAttributeType = mdTokenNil; - mdTypeRef tkSecurityTreatAsSafeAttributeType = mdTokenNil; - - NewArrayHolder<BYTE> rgSigBytesSecurityCriticalEverythingCtor(new (nothrow)BYTE[COR_SECURITYCRITICAL_CTOR_SCOPE_SIG_MAX_SIZE]); - BYTE* pSigBytesSecurityCriticalEverythingCtor = rgSigBytesSecurityCriticalEverythingCtor.GetValue(); - IfFailGo((pSigBytesSecurityCriticalEverythingCtor == NULL)?E_OUTOFMEMORY:S_OK); - - IfFailGo(RetrieveStandardSecurityCriticalMetaData( - tkMscorlib, - securityEnum, - pSigBytesSecurityCriticalEverythingCtor, - dwSigSize, - rgSigBytesSecurityCriticalExplicitCtor, - dwSigSize_TEMP)); - - if (S_OK != ImportHelper::FindTypeRefByName(emit, - tkMscorlib, - COR_COMPILERSERVICE_NAMESPACE, - MODULE_CA_TYPENAME, - &fakeModuleTypeRef)) - { - // for now let use the fake module ref as the assembly def - fakeModuleTypeRef = 0x000001; - } - - IfFailGo(m_pRegMetaEmit->DefineTypeRefByName( - tkMscorlib, COR_SECURITYCRITICAL_ATTRIBUTE_FULL_W, &tkSecurityCriticalEverythingAttributeType)); - - IfFailGo(m_pRegMetaEmit->DefineMemberRef(tkSecurityCriticalEverythingAttributeType, - COR_CONSTRUCTOR_METADATA_IDENTIFIER, - rgSigBytesSecurityCriticalEverythingCtor.GetValue(), - dwSigSize, - &tkSecurityCriticalEverythingAttribute)); - - IfFailGo(m_pRegMetaEmit->DefineTypeRefByName( - tkMscorlib, COR_SECURITYTREATASSAFE_ATTRIBUTE_FULL_W, - &tkSecurityTreatAsSafeAttributeType)); - - IfFailGo(m_pRegMetaEmit->DefineMemberRef(tkSecurityTreatAsSafeAttributeType, - COR_CONSTRUCTOR_METADATA_IDENTIFIER, - rgSigBytesTreatAsSafeCtor, - sizeof(rgSigBytesTreatAsSafeCtor), - &tkSecurityTreatAsSafeAttribute)); - - - // place this block in a new scope so that we can safely goto past it - { - mdTypeRef tkSecuritySafeCriticalAttributeType = mdTokenNil; - if (FAILED (hr = m_pRegMetaEmit->DefineTypeRefByName(tkMscorlib, COR_SECURITYSAFECRITICAL_ATTRIBUTE_FULL_W, - &tkSecuritySafeCriticalAttributeType))) - { - _ASSERTE(!"Couldn't Emit a Typeref for SafeCritical attribute"); - return hr; - } - - BYTE rgSigBytesSafeCriticalCtor[] = {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 0x00, ELEMENT_TYPE_VOID}; - if (FAILED(hr = m_pRegMetaEmit->DefineMemberRef(tkSecuritySafeCriticalAttributeType, - W(".ctor"), - rgSigBytesSafeCriticalCtor, - sizeof(rgSigBytesSafeCriticalCtor), - &tkSecuritySafeCriticalAttribute))) - { - _ASSERTE(!"Couldn't Emit a MemberRef for SafeCritical attribute .ctor"); - return hr; - } - } - - - for (MergeImportData* pImportData = m_pImportDataList; pImportData != NULL; pImportData = pImportData->m_pNextImportData) - { - // if the import is marked TAS, then we need to explicitly mark each type as TAS - // if the import is marked Crit/Everything, then we need to explicitly mark each type as Crit - // if the import is not marked at all, then we need to explicitly mark each type TAS/Crit - - // if the import is marked ONLY Crit/Explicit or ONLY Transparent then we can ignore it - if (ISSCS_SecurityTransparent == pImportData->m_isscsSecurityCriticalStatus || - ISSCS_SecurityCriticalExplicit == pImportData->m_isscsSecurityCriticalStatus) continue; - - // Run through the scopes that need to have their types decorated with this attribute - MDTOKENMAP*pCurTKMap = pImportData->m_pMDTokenMap; - BYTE rgTreatAsSafeCtorValue[] = COR_SECURITYTREATASSAFE_ATTRIBUTE_VALUE; - - BOOL fMarkEachTokenAsCritical = FALSE; - // if the import is unmarked or marked Crit/Everything, - // then we need to explicitly mark each token as Crit - // Unless the the global scope already has SecurityCritical.Everything - if (((ISSCS_SecurityCriticalEverything & m_isscsSecurityCriticalAllScopes) != ISSCS_SecurityCriticalEverything) && - (((ISSCS_SecurityCriticalEverything & pImportData->m_isscsSecurityCriticalStatus) == ISSCS_SecurityCriticalEverything ) || - - // OR this scope is NOT transparent or critical-explicit - (ISSCS_SecurityTransparent & pImportData->m_isscsSecurityCriticalStatus) == 0 || - (ISSCS_SecurityCritical & pImportData->m_isscsSecurityCriticalStatus) == 0 || - - // OR this scope is UNKNOWN - (ISSCS_Unknown == (ISSCS_SECURITYCRITICAL_FLAGS & pImportData->m_isscsSecurityCriticalStatus)))) - { - fMarkEachTokenAsCritical = TRUE; - } - - BOOL fMarkEachTokenAsSafe = FALSE; - // if the import is unmarked or marked TAS, - // then we need to explicitly mark each token as TAS - // Unless the the global scope already has SecurityTreatAsSafe - if (((ISSCS_SecurityTreatAsSafe & m_isscsSecurityCriticalAllScopes) != ISSCS_SecurityTreatAsSafe) && - ((ISSCS_SecurityTreatAsSafe & pImportData->m_isscsSecurityCriticalStatus) || - ISSCS_Unknown == (pImportData->m_isscsSecurityCriticalStatus & ISSCS_SECURITYCRITICAL_FLAGS))) - { - fMarkEachTokenAsSafe = TRUE; - } - - BYTE rgSafeCriticalCtorValue[] = {0x01, 0x00, 0x00 ,0x00}; - - for (int i = 0; i < pCurTKMap->Count(); i++) - { - TOKENREC* pRec = pCurTKMap->Get(i); - BOOL fInjectSecurityAttributes = FALSE; - - // skip empty records - if (pRec->IsEmpty()) continue; - - // If this scope contained a typeref that was resolved to a typedef, let's not mark it. We'll let the owner - // of the actual typedef decide if that type should be marked. - if ((TypeFromToken(pRec->m_tkFrom) == mdtTypeRef) && (TypeFromToken(pRec->m_tkTo) == mdtTypeDef)) - continue; - - // Same for method refs/method defs - if ((TypeFromToken(pRec->m_tkFrom) == mdtMemberRef) && (TypeFromToken(pRec->m_tkTo) == mdtMethodDef)) - continue; - - // check for typedefs, but don't put this on the global typedef - if ((TypeFromToken(pRec->m_tkTo) == mdtTypeDef) && (pRec->m_tkTo != TokenFromRid(1, mdtTypeDef))) - { - // by default we will inject - fInjectSecurityAttributes = TRUE; - // except for Enums - DWORD dwClassAttrs = 0; - mdTypeRef crExtends = mdTokenNil; - - if (FAILED(hr = m_pRegMetaEmit->GetTypeDefProps(pRec->m_tkTo, NULL, NULL, 0 , &dwClassAttrs, &crExtends))) - { - // TODO: should we fail ?? - } - - // check for Enum types - if (!IsNilToken(crExtends) && (TypeFromToken(crExtends)==mdtTypeRef)) - { - // get the namespace and the name for this token - CMiniMdRW *pMiniMd = GetMiniMdEmit(); - TypeRefRec *pTypeRefRec; - IfFailGo(pMiniMd->GetTypeRefRecord(RidFromToken(crExtends), &pTypeRefRec)); - LPCSTR szNamespace; - LPCSTR szName; - IfFailGo(pMiniMd->getNamespaceOfTypeRef(pTypeRefRec, &szNamespace));; - IfFailGo(pMiniMd->getNameOfTypeRef(pTypeRefRec, &szName)); - // check for System.Enum - BOOL bIsEnum = (!strcmp(szNamespace,"System"))&&(!strcmp(szName,"Enum")); - if (bIsEnum) - { - fInjectSecurityAttributes = FALSE; - } - } - } - else // check for global method defs - if (TypeFromToken(pRec->m_tkTo) == mdtMethodDef) - { - int isGlobal = 0; - if (!FAILED(m_pRegMetaEmit->IsGlobal(pRec->m_tkTo, &isGlobal))) - { - // check for global methods - if (isGlobal != 0) - { - fInjectSecurityAttributes = TRUE; - } - } - } - - if (fInjectSecurityAttributes) - { - // check to see if the token already has a custom attribute - const void *pbData = NULL; // [OUT] Put pointer to data here. - ULONG cbData = 0; - - if (fMarkEachTokenAsCritical) - { - // Check if the Type already has SecurityCritical - BOOL fInjectSecurityCriticalEverything = TRUE; - if (S_OK == m_pRegMetaEmit->GetCustomAttributeByName(pRec->m_tkTo, COR_SECURITYCRITICAL_ATTRIBUTE_FULL_W, &pbData, &cbData)) - { - // if value is non-0 (i.e. 1), then it is SecurityCritical.Everything - so do not inject another - fInjectSecurityCriticalEverything = !(NULL != pbData && cbData == 8 && - memcmp(rgSecurityCriticalEverythingCtorValue, pbData, cbData) == 0); - } - - // either inject or overwrite SecurityCritical.Everything - if (fInjectSecurityCriticalEverything) - { - IfFailGo(m_pRegMetaEmit->DefineCustomAttribute( - pRec->m_tkTo, tkSecurityCriticalEverythingAttribute, - rgSecurityCriticalEverythingCtorValue, // Use this if you need specific custom attribute data (presence of the attribute isn't enough) - sizeof(rgSecurityCriticalEverythingCtorValue), // Length of your custom attribute data - NULL)); - } - } - - // If the Type does NOT already have TAS then add it - if (fMarkEachTokenAsSafe && - S_OK != m_pRegMetaEmit->GetCustomAttributeByName(pRec->m_tkTo, COR_SECURITYTREATASSAFE_ATTRIBUTE_FULL_W, &pbData, &cbData)) - { - IfFailGo(m_pRegMetaEmit->DefineCustomAttribute( - pRec->m_tkTo, tkSecurityTreatAsSafeAttribute, - rgTreatAsSafeCtorValue, // Use this if you need specific custom attribute data (presence of the attribute isn't enough) - sizeof(rgTreatAsSafeCtorValue), // Length of your custom attribute data - NULL)); - } - - hr = m_pRegMetaEmit->DefineCustomAttribute(pRec->m_tkTo, tkSecuritySafeCriticalAttribute, - rgSafeCriticalCtorValue, // Use this if you need specific custom attribute data (presence of the attribute isn't enough) - sizeof(rgSafeCriticalCtorValue), // Length of your custom attribute data - NULL); - - } - } - } - - // If the global scope is not Transparent, we should emit SecurityCritical.Explicit || Everything - if ((m_isscsSecurityCriticalAllScopes & ISSCS_SecurityTransparent) != ISSCS_SecurityTransparent && - (m_isscsSecurityCritical & ISSCS_SecurityCriticalEverything) != ISSCS_SecurityCriticalExplicit) - { - BOOL fEmitSecurityEverything = FALSE; - // in the case of Unmarked and TAS/Unmarked, we need to emit the SecurityCritical.Everything attribute - // if it hasn't already been emitted - if ((m_isscsSecurityCriticalAllScopes & ISSCS_SecurityCriticalEverything) == - ISSCS_SecurityCriticalEverything) - { - fEmitSecurityEverything = TRUE; - } - // otherwise, emit the SecurityCritical.Explicit attribute - - BOOL fSecurityCriticalExists = FALSE; - // check to see if the assembly already has the appropriate SecurityCritical attribute - // [from one of the input scopes] - const void *pbData = NULL; - ULONG cbData = 0; - if (S_OK == ImportHelper::GetCustomAttributeByName(emit, - fakeModuleTypeRef, // This is the assembly def token - COR_SECURITYCRITICAL_ATTRIBUTE_FULL, - &pbData, - &cbData)) - { - // find out if critical everything or explicit - // default to critical - // if value is non-0 (i.e. 1), then mark as SecurityCritical everything, otherwise, explicit - if (NULL != pbData && cbData == 8 && - memcmp(rgSecurityCriticalEverythingCtorValue, pbData, cbData) == 0) - { - if (!fEmitSecurityEverything) - { - _ASSERTE(!"Unexpected SecurityCritical.Everything attribute detected"); - IfFailGo(META_E_BADMETADATA); - } - } - else - { - if (fEmitSecurityEverything) - { - _ASSERTE(!"Unexpected SecurityCritical.Explicit attribute detected"); - IfFailGo(META_E_BADMETADATA); - } - } - fSecurityCriticalExists = TRUE; - } - - if (!fSecurityCriticalExists) - { - // retrieve the type and CustomAttribute - mdCustomAttribute tkSecurityCriticalAttributeExplicit; - - mdTypeRef tkSecurityCriticalExplicitAttributeType = mdTokenNil; - - IfFailGo(m_pRegMetaEmit->DefineTypeRefByName( - tkMscorlib, COR_SECURITYCRITICAL_ATTRIBUTE_FULL_W, - &tkSecurityCriticalExplicitAttributeType)); - - BYTE rgSigBytesSecurityCriticalExplicitCtorLocal[] = {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 0x00, ELEMENT_TYPE_VOID}; - BYTE rgSecurityCriticalExplicitCtorValue[] = COR_SECURITYCRITICAL_ATTRIBUTE_VALUE_EXPLICIT; - - IfFailGo(m_pRegMetaEmit->DefineMemberRef(tkSecurityCriticalExplicitAttributeType, - COR_CONSTRUCTOR_METADATA_IDENTIFIER, - rgSigBytesSecurityCriticalExplicitCtorLocal, - sizeof(rgSigBytesSecurityCriticalExplicitCtorLocal), - &tkSecurityCriticalAttributeExplicit)); - - IfFailGo(m_pRegMetaEmit->DefineCustomAttribute( - fakeModuleTypeRef, - fEmitSecurityEverything?tkSecurityCriticalEverythingAttribute:tkSecurityCriticalAttributeExplicit, - fEmitSecurityEverything?rgSecurityCriticalEverythingCtorValue:rgSecurityCriticalExplicitCtorValue, - fEmitSecurityEverything?sizeof(rgSecurityCriticalEverythingCtorValue):sizeof(rgSecurityCriticalExplicitCtorValue), - NULL)); - - } - } - -ErrExit: - return hr; -} // HRESULT NEWMERGER::MergeSecurityCriticalAttributes() - -//******************************************************************************* -// Helper to copy an InterfaceImpl record -//******************************************************************************* -HRESULT NEWMERGER::CopyInterfaceImpl( - InterfaceImplRec *pRecEmit, // [IN] the emit record to fill - MergeImportData *pImportData, // [IN] the importing context - InterfaceImplRec *pRecImp) // [IN] the record to import -{ - HRESULT hr; - mdToken tkParent; - mdToken tkInterface; - CMiniMdRW *pMiniMdEmit = GetMiniMdEmit(); - CMiniMdRW *pMiniMdImp; - MDTOKENMAP *pCurTkMap; - - pMiniMdImp = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - - // set the current MDTokenMap - pCurTkMap = pImportData->m_pMDTokenMap; - - tkParent = pMiniMdImp->getClassOfInterfaceImpl(pRecImp); - tkInterface = pMiniMdImp->getInterfaceOfInterfaceImpl(pRecImp); - - IfFailGo( pCurTkMap->Remap(tkParent, &tkParent) ); - IfFailGo( pCurTkMap->Remap(tkInterface, &tkInterface) ); - - IfFailGo( pMiniMdEmit->PutToken( TBL_InterfaceImpl, InterfaceImplRec::COL_Class, pRecEmit, tkParent) ); - IfFailGo( pMiniMdEmit->PutToken( TBL_InterfaceImpl, InterfaceImplRec::COL_Interface, pRecEmit, tkInterface) ); - -ErrExit: - return hr; -} // HRESULT NEWMERGER::CopyInterfaceImpl() - - -//***************************************************************************** -// Merge Assembly table -//***************************************************************************** -HRESULT NEWMERGER::MergeAssembly() -{ - HRESULT hr = NOERROR; - AssemblyRec *pRecImport = NULL; - AssemblyRec *pRecEmit = NULL; - CMiniMdRW *pMiniMdImport; - CMiniMdRW *pMiniMdEmit; - LPCUTF8 szTmp; - const BYTE *pbTmp; - ULONG cbTmp; - ULONG iRecord; - TOKENREC *pTokenRec; - - MergeImportData *pImportData; - MDTOKENMAP *pCurTkMap; - - pMiniMdEmit = GetMiniMdEmit(); - - for (pImportData = m_pImportDataList; pImportData != NULL; pImportData = pImportData->m_pNextImportData) - { - // for each import scope - pMiniMdImport = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - - // set the current MDTokenMap - pCurTkMap = pImportData->m_pMDTokenMap; - if (!pMiniMdImport->getCountAssemblys()) - goto ErrExit; // There is no Assembly in the import scope to merge. - - // Copy the Assembly map record to the Emit scope and send a token remap notifcation - // to the client. No duplicate checking needed since the Assembly can be present in - // only one scope and there can be atmost one entry. - IfFailGo(pMiniMdImport->GetAssemblyRecord(1, &pRecImport)); - IfFailGo(pMiniMdEmit->AddAssemblyRecord(&pRecEmit, &iRecord)); - - pRecEmit->Copy(pRecImport); - - IfFailGo(pMiniMdImport->getPublicKeyOfAssembly(pRecImport, &pbTmp, &cbTmp)); - IfFailGo(pMiniMdEmit->PutBlob(TBL_Assembly, AssemblyRec::COL_PublicKey, pRecEmit, - pbTmp, cbTmp)); - - IfFailGo(pMiniMdImport->getNameOfAssembly(pRecImport, &szTmp)); - IfFailGo(pMiniMdEmit->PutString(TBL_Assembly, AssemblyRec::COL_Name, pRecEmit, szTmp)); - - IfFailGo(pMiniMdImport->getLocaleOfAssembly(pRecImport, &szTmp)); - IfFailGo(pMiniMdEmit->PutString(TBL_Assembly, AssemblyRec::COL_Locale, pRecEmit, szTmp)); - - // record the token movement. - IfFailGo(pCurTkMap->InsertNotFound( - TokenFromRid(1, mdtAssembly), - false, - TokenFromRid(iRecord, mdtAssembly), - &pTokenRec)); - } -ErrExit: - return hr; -} // HRESULT NEWMERGER::MergeAssembly() - - - - -//***************************************************************************** -// Merge File table -//***************************************************************************** -HRESULT NEWMERGER::MergeFiles() -{ - HRESULT hr = NOERROR; - FileRec *pRecImport = NULL; - FileRec *pRecEmit = NULL; - CMiniMdRW *pMiniMdImport; - CMiniMdRW *pMiniMdEmit; - LPCUTF8 szTmp; - const void *pbTmp; - ULONG cbTmp; - ULONG iCount; - ULONG i; - ULONG iRecord; - TOKENREC *pTokenRec; - - MergeImportData *pImportData; - MDTOKENMAP *pCurTkMap; - - pMiniMdEmit = GetMiniMdEmit(); - - for (pImportData = m_pImportDataList; pImportData != NULL; pImportData = pImportData->m_pNextImportData) - { - // for each import scope - pMiniMdImport = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - - // set the current MDTokenMap - pCurTkMap = pImportData->m_pMDTokenMap; - iCount = pMiniMdImport->getCountFiles(); - - // Loop through all File records and copy them to the Emit scope. - // Since there can only be one File table in all the scopes combined, - // there isn't any duplicate checking that needs to be done. - for (i = 1; i <= iCount; i++) - { - IfFailGo(pMiniMdImport->GetFileRecord(i, &pRecImport)); - IfFailGo(pMiniMdEmit->AddFileRecord(&pRecEmit, &iRecord)); - - pRecEmit->Copy(pRecImport); - - IfFailGo(pMiniMdImport->getNameOfFile(pRecImport, &szTmp)); - IfFailGo(pMiniMdEmit->PutString(TBL_File, FileRec::COL_Name, pRecEmit, szTmp)); - - IfFailGo(pMiniMdImport->getHashValueOfFile(pRecImport, (const BYTE **)&pbTmp, &cbTmp)); - IfFailGo(pMiniMdEmit->PutBlob(TBL_File, FileRec::COL_HashValue, pRecEmit, pbTmp, cbTmp)); - - // record the token movement. - IfFailGo(pCurTkMap->InsertNotFound( - TokenFromRid(i, mdtFile), - false, - TokenFromRid(iRecord, mdtFile), - &pTokenRec)); - } - } -ErrExit: - return hr; -} // HRESULT NEWMERGER::MergeFiles() - - -//***************************************************************************** -// Merge ExportedType table -//***************************************************************************** -HRESULT NEWMERGER::MergeExportedTypes() -{ - HRESULT hr = NOERROR; - ExportedTypeRec *pRecImport = NULL; - ExportedTypeRec *pRecEmit = NULL; - CMiniMdRW *pMiniMdImport; - CMiniMdRW *pMiniMdEmit; - LPCUTF8 szTmp; - mdToken tkTmp; - ULONG iCount; - ULONG i; - ULONG iRecord; - TOKENREC *pTokenRec; - - MergeImportData *pImportData; - MDTOKENMAP *pCurTkMap; - - pMiniMdEmit = GetMiniMdEmit(); - - for (pImportData = m_pImportDataList; pImportData != NULL; pImportData = pImportData->m_pNextImportData) - { - // for each import scope - pMiniMdImport = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - - // set the current MDTokenMap - pCurTkMap = pImportData->m_pMDTokenMap; - iCount = pMiniMdImport->getCountExportedTypes(); - - // Loop through all ExportedType records and copy them to the Emit scope. - // Since there can only be one ExportedType table in all the scopes combined, - // there isn't any duplicate checking that needs to be done. - for (i = 1; i <= iCount; i++) - { - IfFailGo(pMiniMdImport->GetExportedTypeRecord(i, &pRecImport)); - IfFailGo(pMiniMdEmit->AddExportedTypeRecord(&pRecEmit, &iRecord)); - - pRecEmit->Copy(pRecImport); - - IfFailGo(pMiniMdImport->getTypeNameOfExportedType(pRecImport, &szTmp)); - IfFailGo(pMiniMdEmit->PutString(TBL_ExportedType, ExportedTypeRec::COL_TypeName, pRecEmit, szTmp)); - - IfFailGo(pMiniMdImport->getTypeNamespaceOfExportedType(pRecImport, &szTmp)); - IfFailGo(pMiniMdEmit->PutString(TBL_ExportedType, ExportedTypeRec::COL_TypeNamespace, pRecEmit, szTmp)); - - tkTmp = pMiniMdImport->getImplementationOfExportedType(pRecImport); - IfFailGo(pCurTkMap->Remap(tkTmp, &tkTmp)); - IfFailGo(pMiniMdEmit->PutToken(TBL_ExportedType, ExportedTypeRec::COL_Implementation, - pRecEmit, tkTmp)); - - - // record the token movement. - IfFailGo(pCurTkMap->InsertNotFound( - TokenFromRid(i, mdtExportedType), - false, - TokenFromRid(iRecord, mdtExportedType), - &pTokenRec)); - } - } -ErrExit: - return hr; -} // HRESULT NEWMERGER::MergeExportedTypes() - - -//***************************************************************************** -// Merge ManifestResource table -//***************************************************************************** -HRESULT NEWMERGER::MergeManifestResources() -{ - HRESULT hr = NOERROR; - ManifestResourceRec *pRecImport = NULL; - ManifestResourceRec *pRecEmit = NULL; - CMiniMdRW *pMiniMdImport; - CMiniMdRW *pMiniMdEmit; - LPCUTF8 szTmp; - mdToken tkTmp; - ULONG iCount; - ULONG i; - ULONG iRecord; - TOKENREC *pTokenRec; - - MergeImportData *pImportData; - MDTOKENMAP *pCurTkMap; - - pMiniMdEmit = GetMiniMdEmit(); - - for (pImportData = m_pImportDataList; pImportData != NULL; pImportData = pImportData->m_pNextImportData) - { - // for each import scope - pMiniMdImport = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - - // set the current MDTokenMap - pCurTkMap = pImportData->m_pMDTokenMap; - iCount = pMiniMdImport->getCountManifestResources(); - - // Loop through all ManifestResource records and copy them to the Emit scope. - // Since there can only be one ManifestResource table in all the scopes combined, - // there isn't any duplicate checking that needs to be done. - for (i = 1; i <= iCount; i++) - { - IfFailGo(pMiniMdImport->GetManifestResourceRecord(i, &pRecImport)); - IfFailGo(pMiniMdEmit->AddManifestResourceRecord(&pRecEmit, &iRecord)); - - pRecEmit->Copy(pRecImport); - - IfFailGo(pMiniMdImport->getNameOfManifestResource(pRecImport, &szTmp)); - IfFailGo(pMiniMdEmit->PutString(TBL_ManifestResource, ManifestResourceRec::COL_Name, - pRecEmit, szTmp)); - - tkTmp = pMiniMdImport->getImplementationOfManifestResource(pRecImport); - IfFailGo(pCurTkMap->Remap(tkTmp, &tkTmp)); - IfFailGo(pMiniMdEmit->PutToken(TBL_ManifestResource, ManifestResourceRec::COL_Implementation, - pRecEmit, tkTmp)); - - // record the token movement. - IfFailGo(pCurTkMap->InsertNotFound( - TokenFromRid(i, mdtManifestResource), - false, - TokenFromRid(iRecord, mdtManifestResource), - &pTokenRec)); - } - } -ErrExit: - return hr; -} // HRESULT NEWMERGER::MergeManifestResources() - - - - - -//***************************************************************************** -// Error handling. Call back to host to see what they want to do. -//***************************************************************************** -HRESULT NEWMERGER::OnError( - HRESULT hrIn, // The error HR we're reporting. - MergeImportData *pImportData, // The input scope with the error. - mdToken token) // The token with the error. -{ - // This function does a QI and a Release on every call. However, it should be - // called very infrequently, and lets the scope just keep a generic handler. - IMetaDataError *pIErr = NULL; - IUnknown *pHandler = pImportData->m_pHandler; - CMiniMdRW *pMiniMd = &(pImportData->m_pRegMetaImport->m_pStgdb->m_MiniMd); - CQuickArray<WCHAR> rName; // Name of the TypeDef in unicode. - LPCUTF8 szTypeName; - LPCUTF8 szNSName; - TypeDefRec *pTypeRec; - int iLen; // Length of a name. - mdToken tkParent; - HRESULT hr = NOERROR; - - if (pHandler && pHandler->QueryInterface(IID_IMetaDataError, (void**)&pIErr)==S_OK) - { - switch (hrIn) - { - - case META_E_PARAM_COUNTS: - case META_E_METHD_NOT_FOUND: - case META_E_METHDIMPL_INCONSISTENT: - { - LPCUTF8 szMethodName; - MethodRec *pMethodRec; - - // Method name. - _ASSERTE(TypeFromToken(token) == mdtMethodDef); - IfFailGo(pMiniMd->GetMethodRecord(RidFromToken(token), &pMethodRec)); - IfFailGo(pMiniMd->getNameOfMethod(pMethodRec, &szMethodName)); - MAKE_WIDEPTR_FROMUTF8_NOTHROW(wzMethodName, szMethodName); - IfNullGo(wzMethodName); - - // Type and its name. - IfFailGo( pMiniMd->FindParentOfMethodHelper(token, &tkParent) ); - IfFailGo(pMiniMd->GetTypeDefRecord(RidFromToken(tkParent), &pTypeRec)); - IfFailGo(pMiniMd->getNameOfTypeDef(pTypeRec, &szTypeName)); - IfFailGo(pMiniMd->getNamespaceOfTypeDef(pTypeRec, &szNSName)); - // Put namespace + name together. - iLen = ns::GetFullLength(szNSName, szTypeName); - IfFailGo(rName.ReSizeNoThrow(iLen+1)); - ns::MakePath(rName.Ptr(), iLen+1, szNSName, szTypeName); - - PostError(hrIn, (LPWSTR) rName.Ptr(), wzMethodName, token); - break; - } - case META_E_FIELD_NOT_FOUND: - { - LPCUTF8 szFieldName; - FieldRec *pFieldRec; - - // Field name. - _ASSERTE(TypeFromToken(token) == mdtFieldDef); - IfFailGo(pMiniMd->GetFieldRecord(RidFromToken(token), &pFieldRec)); - IfFailGo(pMiniMd->getNameOfField(pFieldRec, &szFieldName)); - MAKE_WIDEPTR_FROMUTF8_NOTHROW(wzFieldName, szFieldName); - IfNullGo(wzFieldName); - - // Type and its name. - IfFailGo( pMiniMd->FindParentOfFieldHelper(token, &tkParent) ); - IfFailGo(pMiniMd->GetTypeDefRecord(RidFromToken(tkParent), &pTypeRec)); - IfFailGo(pMiniMd->getNameOfTypeDef(pTypeRec, &szTypeName)); - IfFailGo(pMiniMd->getNamespaceOfTypeDef(pTypeRec, &szNSName)); - // Put namespace + name together. - iLen = ns::GetFullLength(szNSName, szTypeName); - IfFailGo(rName.ReSizeNoThrow(iLen+1)); - ns::MakePath(rName.Ptr(), iLen+1, szNSName, szTypeName); - - PostError(hrIn, (LPWSTR) rName.Ptr(), wzFieldName, token); - break; - } - case META_E_EVENT_NOT_FOUND: - { - LPCUTF8 szEventName; - EventRec *pEventRec; - - // Event name. - _ASSERTE(TypeFromToken(token) == mdtEvent); - IfFailGo(pMiniMd->GetEventRecord(RidFromToken(token), &pEventRec)); - IfFailGo(pMiniMd->getNameOfEvent(pEventRec, &szEventName)); - MAKE_WIDEPTR_FROMUTF8_NOTHROW(wzEventName, szEventName); - IfNullGo(wzEventName); - - // Type and its name. - IfFailGo( pMiniMd->FindParentOfEventHelper(token, &tkParent) ); - IfFailGo(pMiniMd->GetTypeDefRecord(RidFromToken(tkParent), &pTypeRec)); - IfFailGo(pMiniMd->getNameOfTypeDef(pTypeRec, &szTypeName)); - IfFailGo(pMiniMd->getNamespaceOfTypeDef(pTypeRec, &szNSName)); - // Put namespace + name together. - iLen = ns::GetFullLength(szNSName, szTypeName); - IfFailGo(rName.ReSizeNoThrow(iLen+1)); - ns::MakePath(rName.Ptr(), iLen+1, szNSName, szTypeName); - - PostError(hrIn, (LPWSTR) rName.Ptr(), wzEventName, token); - break; - } - case META_E_PROP_NOT_FOUND: - { - LPCUTF8 szPropertyName; - PropertyRec *pPropertyRec; - - // Property name. - _ASSERTE(TypeFromToken(token) == mdtProperty); - IfFailGo(pMiniMd->GetPropertyRecord(RidFromToken(token), &pPropertyRec)); - IfFailGo(pMiniMd->getNameOfProperty(pPropertyRec, &szPropertyName)); - MAKE_WIDEPTR_FROMUTF8_NOTHROW(wzPropertyName, szPropertyName); - IfNullGo(wzPropertyName); - - // Type and its name. - IfFailGo( pMiniMd->FindParentOfPropertyHelper(token, &tkParent) ); - IfFailGo(pMiniMd->GetTypeDefRecord(RidFromToken(tkParent), &pTypeRec)); - IfFailGo(pMiniMd->getNameOfTypeDef(pTypeRec, &szTypeName)); - IfFailGo(pMiniMd->getNamespaceOfTypeDef(pTypeRec, &szNSName)); - // Put namespace + name together. - iLen = ns::GetFullLength(szNSName, szTypeName); - IfFailGo(rName.ReSizeNoThrow(iLen+1)); - ns::MakePath(rName.Ptr(), iLen+1, szNSName, szTypeName); - - PostError(hrIn, (LPWSTR) rName.Ptr(), wzPropertyName, token); - break; - } - case META_S_PARAM_MISMATCH: - { - LPCUTF8 szMethodName; - MethodRec *pMethodRec; - mdToken tkMethod; - - // Method name. - _ASSERTE(TypeFromToken(token) == mdtParamDef); - IfFailGo( pMiniMd->FindParentOfParamHelper(token, &tkMethod) ); - IfFailGo(pMiniMd->GetMethodRecord(RidFromToken(tkMethod), &pMethodRec)); - IfFailGo(pMiniMd->getNameOfMethod(pMethodRec, &szMethodName)); - MAKE_WIDEPTR_FROMUTF8_NOTHROW(wzMethodName, szMethodName); - IfNullGo(wzMethodName); - - // Type and its name. - IfFailGo( pMiniMd->FindParentOfMethodHelper(token, &tkParent) ); - IfFailGo(pMiniMd->GetTypeDefRecord(RidFromToken(tkParent), &pTypeRec)); - IfFailGo(pMiniMd->getNameOfTypeDef(pTypeRec, &szTypeName)); - IfFailGo(pMiniMd->getNamespaceOfTypeDef(pTypeRec, &szNSName)); - // Put namespace + name together. - iLen = ns::GetFullLength(szNSName, szTypeName); - IfFailGo(rName.ReSizeNoThrow(iLen+1)); - ns::MakePath(rName.Ptr(), iLen+1, szNSName, szTypeName); - - // use the error hresult so that we can post the correct error. - PostError(META_E_PARAM_MISMATCH, wzMethodName, (LPWSTR) rName.Ptr(), token); - break; - } - case META_E_INTFCEIMPL_NOT_FOUND: - { - InterfaceImplRec *pRec; // The InterfaceImpl - mdToken tkIface; // Token of the implemented interface. - CQuickArray<WCHAR> rIface; // Name of the Implemented Interface in unicode. - TypeRefRec *pRef; // TypeRef record when II is a typeref. - InterfaceImplRec *pInterfaceImplRec; - - // Get the record. - _ASSERTE(TypeFromToken(token) == mdtInterfaceImpl); - IfFailGo(pMiniMd->GetInterfaceImplRecord(RidFromToken(token), &pRec)); - // Get the name of the class. - tkParent = pMiniMd->getClassOfInterfaceImpl(pRec); - IfFailGo(pMiniMd->GetTypeDefRecord(RidFromToken(tkParent), &pTypeRec)); - IfFailGo(pMiniMd->getNameOfTypeDef(pTypeRec, &szTypeName)); - IfFailGo(pMiniMd->getNamespaceOfTypeDef(pTypeRec, &szNSName)); - // Put namespace + name together. - iLen = ns::GetFullLength(szNSName, szTypeName); - IfFailGo(rName.ReSizeNoThrow(iLen+1)); - ns::MakePath(rName.Ptr(), iLen+1, szNSName, szTypeName); - - // Get the name of the implemented interface. - IfFailGo(pMiniMd->GetInterfaceImplRecord(RidFromToken(token), &pInterfaceImplRec)); - tkIface = pMiniMd->getInterfaceOfInterfaceImpl(pInterfaceImplRec); - if (TypeFromToken(tkIface) == mdtTypeDef) - { // If it is a typedef... - IfFailGo(pMiniMd->GetTypeDefRecord(RidFromToken(tkIface), &pTypeRec)); - IfFailGo(pMiniMd->getNameOfTypeDef(pTypeRec, &szTypeName)); - IfFailGo(pMiniMd->getNamespaceOfTypeDef(pTypeRec, &szNSName)); - } - else - { // If it is a typeref... - _ASSERTE(TypeFromToken(tkIface) == mdtTypeRef); - IfFailGo(pMiniMd->GetTypeRefRecord(RidFromToken(tkIface), &pRef)); - IfFailGo(pMiniMd->getNameOfTypeRef(pRef, &szTypeName)); - IfFailGo(pMiniMd->getNamespaceOfTypeRef(pRef, &szNSName)); - } - // Put namespace + name together. - iLen = ns::GetFullLength(szNSName, szTypeName); - IfFailGo(rIface.ReSizeNoThrow(iLen+1)); - ns::MakePath(rIface.Ptr(), iLen+1, szNSName, szTypeName); - - - PostError(hrIn, (LPWSTR) rName.Ptr(), (LPWSTR)rIface.Ptr(), token); - break; - } - case META_E_CLASS_LAYOUT_INCONSISTENT: - case META_E_METHOD_COUNTS: - case META_E_FIELD_COUNTS: - case META_E_EVENT_COUNTS: - case META_E_PROPERTY_COUNTS: - { - // get the type name. - _ASSERTE(TypeFromToken(token) == mdtTypeDef); - IfFailGo(pMiniMd->GetTypeDefRecord(RidFromToken(token), &pTypeRec)); - IfFailGo(pMiniMd->getNameOfTypeDef(pTypeRec, &szTypeName)); - IfFailGo(pMiniMd->getNamespaceOfTypeDef(pTypeRec, &szNSName)); - // Put namespace + name together. - iLen = ns::GetFullLength(szNSName, szTypeName); - IfFailGo(rName.ReSizeNoThrow(iLen+1)); - ns::MakePath(rName.Ptr(), iLen+1, szNSName, szTypeName); - - PostError(hrIn, (LPWSTR) rName.Ptr(), token); - break; - } - case META_E_GENERICPARAM_INCONSISTENT: - { - // If token is type, get type name; if method, get method name. - LPWSTR wzName; - LPCUTF8 szMethodName; - MethodRec *pMethodRec; - - if ((TypeFromToken(token) == mdtMethodDef)) - { - // Get the method name. - IfFailGo(pMiniMd->GetMethodRecord(RidFromToken(token), &pMethodRec)); - IfFailGo(pMiniMd->getNameOfMethod(pMethodRec, &szMethodName)); - MAKE_WIDEPTR_FROMUTF8_NOTHROW(wzMethodName, szMethodName); - IfNullGo(wzMethodName); - wzName = wzMethodName; - } - else - { - // Get the type name. - _ASSERTE(TypeFromToken(token) == mdtTypeDef); - IfFailGo(pMiniMd->GetTypeDefRecord(RidFromToken(token), &pTypeRec)); - IfFailGo(pMiniMd->getNameOfTypeDef(pTypeRec, &szTypeName)); - IfFailGo(pMiniMd->getNamespaceOfTypeDef(pTypeRec, &szNSName)); - // Put namespace + name together. - iLen = ns::GetFullLength(szNSName, szTypeName); - IfFailGo(rName.ReSizeNoThrow(iLen+1)); - ns::MakePath(rName.Ptr(), iLen+1, szNSName, szTypeName); - wzName = (LPWSTR)rName.Ptr(); - } - - PostError(hrIn, wzName, token); - break; - } - case META_E_TYPEDEF_MISSING: - { - TypeRefRec *pRef; // TypeRef record when II is a typeref. - - // Get the record. - _ASSERTE(TypeFromToken(token) == mdtTypeRef); - IfFailGo(pMiniMd->GetTypeRefRecord(RidFromToken(token), &pRef)); - IfFailGo(pMiniMd->getNameOfTypeRef(pRef, &szTypeName)); - IfFailGo(pMiniMd->getNamespaceOfTypeRef(pRef, &szNSName)); - - // Put namespace + name together. - iLen = ns::GetFullLength(szNSName, szTypeName); - IfFailGo(rName.ReSizeNoThrow(iLen+1)); - ns::MakePath(rName.Ptr(), iLen+1, szNSName, szTypeName); - - - PostError(hrIn, (LPWSTR) rName.Ptr(), token); - break; - } - default: - { - PostError(hrIn, token); - break; - } - } - hr = pIErr->OnError(hrIn, token); - } - else - hr = S_FALSE; -ErrExit: - if (pIErr) - pIErr->Release(); - return (hr); -} // NEWMERGER::OnError - -#endif //FEATURE_METADATA_EMIT_ALL diff --git a/src/md/compiler/newmerger.h b/src/md/compiler/newmerger.h deleted file mode 100644 index fc89ab7f61..0000000000 --- a/src/md/compiler/newmerger.h +++ /dev/null @@ -1,256 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. -//***************************************************************************** -// NewMerger.h -// - -// -// Contains utility code for MD directory -// -//***************************************************************************** -#ifndef __NEWMERGER__h__ -#define __NEWMERGER__h__ - -class RegMeta; - -class MDTOKENMAP; - -// module-level awareness of Security critical annotions -typedef BYTE InputScopeSecurityCriticalStatus; -#define ISSCS_Unknown 0x0 -#define ISSCS_SecurityCritical 0x1 -#define ISSCS_SecurityCriticalEverything (ISSCS_SecurityCritical | 0x2) -#define ISSCS_SecurityCriticalExplicit (ISSCS_SecurityCritical) -#define ISSCS_SecurityTransparent 0x4 -#define ISSCS_SecurityTreatAsSafe 0x8 -#define ISSCS_SECURITYCRITICAL_LEGACY (ISSCS_SecurityCriticalEverything | ISSCS_SecurityTreatAsSafe) -#define ISSCS_SECURITYCRITICAL_FLAGS (ISSCS_SecurityCriticalEverything | ISSCS_SecurityTransparent) - -//********************************************************************* -// MergeImportData -//********************************************************************* -class MergeImportData -{ -public: - RegMeta *m_pRegMetaImport; - IUnknown *m_pHandler; - IMapToken *m_pHostMapToken; - MDTOKENMAP *m_pMDTokenMap; - MergeImportData *m_pNextImportData; - - mdMemberRef m_tkSuppressMergeCheckCtor; // caches the SuppressMergeCheckAttribute's .ctor token - mdMemberRef m_tkHandleProcessCorruptedStateCtor; // caches the memberRef token to HandleProcessCorruptedStateExceptionsAttribute's .ctor token - - // import contains assembly-level SecurityTransparent or SecurityCritical - InputScopeSecurityCriticalStatus m_isscsSecurityCriticalStatus; -#if _DEBUG - int m_iImport; // debug only. This is the ith import for merge. -#endif // _DEBUG -}; - -//********************************************************************* -// MergeTypeData -//********************************************************************* -struct MergeTypeData -{ - ULONG m_cMethods; - ULONG m_cFields; - ULONG m_cEvents; - ULONG m_cProperties; - BOOL m_bSuppressMergeCheck; -}; - - -//********************************************************************* -// Class to handle merge -//********************************************************************* -class NEWMERGER -{ - friend class RegMeta; -public: - NEWMERGER(); - ~NEWMERGER(); - - HRESULT Init(RegMeta *pRegMetaDest); - - HRESULT AddImport( - IMetaDataImport2 *pImport, // [IN] The scope to be merged. - IMapToken *pHostMapToken, // [IN] Host IMapToken interface to receive token remap notification - IUnknown *pHandler); // [IN] An object to receive to receive error notification. - - HRESULT Merge(MergeFlags flags, CorRefToDefCheck optimizeRefToDef); - -protected: - - CMiniMdRW *GetMiniMdEmit(); - - HRESULT InitMergeTypeData(); - - HRESULT MergeTypeDefNamesOnly(); - HRESULT MergeModuleRefs(); - HRESULT MergeAssemblyRefs(); - HRESULT MergeTypeRefs(); - HRESULT CompleteMergeTypeDefs(); - - HRESULT CopyTypeDefPartially( - TypeDefRec *pRecEmit, // [IN] the emit record to fill - CMiniMdRW *pMiniMdImport, // [IN] the importing scope - TypeDefRec *pRecImp); // [IN] the record to import - - // helpers for merging tables - HRESULT MergeModule( ); - HRESULT MergeTypeDefChildren(); - HRESULT MergeInterfaceImpls( ); - HRESULT MergeMemberRefs( ); - HRESULT MergePinvoke(); - - HRESULT MergeConstants( ); - HRESULT MergeCustomAttributes( ); - HRESULT MergeFieldMarshals( ); - HRESULT MergeDeclSecuritys( ); - HRESULT MergeClassLayouts( ); - HRESULT MergeFieldLayouts( ); - HRESULT MergeFieldRVAs(); - HRESULT MergeMethodImpls( ); - HRESULT MergeStandAloneSigs(); - HRESULT MergeMethodSpecs(); - HRESULT MergeTypeSpecs(); - HRESULT MergeSourceFiles( ); - HRESULT MergeBlocks( ); - HRESULT MergeScopes( ); - HRESULT MergeLocalVariables( ); - HRESULT MergeStrings( ); - - HRESULT MergeAssembly(); - HRESULT MergeFiles(); - HRESULT MergeExportedTypes(); - HRESULT MergeManifestResources(); - - // helpers for SecurityCritical-related merging - InputScopeSecurityCriticalStatus CheckInputScopeIsCritical(MergeImportData* pImportData, HRESULT& hr); - HRESULT RetrieveStandardSecurityCriticalMetaData( - mdAssemblyRef& tkMscorlib, - mdTypeRef& securityEnum, - BYTE*& rgSigBytesSecurityCriticalEverythingCtor, - DWORD& dwSigEverythingSize, - BYTE*& rgSigBytesSecurityCriticalExplicitCtor, - DWORD& dwSigExplicitSize); - - HRESULT MergeSecurityCriticalModuleLevelAttributes( - MergeImportData* pImportData, - mdToken tkParentImp, TOKENREC* pTypeRec, - mdToken mrSecurityTreatAsSafeAttributeCtor, - mdToken mrSecurityTransparentAttributeCtor, - mdToken mrSecurityCriticalExplicitAttributeCtor, - mdToken mrSecurityCriticalEverythingAttributeCtor); - HRESULT MergeSecurityCriticalAttributes(); - - // copy over a interfaceimpl record - HRESULT CopyInterfaceImpl( - InterfaceImplRec *pRecEmit, // [IN] the emit record to fill - MergeImportData *pImportData, // [IN] the importing context - InterfaceImplRec *pRecImp); // [IN] the record to import - - // verification helpers - HRESULT VerifyMethods(MergeImportData *pImportData, mdTypeDef tdImp, mdTypeDef tdEmit); - HRESULT VerifyFields(MergeImportData *pImportData, mdTypeDef tdImp, mdTypeDef tdEmit); - HRESULT VerifyEvents(MergeImportData *pImportData, mdTypeDef tdImp, mdTypeDef tdEmit); - HRESULT VerifyProperties(MergeImportData *pImportData, mdTypeDef tdImp, mdTypeDef tdEmit); - HRESULT VerifyParams(MergeImportData *pImportData, mdMethodDef mdImp, mdMethodDef mdEmit); - HRESULT VerifyGenericParams(MergeImportData *pImportData, mdTypeDef tdImp, mdTypeDef tdEmit); - HRESULT VerifyGenericParamConstraints(MergeImportData *pImportData, mdGenericParam gpImp, mdGenericParam gpEmit); - - // Copy helpers - HRESULT CopyMethods(MergeImportData *pImportData, mdTypeDef tdImp, mdTypeDef tdEmit); - HRESULT CopyFields(MergeImportData *pImportData, mdTypeDef tdImp, mdTypeDef tdEmit); - HRESULT CopyEvents(MergeImportData *pImportData, mdTypeDef tdImp, mdTypeDef tdEmit); - HRESULT CopyProperties(MergeImportData *pImportData, mdTypeDef tdImp, mdTypeDef tdEmit); - HRESULT CopyParams(MergeImportData *pImportData, mdMethodDef mdImp, mdMethodDef mdEmit); - HRESULT CopyGenericParams(MergeImportData *pImportData, mdToken tkImp, mdToken tkEmit); - HRESULT CopyGenericParamConstraints(MergeImportData *pImportData, mdGenericParam gpImp, mdGenericParam gpEmit); - - HRESULT CopyMethod( - MergeImportData *pImportData, // [IN] import scope - MethodRec *pRecImp, // [IN] the record to import - MethodRec *pRecEmit); // [IN] the emit record to fill - - HRESULT CopyField( - MergeImportData *pImportData, // [IN] import scope - FieldRec *pRecImp, // [IN] the record to import - FieldRec *pRecEmit); // [IN] the emit record to fill - - HRESULT CopyEvent( - MergeImportData *pImportData, // [IN] import scope - EventRec *pRecImp, // [IN] the record to import - EventRec *pRecEmit); // [IN] the emit record to fill - - HRESULT CopyProperty( - MergeImportData *pImportData, // [IN] import scope - PropertyRec *pRecImp, // [IN] the record to import - PropertyRec *pRecEmit); // [IN] the emit record to fill - - HRESULT CopyParam( - MergeImportData *pImportData, // [IN] import scope - ParamRec *pRecImp, // [IN] the record to import - ParamRec *pRecEmit); // [IN] the emit record to fill - - HRESULT CopyMethodSemantics( - MergeImportData *pImportData, - mdToken tkImport, // Event or property in the import scope - mdToken tkEmit); // corresponding event or property in the emitting scope - - HRESULT VerifyMethod( - MergeImportData *pImportData, - mdMethodDef mdImp, // [IN] the emit record to fill - mdMethodDef mdEmit); // [IN] the record to import - - HRESULT OnError(HRESULT hr, MergeImportData *pImportData, mdToken token); - -private: - RegMeta *m_pRegMetaEmit; - MergeImportData *m_pImportDataList; - MergeImportData **m_pImportDataTail; - MergeFlags m_dwMergeFlags; - BOOL m_fDupCheck; - CorRefToDefCheck m_optimizeRefToDef; - // the combined value of the Security Critical input scopes (e.g. UNION of each scope's attributes) - // if ANY of the scopes have a bit set, then we must do some merging - InputScopeSecurityCriticalStatus m_isscsSecurityCritical; - // the common values of the Security Critical input scopes (e.g. INTERSECTION of each scope's attributes) - // if all scopes have the same bit set, then we can emit one bit at the final output scope - InputScopeSecurityCriticalStatus m_isscsSecurityCriticalAllScopes; - - CDynArray<MergeTypeData> m_rMTDs; -#if _DEBUG - int m_iImport; // debug only. To count how many import scopes to be merged. -#endif // _DEBUG -}; - - -#define CheckContinuableErrorEx(EXPR, HANDLER, TOKEN) \ -{ \ - HRESULT hrOnErr, hrExpr; \ - hrExpr = EXPR; \ - \ - hrOnErr = OnError(hrExpr, HANDLER, TOKEN); \ - if (hrOnErr != S_OK) \ - { \ - if (hrOnErr == S_FALSE) \ - { \ - hr = hrExpr; \ - } \ - else if (SUCCEEDED(hrOnErr)) \ - { \ - hr = E_UNEXPECTED; \ - } \ - else if (FAILED(hrOnErr)) \ - { \ - hr = hrOnErr; \ - } \ - IfFailGo(hr); \ - } \ -} - - -#endif // __NEWMERGER__h__ diff --git a/src/md/compiler/regmeta.cpp b/src/md/compiler/regmeta.cpp index feb1cdd31b..f591a6e01b 100644 --- a/src/md/compiler/regmeta.cpp +++ b/src/md/compiler/regmeta.cpp @@ -59,9 +59,6 @@ RegMeta::RegMeta() : m_fIsTypeDefDirty(false), m_fIsMemberDefDirty(false), m_fStartedEE(false), -#ifdef FEATURE_INCLUDE_ALL_INTERFACES - m_pCorHost(NULL), -#endif // FEATURE_INCLUDE_ALL_INTERFACES m_pAppDomain(NULL), m_OpenFlags(0), m_cRef(0), @@ -167,10 +164,6 @@ RegMeta::~RegMeta() if (m_fStartedEE) { m_pAppDomain->Release(); -#ifdef FEATURE_INCLUDE_ALL_INTERFACES - m_pCorHost->Stop(); - m_pCorHost->Release(); -#endif // FEATURE_INCLUDE_ALL_INTERFACES } if (m_pFilterManager != NULL) @@ -284,11 +277,6 @@ RegMeta::CreateNewMD() INDEBUG(m_pStgdb->m_MiniMd.Debug_SetLock(m_pSemReadWrite);) } -#ifdef FEATURE_METADATA_EMIT_ALL - // initialize the embedded merger - m_newMerger.Init(this); -#endif //FEATURE_METADATA_EMIT_ALL - ErrExit: return hr; } // RegMeta::CreateNewMD @@ -347,11 +335,6 @@ HRESULT RegMeta::OpenExistingMD( if (!IsOfReOpen(dwOpenFlags)) { -#ifdef FEATURE_METADATA_EMIT_ALL - // initialize the embedded merger - m_newMerger.Init(this); -#endif //FEATURE_METADATA_EMIT_ALL - // There must always be a Global Module class and its the first entry in // the TypeDef table. m_tdModule = TokenFromRid(1, mdtTypeDef); @@ -405,11 +388,6 @@ HRESULT RegMeta::OpenExistingMD( if (!IsOfReOpen(dwOpenFlags)) { -#ifdef FEATURE_METADATA_EMIT_ALL - // initialize the embedded merger - m_newMerger.Init(this); -#endif //FEATURE_METADATA_EMIT_ALL - // There must always be a Global Module class and its the first entry in // the TypeDef table. m_tdModule = TokenFromRid(1, mdtTypeDef); @@ -556,12 +534,10 @@ RegMeta::QueryInterface( *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) @@ -581,12 +557,6 @@ RegMeta::QueryInterface( } #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) @@ -698,7 +668,6 @@ ErrExit: return hr; } // RegMeta::QueryInterface -#ifndef FEATURE_METADATA_STANDALONE_WINRT //--------------------------------------------------------------------------------------- // @@ -794,7 +763,6 @@ ErrExit: return hr; } // RegMeta::GetFileMapping -#endif //!FEATURE_METADATA_STANDALONE_WINRT //------------------------------------------------------------------------------ // Metadata dump diff --git a/src/md/compiler/regmeta.h b/src/md/compiler/regmeta.h index cb7bae17b5..04456d8548 100644 --- a/src/md/compiler/regmeta.h +++ b/src/md/compiler/regmeta.h @@ -20,16 +20,11 @@ #include "../inc/mdlog.h" #include "utsem.h" -#include "newmerger.h" - #include "rwutil.h" #include "mdperf.h" #include <ivehandler.h> #include "sigparser.h" -#ifdef FEATURE_FUSION -#include "fusion.h" -#endif #include "winmdinterfaces.h" @@ -155,9 +150,7 @@ class RegMeta : public IMetaDataAssemblyImport, public IMetaDataTables2 -#ifndef FEATURE_METADATA_STANDALONE_WINRT , public IMetaDataInfo -#endif #ifdef FEATURE_METADATA_EMIT , public IMetaDataEmit2 @@ -188,7 +181,6 @@ class RegMeta : #endif , public IMDCommon { - friend class NEWMERGER; friend class CImportTlb; friend class MDInternalRW; friend class MDInternalRO; @@ -1492,7 +1484,6 @@ public: const void **ppv, // [OUT] put pointer to MD stream here. ULONG *pcb); // [OUT] put size of the stream here. -#ifndef FEATURE_METADATA_STANDALONE_WINRT //***************************************************************************** // IMetaDataInfo @@ -1511,7 +1502,6 @@ public: ULONGLONG * pcbData, // [out] Size of the mapped memory region.. DWORD * pdwMappingType); // [out] Type of file mapping (code:CorFileMapping). -#endif //!FEATURE_METADATA_STANDALONE_WINRT #if defined(FEATURE_METADATA_IN_VM) && defined(FEATURE_PREJIT) @@ -1633,8 +1623,6 @@ protected: } HRESULT PreSave(); - HRESULT ProcessFilter(); - HRESULT ProcessFilterWorker(); // Initialize the EE HRESULT StartupEE(); @@ -2026,18 +2014,12 @@ protected: bool m_fIsTypeDefDirty; // This flag is set when the TypeRef to TypeDef map is not valid bool m_fIsMemberDefDirty; // This flag is set when the MemberRef to MemberDef map is not valid bool m_fStartedEE; // Set when EE runtime has been started up. -#ifdef FEATURE_INCLUDE_ALL_INTERFACES - ICorRuntimeHost *m_pCorHost; // Hosting environment for EE runtime. -#endif // FEATURE_INCLUDE_ALL_INTERFACES IUnknown *m_pAppDomain; // AppDomain in which managed security code will be run. private: ULONG m_OpenFlags; // Open time flags. LONG m_cRef; // Ref count. -#ifdef FEATURE_METADATA_EMIT_ALL - NEWMERGER m_newMerger; // class for handling merge -#endif //FEATURE_METADATA_EMIT_ALL IUnknown *m_pFreeThreadedMarshaler; // FreeThreadedMarshaler #ifdef FEATURE_METADATA_PERF_STATS @@ -2059,9 +2041,6 @@ private: CorValidatorModuleType m_ModuleType; IVEHandler *m_pVEHandler; -#ifndef FEATURE_CORECLR - ValidateRecordFunction m_ValidateRecordFunctionTable[TBL_COUNT]; -#endif CCustAttrHash m_caHash; // Hashed list of custom attribute types seen. bool m_bKeepKnownCa; // Should all known CA's be kept? diff --git a/src/md/compiler/regmeta_compilersupport.cpp b/src/md/compiler/regmeta_compilersupport.cpp index 0bea06699b..571f9288b6 100644 --- a/src/md/compiler/regmeta_compilersupport.cpp +++ b/src/md/compiler/regmeta_compilersupport.cpp @@ -49,35 +49,7 @@ STDMETHODIMP RegMeta::Merge( // S_OK or error. IMapToken *pHostMapToken, // [IN] Host IMapToken interface to receive token remap notification IUnknown *pHandler) // [IN] An object to receive to receive error notification. { -#ifdef FEATURE_METADATA_EMIT_ALL - HRESULT hr = NOERROR; - - BEGIN_ENTRYPOINT_NOTHROW; - - IMetaDataImport2 *pI2=NULL; - - LOG((LOGMD, "RegMeta::Merge(0x%08x, 0x%08x)\n", pImport, pHandler)); - START_MD_PERF(); - LOCKWRITE(); - - IfFailGo(VerifyNotWinMD(pImport, "IMetaDataEmit::Merge(): merging with a .winmd file not supported.")); - - IfFailGo(pImport->QueryInterface(IID_IMetaDataImport2, (void**)&pI2)); - m_hasOptimizedRefToDef = false; - - // track this import - IfFailGo( m_newMerger.AddImport(pI2, pHostMapToken, pHandler) ); - -ErrExit: - if (pI2) - pI2->Release(); - STOP_MD_PERF(Merge); - END_ENTRYPOINT_NOTHROW; - - return (hr); -#else //!FEATURE_METADATA_EMIT_ALL return E_NOTIMPL; -#endif //!FEATURE_METADATA_EMIT_ALL } // RegMeta::Merge @@ -86,32 +58,7 @@ ErrExit: //***************************************************************************** STDMETHODIMP RegMeta::MergeEnd() // S_OK or error. { -#ifdef FEATURE_METADATA_EMIT_ALL - HRESULT hr = NOERROR; - - BEGIN_ENTRYPOINT_NOTHROW; - - LOG((LOGMD, "RegMeta::MergeEnd()\n")); - START_MD_PERF(); - LOCKWRITE(); - // Merge happens here!! - - // <REVISIT_TODO>bug 16719. Merge itself is doing a lots of small changes in literally - // dozens of places. It would be to hard to maintain and would cause code - // bloat to auto-grow the tables. So instead, we've opted to just expand - // the world right away and avoid the trouble.</REVISIT_TODO> - IfFailGo(m_pStgdb->m_MiniMd.ExpandTables()); - - IfFailGo(m_newMerger.Merge(m_OptionValue.m_MergeOptions, m_OptionValue.m_RefToDefCheck) ); - -ErrExit: - STOP_MD_PERF(MergeEnd); - END_ENTRYPOINT_NOTHROW; - - return (hr); -#else //!FEATURE_METADATA_EMIT_ALL return E_NOTIMPL; -#endif //!FEATURE_METADATA_EMIT_ALL } // RegMeta::MergeEnd @@ -282,225 +229,4 @@ ErrExit: #endif //!FEATURE_METADATA_EMIT_ALL } // RegMeta::ResetENCLog -#ifdef FEATURE_METADATA_EMIT_ALL - -// Helper for code:RegMeta::ProcessFilter -HRESULT RegMeta::ProcessFilterWorker() -{ - HRESULT hr = S_OK; - - CMiniMdRW *pMiniMd; // The MiniMd with the data. - RegMeta *pMetaNew = NULL; - CMapToken *pMergeMap = NULL; - IMapToken *pMapNew = NULL; - MergeTokenManager *pCompositHandler = NULL; - IMapToken *pHostMapToken = NULL; - - // For convenience. - pMiniMd = &(m_pStgdb->m_MiniMd); - IfNullGo( pMiniMd->GetFilterTable() ); - _ASSERTE(pMiniMd->GetFilterTable()->Count() != 0); // caller verified this - - // Yes, client has used filter to specify what are the metadata needed. - // We will create another instance of RegMeta and make this module an imported module - // to be merged into the new RegMeta. We will provide the handler to track all of the token - // movements. We will replace the merged light weight stgdb to this RegMeta.. - // Then we will need to fix up the MergeTokenManager with this new movement. - // The reason that we decide to choose this approach is because it will be more complicated - // and very likely less efficient to fix up the signature blob pool and then compact all of the pools! - // - - // Create a new RegMeta. - pMetaNew = new (nothrow) RegMeta(); - IfNullGo( pMetaNew ); - pMetaNew->AddRef(); - IfFailGo(pMetaNew->SetOption(&m_OptionValue)); - - - // Remember the open type. - IfFailGo(pMetaNew->CreateNewMD()); - IfFailGo(pMetaNew->AddToCache()); - - // Ignore the error return by setting handler - hr = pMetaNew->SetHandler(m_pHandler); - - // create the IMapToken to receive token remap information from merge - pMergeMap = new (nothrow) CMapToken; - IfNullGo( pMergeMap ); - - // use merge to filter out the unneeded data. But we need to keep COMType and also need to drop off the - // CustomAttributes that associated with MemberRef with parent MethodDef - // - pMetaNew->m_hasOptimizedRefToDef = false; - IfFailGo( pMetaNew->m_newMerger.AddImport(this, pMergeMap, NULL) ); - IfFailGo( pMetaNew->m_pStgdb->m_MiniMd.ExpandTables()); - IfFailGo( pMetaNew->m_newMerger.Merge((MergeFlags)(MergeManifest | DropMemberRefCAs | NoDupCheck), MDRefToDefDefault) ); - - // Now we need to recalculate the token movement - // - if (m_newMerger.m_pImportDataList) - { - - // This is the case the filter is applied to merged emit scope. We need calculate how this implicit merge - // affects the original merge remap. Basically we need to walk all the m_pTkMapList in the merger and replace - // the to token to the most recent to token. - // - MDTOKENMAP *pMDTokenMapList; - - pMDTokenMapList = m_newMerger.m_pImportDataList->m_pMDTokenMap; - - MDTOKENMAP *pMap; - TOKENREC *pTKRec; - ULONG i; - mdToken tkFinalTo; - ModuleRec *pMod; - ModuleRec *pModNew; - LPCUTF8 szName; - - // update each import map from merge to have the m_tkTo points to the final mapped to token - for (pMap = pMDTokenMapList; pMap; pMap = pMap->m_pNextMap) - { - // update each record - for (i = 0; i < (ULONG) (pMap->Count()); i++) - { - TOKENREC *pRecTo; - pTKRec = pMap->Get(i); - if ( pMergeMap->Find( pTKRec->m_tkTo, &pRecTo ) ) - { - // This record is kept by the filter and the tkTo is changed - pRecTo->m_isFoundInImport = true; - tkFinalTo = pRecTo->m_tkTo; - pTKRec->m_tkTo = tkFinalTo; - pTKRec->m_isDeleted = false; - - // send the notification now. Because after merge, we may have everything in order and - // won't send another set of notification. - // - LOG((LOGMD, "TokenRemap in RegMeta::ProcessFilter (IMapToken 0x%08x): from 0x%08x to 0x%08x\n", pMap->m_pMap, pTKRec->m_tkFrom, pTKRec->m_tkTo)); - - pMap->m_pMap->Map(pTKRec->m_tkFrom, pTKRec->m_tkTo); - } - else - { - // This record is pruned by the filter upon save - pTKRec->m_isDeleted = true; - } - } - } - - // now walk the pMergeMap and check to see if there is any entry that is not set to true for m_isFoundInImport. - // These are the records that from calling DefineXXX methods directly on the Emitting scope! - if (m_pHandler) - m_pHandler->QueryInterface(IID_IMapToken, (void **)&pHostMapToken); - if (pHostMapToken) - { - for (i = 0; i < (ULONG) (pMergeMap->m_pTKMap->Count()); i++) - { - pTKRec = pMergeMap->m_pTKMap->Get(i); - if (pTKRec->m_isFoundInImport == false) - { - LOG((LOGMD, "TokenRemap in RegMeta::ProcessFilter (default IMapToken 0x%08x): from 0x%08x to 0x%08x\n", pHostMapToken, pTKRec->m_tkFrom, pTKRec->m_tkTo)); - - // send the notification on the IMapToken from SetHandler of this RegMeta - pHostMapToken->Map(pTKRec->m_tkFrom, pTKRec->m_tkTo); - } - } - } - - // Preserve module name across merge. - IfFailGo(m_pStgdb->m_MiniMd.GetModuleRecord(1, &pMod)); - IfFailGo(pMetaNew->m_pStgdb->m_MiniMd.GetModuleRecord(1, &pModNew)); - IfFailGo(m_pStgdb->m_MiniMd.getNameOfModule(pMod, &szName)); - IfFailGo(pMetaNew->m_pStgdb->m_MiniMd.PutString(TBL_Module, ModuleRec::COL_Name, pModNew, szName)); - - // now swap the stgdb but keep the merger... - _ASSERTE( !IsOfExternalStgDB(m_OpenFlags) ); - - CLiteWeightStgdbRW * pStgdbTmp = m_pStgdb; - m_pStgdb = pMetaNew->m_pStgdb; - pMetaNew->m_pStgdb = pStgdbTmp; - // Update RuntimeVersion string pointers to point to the owning RegMeta string (the strings are 2 copies of the same string content) - m_pStgdb->m_MiniMd.m_OptionValue.m_RuntimeVersion = m_OptionValue.m_RuntimeVersion; - pMetaNew->m_pStgdb->m_MiniMd.m_OptionValue.m_RuntimeVersion = pMetaNew->m_OptionValue.m_RuntimeVersion; - } - else - { - // swap the Stgdb - CLiteWeightStgdbRW * pStgdbTmp = m_pStgdb; - m_pStgdb = pMetaNew->m_pStgdb; - pMetaNew->m_pStgdb = pStgdbTmp; - // Update RuntimeVersion string pointers to point to the owning RegMeta string (the strings are 2 copies of the same string content) - m_pStgdb->m_MiniMd.m_OptionValue.m_RuntimeVersion = m_OptionValue.m_RuntimeVersion; - pMetaNew->m_pStgdb->m_MiniMd.m_OptionValue.m_RuntimeVersion = pMetaNew->m_OptionValue.m_RuntimeVersion; - - // Client either open an existing scope and apply the filter mechanism, or client define the scope and then - // apply the filter mechanism. - - // In this case, host better has supplied the handler!! - _ASSERTE( m_bRemap && m_pHandler); - IfFailGo( m_pHandler->QueryInterface(IID_IMapToken, (void **) &pMapNew) ); - - - { - // Send the notification of token movement now because after merge we may not move tokens again - // and thus no token notification will be send. - MDTOKENMAP *pMap = pMergeMap->m_pTKMap; - TOKENREC *pTKRec; - ULONG i; - - for (i=0; i < (ULONG) (pMap->Count()); i++) - { - pTKRec = pMap->Get(i); - pMap->m_pMap->Map(pTKRec->m_tkFrom, pTKRec->m_tkTo); - } - - } - - - // What we need to do here is create a IMapToken that will replace the original handler. This new IMapToken - // upon called will first map the from token to the most original from token. - // - pCompositHandler = new (nothrow) MergeTokenManager(pMergeMap->m_pTKMap, NULL); - IfNullGo( pCompositHandler ); - - // now update the following field to hold on to the real IMapToken supplied by our client by SetHandler - if (pMergeMap->m_pTKMap->m_pMap) - pMergeMap->m_pTKMap->m_pMap->Release(); - _ASSERTE(pMapNew); - pMergeMap->m_pTKMap->m_pMap = pMapNew; - - // ownership transferred - pMergeMap = NULL; - pMapNew = NULL; - - // now you want to replace all of the IMapToken set by calling SetHandler to this new MergeTokenManager - IfFailGo( m_pStgdb->m_MiniMd.SetHandler(pCompositHandler) ); - - m_pHandler = pCompositHandler; - - // ownership transferred - pCompositHandler = NULL; - } - - // Force a ref to def optimization because the remap information was stored in the thrown away CMiniMdRW - m_hasOptimizedRefToDef = false; - IfFailGo( RefToDefOptimization() ); - -ErrExit: - if (pHostMapToken) - pHostMapToken->Release(); - if (pMetaNew) - pMetaNew->Release(); - if (pMergeMap) - pMergeMap->Release(); - if (pCompositHandler) - pCompositHandler->Release(); - if (pMapNew) - pMapNew->Release(); - - return hr; -} // RegMeta::ProcessFilter - -#endif //FEATURE_METADATA_EMIT_ALL - #endif //FEATURE_METADATA_EMIT diff --git a/src/md/compiler/regmeta_emit.cpp b/src/md/compiler/regmeta_emit.cpp index 22d2979343..d3268fec8a 100644 --- a/src/md/compiler/regmeta_emit.cpp +++ b/src/md/compiler/regmeta_emit.cpp @@ -279,13 +279,6 @@ STDMETHODIMP RegMeta::GetSaveSize( // S_OK or error. IfFailGo(m_pFilterManager->Mark(TokenFromRid(iCount, mdtAssembly))); } } -#ifdef FEATURE_METADATA_EMIT_ALL - else if (m_newMerger.m_pImportDataList) - { - // always pipe through another pass of merge to drop unnecessary ref for linker. - MarkAll(); - } -#endif //FEATURE_METADATA_EMIT_ALL IfFailGo(PreSave()); @@ -734,7 +727,6 @@ HRESULT RegMeta::PreSave() // Return code. HRESULT hr = S_OK; // A result. CMiniMdRW *pMiniMd; // The MiniMd with the data. unsigned bRemapOld = m_bRemap; - MergeTokenManager *ptkMgr = NULL; // For convenience. pMiniMd = &(m_pStgdb->m_MiniMd); @@ -745,21 +737,6 @@ HRESULT RegMeta::PreSave() // Return code. if (m_bSaveOptimized) goto ErrExit; -#ifdef FEATURE_METADATA_EMIT_ALL - if (m_newMerger.m_pImportDataList != NULL) - { - // This is the linker scenario. We we have IMap for each scope. We will create an instance of our own mapper - // who knows how to send notification back to host! - - // cache the host provided handler to the end our MergeTokenManager - - ptkMgr = new (nothrow) MergeTokenManager(m_newMerger.m_pImportDataList->m_pMDTokenMap, m_pHandler); - IfNullGo(ptkMgr); - hr = m_pStgdb->m_MiniMd.SetHandler(ptkMgr); - _ASSERTE(SUCCEEDED(hr)); - } -#endif //FEATURE_METADATA_EMIT_ALL - IfFailGo(RefToDefOptimization()); // we need to update MethodImpl table here with ref to def result @@ -808,19 +785,7 @@ HRESULT RegMeta::PreSave() // Return code. } } } - -#ifdef FEATURE_METADATA_EMIT_ALL - IfFailGo(ProcessFilter()); - - if (m_newMerger.m_pImportDataList != NULL) - { - // Allocate a token mapper object that will be used for phase 1 if there is not Handler but - // linker has provided the IMapToken - // - m_bRemap = true; - } -#endif //FEATURE_METADATA_EMIT_ALL - + // reget the minimd because it can be swapped in the call of ProcessFilter pMiniMd = &(m_pStgdb->m_MiniMd); @@ -831,13 +796,6 @@ HRESULT RegMeta::PreSave() // Return code. IfFailGo(m_pStgdb->m_MiniMd.PreSave(m_ReorderingOptions, m_pCorProfileData)); ErrExit: - if (ptkMgr != NULL) - { - // recovery the initial state - hr = m_pStgdb->m_MiniMd.SetHandler(NULL); - ptkMgr->Release(); - } - m_bRemap = bRemapOld; return hr; @@ -1008,37 +966,6 @@ ErrExit: return hr; } // RegMeta::RefToDefOptimization -#ifdef FEATURE_METADATA_EMIT_ALL - -//***************************************************************************** -// Process filter -//***************************************************************************** -HRESULT RegMeta::ProcessFilter() -{ - HRESULT hr = S_OK; - - CMiniMdRW *pMiniMd; // The MiniMd with the data. - - START_MD_PERF(); - - // For convenience. - pMiniMd = &(m_pStgdb->m_MiniMd); - IfNullGo( pMiniMd->GetFilterTable() ); - if ( pMiniMd->GetFilterTable()->Count() == 0 ) - { - // there is no filter - goto ErrExit; - } - hr = ProcessFilterWorker(); - -ErrExit: - STOP_MD_PERF(ProcessFilter); - - return hr; -} // RegMeta::ProcessFilter - -#endif //FEATURE_METADATA_EMIT_ALL - //***************************************************************************** // Define a TypeRef given the fully qualified name. //***************************************************************************** diff --git a/src/md/compiler/regmeta_vm.cpp b/src/md/compiler/regmeta_vm.cpp index beebb08b5c..a4d9397b0e 100644 --- a/src/md/compiler/regmeta_vm.cpp +++ b/src/md/compiler/regmeta_vm.cpp @@ -29,23 +29,6 @@ #include <metamodelrw.h> -#ifndef FEATURE_CORECLR - -#include <metahost.h> - -// Pointer to the activated CLR interface provided by the shim. -extern ICLRRuntimeInfo *g_pCLRRuntime; - -#ifdef FEATURE_METADATA_EMIT_ALL - -#include "iappdomainsetup.h" - -// {27FFF232-A7A8-40dd-8D4A-734AD59FCD41} -EXTERN_GUID(IID_IAppDomainSetup, 0x27FFF232, 0xA7A8, 0x40dd, 0x8D, 0x4A, 0x73, 0x4A, 0xD5, 0x9F, 0xCD, 0x41); - -#endif //FEATURE_METADATA_EMIT_ALL - -#endif // !FEATURE_CORECLR #define DEFINE_CUSTOM_NODUPCHECK 1 @@ -66,7 +49,7 @@ EXTERN_GUID(IID_IAppDomainSetup, 0x27FFF232, 0xA7A8, 0x40dd, 0x8D, 0x4A, 0x73, 0 //***************************************************************************** HRESULT RegMeta::AddToCache() { -#if defined(FEATURE_METADATA_IN_VM) || defined(FEATURE_METADATA_STANDALONE_WINRT) +#if defined(FEATURE_METADATA_IN_VM) HRESULT hr = S_OK; // The ref count must be > 0 before the module is published, else another @@ -83,9 +66,9 @@ ErrExit: m_bCached = false; } return hr; -#else //!FEATURE_METADATA_IN_VM && !FEATURE_METADATA_STANDALONE_WINRT +#else // FEATURE_METADATA_IN_VM return S_OK; -#endif //!FEATURE_METADATA_IN_VM && !FEATURE_METADATA_STANDALONE_WINRT +#endif // FEATURE_METADATA_IN_VM } // RegMeta::AddToCache @@ -97,13 +80,13 @@ HRESULT RegMeta::FindCachedReadOnlyEntry( DWORD dwOpenFlags, // Flags the new file is opened with. RegMeta **ppMeta) // Put found RegMeta here. { -#if defined(FEATURE_METADATA_IN_VM) || defined(FEATURE_METADATA_STANDALONE_WINRT) +#if defined(FEATURE_METADATA_IN_VM) return LOADEDMODULES::FindCachedReadOnlyEntry(szName, dwOpenFlags, ppMeta); -#else //!FEATURE_METADATA_IN_VM && !FEATURE_METADATA_STANDALONE_WINRT +#else // FEATURE_METADATA_IN_VM // No cache support in standalone version. *ppMeta = NULL; return S_FALSE; -#endif //!FEATURE_METADATA_IN_VM && !FEATURE_METADATA_STANDALONE_WINRT +#endif // FEATURE_METADATA_IN_VM } // RegMeta::FindCachedReadOnlyEntry @@ -117,90 +100,8 @@ HRESULT RegMeta::FindCachedReadOnlyEntry( //***************************************************************************** HRESULT RegMeta::StartupEE() { -#ifdef FEATURE_CORECLR UNREACHABLE_MSG_RET("About to CoCreateInstance! This code should not be " "reachable or needs to be reimplemented for CoreCLR!"); -#else // !FEATURE_CORECLR - - struct Param - { - RegMeta *pThis; - IUnknown *pSetup; - IAppDomainSetup *pDomainSetup; - bool fDoneStart; - HRESULT hr; - } param; - param.pThis = this; - param.pSetup = NULL; - param.pDomainSetup = NULL; - param.fDoneStart = false; - param.hr = S_OK; - - PAL_TRY(Param *, pParam, ¶m) - { - HRESULT hr = S_OK; - - DWORD dwBuffer[1 + (MAX_LONGPATH+1) * sizeof(WCHAR) / sizeof(DWORD) + 1]; - BSTR bstrDir = NULL; - - // Create a hosting environment. - IfFailGo(g_pCLRRuntime->GetInterface( - CLSID_CorRuntimeHost, - IID_ICorRuntimeHost, - (void **)&pParam->pThis->m_pCorHost)); - - // Startup the runtime. - IfFailGo(pParam->pThis->m_pCorHost->Start()); - pParam->fDoneStart = true; - - // Create an AppDomain Setup so we can set the AppBase. - IfFailGo(pParam->pThis->m_pCorHost->CreateDomainSetup(&pParam->pSetup)); - - // Get the current directory (place it in a BSTR). - bstrDir = (BSTR)(dwBuffer + 1); - if ((dwBuffer[0] = (WszGetCurrentDirectory(MAX_LONGPATH + 1, bstrDir) * sizeof(WCHAR)))) - { - // QI for the IAppDomainSetup interface. - IfFailGo(pParam->pSetup->QueryInterface(IID_IAppDomainSetup, - (void**)&pParam->pDomainSetup)); - - // Set the AppBase. - pParam->pDomainSetup->put_ApplicationBase(bstrDir); - } - - // Create a new AppDomain. - IfFailGo(pParam->pThis->m_pCorHost->CreateDomainEx(W("Compilation Domain"), - pParam->pSetup, - NULL, - &pParam->pThis->m_pAppDomain)); - - // That's it, we're all set up. - _ASSERTE(pParam->pThis->m_pAppDomain != NULL); - pParam->pThis->m_fStartedEE = true; - - ErrExit: - pParam->hr = hr; - } - PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - _ASSERTE(!"Unexpected exception setting up hosting environment for security attributes"); - param.hr = E_FAIL; - } - PAL_ENDTRY - - // Cleanup temporary resources. - if (m_pAppDomain && FAILED(param.hr)) - m_pAppDomain->Release(); - if (param.pDomainSetup) - param.pDomainSetup->Release(); - if (param.pSetup) - param.pSetup->Release(); - if (param.fDoneStart && FAILED(param.hr)) - m_pCorHost->Stop(); - if (m_pCorHost && FAILED(param.hr)) - m_pCorHost->Release(); - return param.hr; -#endif // FEATURE_CORECLR } #endif //FEATURE_METADATA_EMIT_ALL @@ -471,72 +372,16 @@ RegMeta::ResolveTypeRef( goto ErrExit; } -#ifndef FEATURE_CORECLR - wcscpy_s(rcModule, _MAX_PATH, wzNameSpace); - - //****************** - // Try to find the module on CORPATH - //****************** - - if ((wcsncmp(rcModule, W("System."), 16) != 0) && - (wcsncmp(rcModule, W("System/"), 16) != 0)) - { - // only go through regular CORPATH lookup by fully qualified class name when - // it is not System.* - hr = CORPATHService::GetClassFromCORPath( - rcModule, - tr, - pMiniMd, - riid, - ppIScope, - ptd); - } - else - { - // force it to look for System.* in mscorlib.dll - hr = S_FALSE; - } - - if (hr == S_FALSE) - { - LPWSTR szTmp; - WszSearchPath( - NULL, - W("mscorlib.dll"), - NULL, - sizeof(rcModule) / sizeof(rcModule[0]), - rcModule, - &szTmp); - - //******************* - // Last desperate try!! - //******************* - - // Use the file name "mscorlib: - IfFailGo(CORPATHService::FindTypeDef( - rcModule, - tr, - pMiniMd, - riid, - ppIScope, - ptd)); - if (hr == S_FALSE) - { - IfFailGo(META_E_CANNOTRESOLVETYPEREF); - } - } -#else //FEATURE_CORECLR IfFailGo(META_E_CANNOTRESOLVETYPEREF); -#endif //FEATURE_CORECLR ErrExit: STOP_MD_PERF(ResolveTypeRef); END_ENTRYPOINT_NOTHROW; return hr; -#else //!FEATURE_METADATA_IN_VM +#else // FEATURE_METADATA_IN_VM return E_NOTIMPL; -#endif //!FEATURE_METADATA_IN_VM +#endif // FEATURE_METADATA_IN_VM } // RegMeta::ResolveTypeRef @@ -551,11 +396,11 @@ ULONG RegMeta::Release() CONTRACT_VIOLATION (SOToleranceViolation); BEGIN_CLEANUP_ENTRYPOINT; -#if defined(FEATURE_METADATA_IN_VM) || defined(FEATURE_METADATA_STANDALONE_WINRT) +#if defined(FEATURE_METADATA_IN_VM) _ASSERTE(!m_bCached || LOADEDMODULES::IsEntryInList(this)); #else _ASSERTE(!m_bCached); -#endif //!FEATURE_METADATA_IN_VM && !FEATURE_METADATA_STANDALONE_WINRT +#endif // FEATURE_METADATA_IN_VM BOOL bCached = m_bCached; ULONG cRef = InterlockedDecrement(&m_cRef); // NOTE: 'this' may be unsafe after this point, if the module is cached, and @@ -570,7 +415,7 @@ ULONG RegMeta::Release() // discovered the module, so this thread can now safely delete it. delete this; } -#if defined(FEATURE_METADATA_IN_VM) || defined(FEATURE_METADATA_STANDALONE_WINRT) +#if defined(FEATURE_METADATA_IN_VM) else if (LOADEDMODULES::RemoveModuleFromLoadedList(this)) { // If the module was cached, RemoveModuleFromLoadedList() will try to // safely un-publish the module, and if it succeeds, no other thread @@ -578,7 +423,7 @@ ULONG RegMeta::Release() m_bCached = false; delete this; } -#endif //!FEATURE_METADATA_IN_VM && !FEATURE_METADATA_STANDALONE_WINRT +#endif // FEATURE_METADATA_IN_VM } END_CLEANUP_ENTRYPOINT diff --git a/src/md/compiler/wks/CMakeLists.txt b/src/md/compiler/wks/CMakeLists.txt index 6bf6c80868..eb39ca7972 100644 --- a/src/md/compiler/wks/CMakeLists.txt +++ b/src/md/compiler/wks/CMakeLists.txt @@ -1,4 +1,6 @@ include(../../md_wks.cmake) +add_definitions(-DFEATURE_METADATA_EMIT_ALL) + add_precompiled_header(stdafx.h ../stdafx.cpp MDCOMPILER_SOURCES) -add_library_clr(mdcompiler_wks ${MDCOMPILER_SOURCES})
\ No newline at end of file +add_library_clr(mdcompiler_wks ${MDCOMPILER_SOURCES}) diff --git a/src/md/enc/imptlb.cpp b/src/md/enc/imptlb.cpp deleted file mode 100644 index faeb0d9882..0000000000 --- a/src/md/enc/imptlb.cpp +++ /dev/null @@ -1,8057 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. -// =========================================================================== -// File: ImpTlb.CPP -// - -// - -// --------------------------------------------------------------- -// Who When What -// --------------------------------------------------------------- -// WGE 970906 Created -// -// =========================================================================== -#include "stdafx.h" - -#include "imptlb.h" -#include <posterror.h> -#include <strongname.h> -#include <nsutilpriv.h> - -#include "..\compiler\regmeta.h" -#include "..\compiler\importhelper.h" -#include "tlbutils.h" // For GenerateMangledTypeName(). -#include <tlbimpexp.h> -#include "sstring.h" -#include "strsafe.h" - -#include <metahost.h> - -// Pointer to the activated CLR interface provided by the shim. -extern ICLRRuntimeInfo *g_pCLRRuntime; - -#ifdef wcsncmp - #undef wcsncmp -#endif -#ifdef wcsncpy - #undef wcsncpy -#endif - -// deprecated: use the secureCrt replacements -// _CRTIMP int __cdecl wcsncmp(const wchar_t *, const wchar_t *, size_t); -// _CRTIMP wchar_t * __cdecl wcsncpy(wchar_t *, const wchar_t *, size_t); - -#define S_CONVERSION_LOSS _HRESULT_TYPEDEF_(3) // Non-error code meaning a conversion lost information. - -#define ADD_ITF_MEMBERS_TO_CLASS // Define to add interface members to the CoClass. -#define ITF_MEMBER_RESOLUTION_NAMEONLY // Define to ignore signatures when looking for collisions (ie, when defined - // void Foo(int) and void Foo(String) collide). - -// defines controlling ctor of non-creatable objects. -#define NONCREATABLE_CTOR_VISIBILITY mdAssem // Define to a visibility flag. - -#define MAX_CLASSNAME_SIZE 1024 - -#ifndef lengthof -#define lengthof(rg) (sizeof(rg)/sizeof(rg[0])) -#endif - -#ifndef IfNullGo -#define IfNullGo(x) do {if (!(x)) IfFailGo(E_OUTOFMEMORY);} while (0) -#endif - -#define BUILD_CUSTOM_ATTRIBUTE(type,bytes) {*reinterpret_cast<UNALIGNED type*>(__pca) = bytes; __pca += sizeof(type); _ASSERTE(__pca-__ca <= sizeof(__ca));} -#define INIT_CUSTOM_ATTRIBUTE(n) {_ASSERTE((n) <= (sizeof(__ca)-sizeof(SHORT)));__pca = __ca; BUILD_CUSTOM_ATTRIBUTE(USHORT,1);} -#define SIZEOF_CUSTOM_ATTRIBUTE() ((ULONG) (__pca - __ca)) -#define PTROF_CUSTOM_ATTRIBUTE() (&__ca[0]) -#define DECLARE_CUSTOM_ATTRIBUTE(n) BYTE __ca[(n)+sizeof(SHORT)*2], *__pca;__pca=__ca; INIT_CUSTOM_ATTRIBUTE(n); -#define APPEND_STRING_TO_CUSTOM_ATTRIBUTE(str) {int l = (int)strlen(str); __pca=(BYTE*)CPackedLen::PutLength(__pca,l);memcpy(__pca,str,l);__pca+=l;} -#define FINISH_CUSTOM_ATTRIBUTE() {BUILD_CUSTOM_ATTRIBUTE(short,0);} - -#define DECLARE_DYNLEN_CUSTOM_ATTRIBUTE(n) CQuickArray<BYTE> __tmpCAArray; IfFailGo(__tmpCAArray.ReSizeNoThrow(n + sizeof(SHORT)*2)); BYTE *__ca, *__pca; __ca = __tmpCAArray.Ptr(); __pca=__ca; BUILD_CUSTOM_ATTRIBUTE(USHORT,1); -#define BUILD_DYNLEN_CUSTOM_ATTRIBUTE(type,bytes) {*reinterpret_cast<UNALIGNED type*>(__pca) = bytes; __pca += sizeof(type); _ASSERTE(__pca-__ca <= (int)__tmpCAArray.Size());} -#define FINISH_DYNLEN_CUSTOM_ATTRIBUTE() {BUILD_DYNLEN_CUSTOM_ATTRIBUTE(short,0);} - -#define APPEND_WIDE_STRING_TO_CUSTOM_ATTRIBUTE(str) \ -{ \ - CQuickArray<char> __tmpStr; \ - int __cStr = WszWideCharToMultiByte(CP_ACP, 0, str, -1, 0, 0, NULL, NULL); \ - IfFailGo(__tmpStr.ReSizeNoThrow(__cStr)); \ - __cStr = WszWideCharToMultiByte(CP_ACP, 0, str, -1, __tmpStr.Ptr(), __cStr, NULL, NULL); \ - __pca=(BYTE*)CPackedLen::PutLength(__pca,__cStr); \ - memcpy(__pca,__tmpStr.Ptr(),__cStr); \ - __pca+=__cStr; \ -} - -// The maximum number of bytes the encoding of a DWORD can take. -#define DWORD_MAX_CB 4 - -// The maximum number of bytes the encoding of a DWORD can take. -#define STRING_OVERHEAD_MAX_CB 4 - -// Use the unused variant types m_knowntypes for common types. -#define VT_SLOT_FOR_GUID VT_EMPTY -#define VT_SLOT_FOR_IENUMERABLE VT_NULL -#define VT_SLOT_FOR_MULTICASTDEL VT_I2 -#define VT_SLOT_FOR_TYPE VT_I4 -#define VT_SLOT_FOR_STRINGBUF VT_I8 - -static LPCWSTR szObject = W("System.Object"); -static LPCWSTR szValueType = W("System.ValueType"); -static LPCWSTR szEnum = W("System.Enum"); - -static LPCWSTR TLB_CLASSLIB_ARRAY = {W("System.Array")}; -static LPCWSTR TLB_CLASSLIB_DATE = {W("System.DateTime")}; -static LPCWSTR TLB_CLASSLIB_DECIMAL = {W("System.Decimal")}; -static LPCWSTR TLB_CLASSLIB_VARIANT = {W("System.Variant")}; -static LPCWSTR TLB_CLASSLIB_GUID = {W("System.Guid")}; -static LPCWSTR TLB_CLASSLIB_IENUMERABLE = {W("System.Collections.IEnumerable")}; -static LPCWSTR TLB_CLASSLIB_MULTICASTDELEGATE = {W("System.MulticastDelegate")}; -static LPCWSTR TLB_CLASSLIB_TYPE = {W("System.Type")}; -static LPCWSTR TLB_CLASSLIB_STRINGBUFFER = {W("System.Text.StringBuilder")}; - -static LPCWSTR COM_STDOLE2 = {W("StdOle")}; -static LPCWSTR COM_GUID = {W("GUID")}; - -static const LPCWSTR PROP_DECORATION_GET = {W("get_")}; -static const LPCWSTR PROP_DECORATION_SET = {W("set_")}; -static const LPCWSTR PROP_DECORATION_LET = {W("let_")}; -static const int PROP_DECORATION_LEN = 4; - -static const LPCWSTR DLL_EXTENSION = {W(".dll")}; -static const int DLL_EXTENSION_LEN = 4; -static const LPCWSTR EXE_EXTENSION = {W(".exe")}; -static const int EXE_EXTENSION_LEN = 4; - -static LPCWSTR const OBJECT_INITIALIZER_NAME = {W(".ctor")}; -static const int OBJECT_INITIALIZER_FLAGS = mdPublic | mdSpecialName; -static const int OBJECT_INITIALIZER_IMPL_FLAGS = miNative | miRuntime | miInternalCall; -static const int NONCREATABLE_OBJECT_INITIALIZER_FLAGS = NONCREATABLE_CTOR_VISIBILITY | mdSpecialName; - -static const COR_SIGNATURE OBJECT_INITIALIZER_SIG[3] = { - (IMAGE_CEE_CS_CALLCONV_DEFAULT | IMAGE_CEE_CS_CALLCONV_HASTHIS), 0, ELEMENT_TYPE_VOID }; - -static const int DEFAULT_INTERFACE_FUNC_FLAGS = mdPublic | mdVirtual | mdAbstract | mdHideBySig | mdNewSlot; -static const int DEFAULT_PROPERTY_FUNC_FLAGS = mdPublic | mdVirtual | mdAbstract | mdHideBySig | mdSpecialName | mdNewSlot; -static const int DEFAULT_CONST_FIELD_FLAGS = fdPublic | fdStatic | fdLiteral; -static const int DEFAULT_RECORD_FIELD_FLAGS = fdPublic; -static const int DELEGATE_INVOKE_FUNC_FLAGS = mdPublic | mdVirtual; - -static const int DEFAULT_ITF_FUNC_IMPL_FLAGS = miNative | miRuntime | miInternalCall; - -static const WCHAR VTBL_GAP_FUNCTION[] = {W("_VtblGap")}; -static const int VTBL_GAP_FUNCTION_FLAGS = mdPublic | mdSpecialName; -static const int VTBL_GAP_FUNC_IMPL_FLAGS = miRuntime; -static const COR_SIGNATURE VTBL_GAP_SIGNATURE[] = {IMAGE_CEE_CS_CALLCONV_DEFAULT, 0, ELEMENT_TYPE_VOID}; -static const LPCWSTR VTBL_GAP_FORMAT_1 = {W("%ls%d")}; -static const LPCWSTR VTBL_GAP_FORMAT_N = {W("%ls%d_%d")}; - -static const LPCWSTR ENUM_TYPE_NAME = {COR_ENUM_FIELD_NAME_W}; -static const DWORD ENUM_TYPE_FLAGS = fdPublic; -static const COR_SIGNATURE ENUM_TYPE_SIGNATURE[] = {IMAGE_CEE_CS_CALLCONV_FIELD, ELEMENT_TYPE_I4}; -static const DWORD ENUM_TYPE_SIGNATURE_SIZE = lengthof(ENUM_TYPE_SIGNATURE); - -static const LPCWSTR DYNAMIC_NAMESPACE_NAME = {W("DynamicModule")}; - -static const LPCWSTR UNSAFE_ITF_PREFIX = {W("Unsafe.")}; - -static const LPCWSTR GET_ENUMERATOR_MEMBER_NAME = {W("GetEnumerator")}; - -static const WCHAR CLASS_SUFFIX[] = {W("Class")}; -static const DWORD CLASS_SUFFIX_LENGTH = lengthof(CLASS_SUFFIX); -static const WCHAR EVENT_ITF_SUFFIX[] = {W("_Event")}; -static const DWORD EVENT_ITF_SUFFIX_LENGTH = lengthof(EVENT_ITF_SUFFIX); -static const WCHAR EVENT_PROVIDER_SUFFIX[] = {W("_EventProvider")}; -static const DWORD EVENT_PROVIDER_SUFFIX_LENGTH = lengthof(EVENT_ITF_SUFFIX); -static const WCHAR EVENT_HANDLER_SUFFIX[] = {W("EventHandler")}; -static const DWORD EVENT_HANDLER_SUFFIX_LENGTH = lengthof(EVENT_HANDLER_SUFFIX); - -static const WCHAR EVENT_ADD_METH_PREFIX[] = {W("add_")}; -static const DWORD EVENT_ADD_METH_PREFIX_LENGTH = lengthof(EVENT_ADD_METH_PREFIX); -static const WCHAR EVENT_REM_METH_PREFIX[] = {W("remove_")}; -static const DWORD EVENT_REM_METH_PREFIX_LENGTH = lengthof(EVENT_REM_METH_PREFIX); - -static const WCHAR DELEGATE_INVOKE_METH_NAME[] = {W("Invoke")}; -static const DWORD DELEGATE_INVOKE_METH_NAME_LENGTH = lengthof(EVENT_ADD_METH_PREFIX); - -// {C013B386-CC3E-4b6d-9B67-A3AE97274BBE} -static const GUID FREE_STATUS_GUID = -{ 0xc013b386, 0xcc3e, 0x4b6d, { 0x9b, 0x67, 0xa3, 0xae, 0x97, 0x27, 0x4b, 0xbe } }; - -// {C013B387-CC3E-4b6d-9B67-A3AE97274BBE} -static const GUID DELETED_STATUS_GUID = -{ 0xc013b387, 0xcc3e, 0x4b6d, { 0x9b, 0x67, 0xa3, 0xae, 0x97, 0x27, 0x4b, 0xbe } }; - -// {C013B388-CC3E-4b6d-9B67-A3AE97274BBE} -static const GUID USED_STATUS_GUID = -{ 0xc013b388, 0xcc3e, 0x4b6d, { 0x9b, 0x67, 0xa3, 0xae, 0x97, 0x27, 0x4b, 0xbe } }; - -static const GUID IID_IEnumerable = -{ 0x496b0abe, 0xcdee, 0x11d3, { 0x88, 0xe8, 0x00, 0x90, 0x27, 0x54, 0xc4, 0x3a } }; - - - #define STRUCTLAYOUT tdSequentialLayout -// ULONG_MAX is a flag meaning "don't convert". -static const ULONG rdwTypeFlags[] = { - tdPublic | tdSealed, // TKIND_ENUM = 0, - tdPublic | tdSealed | tdBeforeFieldInit | STRUCTLAYOUT, // TKIND_RECORD = TKIND_ENUM + 1, - tdPublic | tdAbstract, // TKIND_MODULE = TKIND_RECORD + 1, - tdPublic | tdInterface | tdAbstract | tdImport, // TKIND_INTERFACE = TKIND_MODULE + 1, - tdPublic | tdInterface | tdAbstract | tdImport, // TKIND_DISPATCH = TKIND_INTERFACE + 1, - tdPublic | tdImport, // TKIND_COCLASS = TKIND_DISPATCH + 1, - tdPublic | tdImport, // TKIND_ALIAS = TKIND_COCLASS + 1, - tdPublic | tdSealed | tdExplicitLayout, // TKIND_UNION = TKIND_ALIAS + 1, - ULONG_MAX, // TKIND_MAX = TKIND_UNION + 1 -}; -static const LPCWSTR g_szTypekind[] = { - W("Enum "), - W("Record "), - W("Module "), - W("Interface "), - W("Dispinterface"), - W("Coclass "), - W("Alias "), - W("Union "), -}; - -#define NATIVE_TYPE_NONE ((CorNativeType)(NATIVE_TYPE_MAX+1)) - -#define NON_CONVERTED_PARAMS_FLAGS (PARAMFLAG_FRETVAL|PARAMFLAG_FLCID) - - -//***************************************************************************** -// External declarations. -//***************************************************************************** -extern mdAssemblyRef DefineAssemblyRefForImportedTypeLib( - void *pAssembly, // Assembly importing the typelib. - void *pvModule, // Module importing the typelib. - IUnknown *pIMeta, // IMetaData* from import module. - IUnknown *pIUnk, // IUnknown to referenced Assembly. - BSTR *pwzNamespace, // The namespace of the resolved assembly. - BSTR *pwzAsmName, // The name of the resolved assembly. - Assembly **AssemblyRef); // The resolved assembly. - -extern mdAssemblyRef DefineAssemblyRefForExportedAssembly( - LPCWSTR szFullName, // Assembly full name. - IUnknown *pIMeta); // Metadata emit interface. - -static HRESULT _UnpackVariantToConstantBlob(VARIANT *pvar, BYTE *pcvType, void **pvValue, __int64 *pd); -static INT64 _DoubleDateToTicks(const double d); -static HRESULT TryGetFuncDesc(ITypeInfo *pITI, int i, FUNCDESC **ppFunc); - -//***************************************************************************** -// Class factory. -//***************************************************************************** -CImportTlb* CImportTlb::CreateImporter( - LPCWSTR szLibrary, - ITypeLib *pitlb, - BOOL bGenerateTCEAdapters, - BOOL bUnsafeInterfaces, - BOOL bSafeArrayAsSystemArray, - BOOL bTransformDispRetVals, - BOOL bPreventClassMembers, - BOOL bSerializableValueClasses) -{ - return new (nothrow) CImportTlb(szLibrary, pitlb, bGenerateTCEAdapters, bUnsafeInterfaces, bSafeArrayAsSystemArray, bTransformDispRetVals, bPreventClassMembers, bSerializableValueClasses); -} // CImportTlb* CImportTlb::CreateImporter() - -//***************************************************************************** -// Default constructor. -//***************************************************************************** -CImportTlb::CImportTlb() - : m_szLibrary(NULL), - m_pITLB(NULL), - m_bGenerateTCEAdapters(false), - m_bSafeArrayAsSystemArray(false), - m_bTransformDispRetVals(false), - m_bPreventClassMembers(false), - m_bSerializableValueClasses(false), - m_pEmit(NULL), - m_pImport(NULL), - m_pITI(NULL), - m_pOrigITI(NULL), - m_psAttr(NULL), - m_arSystem(mdAssemblyRefNil), - m_Notify(NULL), - m_trValueType(0), - m_trEnum(0), - m_bUnsafeInterfaces(FALSE), - m_tkSuppressCheckAttr(mdTokenNil), - m_tdHasDefault(0), - m_szName(NULL), - m_szMember(NULL), - m_wzNamespace(NULL), - m_tkInterface(0), - m_szInterface(NULL), - m_pMemberNames(NULL), - m_cMemberProps(0), - m_ImplIface(eImplIfaceNone) -{ - // Clear the known types array. The values will be lazily initialized. - memset(m_tkKnownTypes, 0, sizeof(m_tkKnownTypes)); - memset(m_tkAttr, 0, sizeof(m_tkAttr)); -} // CImportTlb::CImportTlb() - -//***************************************************************************** -// Complex constructor. -//***************************************************************************** -CImportTlb::CImportTlb( - LPCWSTR szLibrary, // Name of library being imported. - ITypeLib *pitlb, // The type library to import from. - BOOL bGenerateTCEAdapters, // A flag indicating if the TCE adapters are being generated. - BOOL bUnsafeInterfaces, // A flag indicating that runtime security checks should be disabled - BOOL bSafeArrayAsSystemArray,// A flag indicating whether to import SAFEARRAY's as System.Array's. - BOOL bTransformDispRetVals, // A flag indicating if we should do [out,retval] transformation on disp only itfs. - BOOL bPreventClassMembers, // A flag indicating if we should add members to CoClasses. - BOOL bSerializableValueClasses) // A flag indicating if we should mark value classes serializable. - : m_szLibrary(szLibrary), - m_pITLB(pitlb), - m_bGenerateTCEAdapters(bGenerateTCEAdapters), - m_bUnsafeInterfaces(bUnsafeInterfaces), - m_bSafeArrayAsSystemArray(bSafeArrayAsSystemArray), - m_bTransformDispRetVals(bTransformDispRetVals), - m_bPreventClassMembers(bPreventClassMembers), - m_bSerializableValueClasses(bSerializableValueClasses), - m_pEmit(0), - m_pImport(0), - m_pITI(0), - m_pOrigITI(0), - m_psAttr(0), - m_arSystem(mdAssemblyRefNil), - m_Notify(0), - m_trValueType(0), - m_trEnum(0), - m_tkSuppressCheckAttr(mdTokenNil), - m_tdHasDefault(0), - m_szName(0), - m_szMember(0), - m_wzNamespace(0), - m_tkInterface(0), - m_szInterface(0), - m_pMemberNames(0), - m_cMemberProps(0), - m_ImplIface(eImplIfaceNone) -{ - if (pitlb) - pitlb->AddRef(); - - // Clear the known types array. The values will be lazily initialized. - memset(m_tkKnownTypes, 0, sizeof(m_tkKnownTypes)); - memset(m_tkAttr, 0, sizeof(m_tkAttr)); - -#if defined(TLB_STATS) - m_bStats = QueryPerformanceFrequency(&m_freqVal); -#endif -} // CImportTlb::CImportTlb() - -//***************************************************************************** -// Destructor. -//***************************************************************************** -CImportTlb::~CImportTlb() -{ - if (m_pEmit) - m_pEmit->Release(); - if (m_pImport) - m_pImport->Release(); - if (m_pITLB) - m_pITLB->Release(); - if (m_Notify) - m_Notify->Release(); - - if (m_wzNamespace) - ::SysFreeString(m_wzNamespace); -} // CImportTlb::~CImportTlb() - - -//***************************************************************************** -// Allow the user to specify a namespace to be used in the conversion. -//***************************************************************************** -HRESULT CImportTlb::SetNamespace( - WCHAR const *pNamespace) -{ - HRESULT hr=S_OK; // A result. - - IfNullGo(m_wzNamespace=::SysAllocString(pNamespace)); - -ErrExit: - - return hr; -} // HRESULT CImportTlb::SetNamespace() - -//***************************************************************************** -// Allow the user to specify a notification object to be used in the conversion. -//***************************************************************************** -HRESULT CImportTlb::SetNotification( - ITypeLibImporterNotifySink *pNotify) -{ - _ASSERTE(m_Notify == 0); - m_Notify = pNotify; - pNotify->AddRef(); - - return S_OK; -} // HRESULT CImportTlb::SetNotification() - -//***************************************************************************** -// Allow the user to specify the MetaData scope to be used in the conversion. -//***************************************************************************** -HRESULT CImportTlb::SetMetaData( - IUnknown *pIUnk) -{ - HRESULT hr; - _ASSERTE(m_pEmit == 0); - IfFailGo(pIUnk->QueryInterface(IID_IMetaDataEmit2, (void**)&m_pEmit)); -ErrExit: - return hr; -} // HRESULT CImportTlb::SetMetaData() - -//***************************************************************************** -// Import a TypeLibrary into a CompLib. -//***************************************************************************** -HRESULT CImportTlb::Import() -{ -#ifndef DACCESS_COMPILE - HRESULT hr; // A result. - mdModule md; // Module token. - VARIANT vt = {0}; // For setting options. - ITypeLib2 *pITLB2 = 0; // To get custom attributes. - IMetaDataDispenserEx *pDisp = 0; // To create export scope. - TLIBATTR *psAttr=0; // The library's attributes. - BSTR szLibraryName = 0; // The library's name. - LPCWSTR wzFile; // The filename of the typelib (no path). - LPCWSTR wzSource; // Source of the typelib, for CA. - - _ASSERTE(m_Notify); - - // Quick sanity check. - if (!m_pITLB) - return (E_INVALIDARG); - - // Check to see if the type library implements ITypeLib2. - if (m_pITLB->QueryInterface(IID_ITypeLib2, (void **)&pITLB2) != S_OK) - pITLB2 = 0; - - // If custom attribute for namespace exists, use it. - if (pITLB2) - { - VARIANT vt; - VariantInit(&vt); - if (pITLB2->GetCustData(GUID_ManagedName, &vt) == S_OK) - { - if (V_VT(&vt) == VT_BSTR) - { - // If there already was a namespace set, release it. - if (m_wzNamespace) - SysFreeString(m_wzNamespace); - - // If the namespace ends with .dll then remove the extension. - LPWSTR pDest = wcsstr(vt.bstrVal, DLL_EXTENSION); - if (pDest && (pDest[DLL_EXTENSION_LEN] == 0 || pDest[DLL_EXTENSION_LEN] == ' ')) - *pDest = 0; - - if (!pDest) - { - // If the namespace ends with .exe then remove the extension. - pDest = wcsstr(vt.bstrVal, EXE_EXTENSION); - if (pDest && (pDest[EXE_EXTENSION_LEN] == 0 || pDest[EXE_EXTENSION_LEN] == ' ')) - *pDest = 0; - } - - if (pDest) - { - // We removed the extension so re-allocate a string of the new length. - m_wzNamespace = SysAllocString(vt.bstrVal); - SysFreeString(vt.bstrVal); - IfNullGo(m_wzNamespace); - } - else - { - // There was no extension to remove so we can use the string returned - // by GetCustData(). - m_wzNamespace = vt.bstrVal; - } - } - else - { - VariantClear(&vt); - } - } - } - - // Use the namespace name if we don't know the filename. - if (!m_szLibrary) - m_szLibrary = m_wzNamespace; - - // If the typelib was exported from COM+ to begin with, don't import it. - if (pITLB2) - { - ::VariantInit(&vt); - hr = pITLB2->GetCustData(GUID_ExportedFromComPlus, &vt); - if (vt.vt != VT_EMPTY) - { - if (0) - { - // com emulates option is ON - } - else - { - IfFailGo(PostError(TLBX_E_CIRCULAR_IMPORT, m_szLibrary)); - } - } - } - - _ASSERTE(m_pEmit); - IfFailGo(m_pEmit->QueryInterface(IID_IMetaDataImport2, (void **)&m_pImport)); - - // Initialize the reserved names map. - IfFailGo(m_ReservedNames.Init()); - - // Initialize the default interface to class interface map for the TLB being imported. - IfFailGo(m_DefItfToClassItfMap.Init(m_pITLB, m_wzNamespace)); - - // Create the Object classref record and AssemblyRef for mscorlib.dll. - IfFailGo(_DefineSysRefs()); - - // Create the library record. - IfFailGo(_NewLibraryObject()); - - // Note that this was imported. - IfFailGo(m_pITLB->GetLibAttr(&psAttr)); - if (SUCCEEDED(::QueryPathOfRegTypeLib(psAttr->guid, psAttr->wMajorVerNum, psAttr->wMinorVerNum, psAttr->lcid, &szLibraryName))) - wzSource = szLibraryName; - else - wzSource = m_szLibrary; - - // We can't base the decision on SYSKIND. For example, we can have a SYS_WIN64 tlb loaded as 32-bit with 4-byte aligned pointers. - m_cbVtableSlot = 0; - - IfFailGo(m_pImport->GetModuleFromScope(&md)); - // Skip the path or drive info - wzFile = wcsrchr(wzSource, W('\\')); - if (wzFile == 0) - { // That's odd, should have been a fully qualified path. Just use an empty string. - wzFile = W(""); - } - else - { // skip leading backslash - wzFile++; - } - - // Convert the typelib. - IfFailGo(ConvertTypeLib()); - -ErrExit: - if (psAttr) - m_pITLB->ReleaseTLibAttr(psAttr); - if (szLibraryName) - ::SysFreeString(szLibraryName); - if (pITLB2) - pITLB2->Release(); - if (pDisp) - pDisp->Release(); - - return (hr); -#else - DacNotImpl(); - return E_NOTIMPL; -#endif // #ifndef DACCESS_COMPILE -} // HRESULT CImportTlb::Import() - -//***************************************************************************** -// Create the Complib to represent the TypeLib. -//***************************************************************************** -HRESULT CImportTlb::_NewLibraryObject() -{ - HRESULT hr; // A result. - TLIBATTR * psAttr=0; // The library's attributes. - BSTR szLibraryName=0; // The library's name. - CQuickArray<WCHAR> rScopeName; // The name of the scope. - - // Information about the library. - IfFailGo(m_pITLB->GetLibAttr(&psAttr)); - IfFailGo(m_pITLB->GetDocumentation(MEMBERID_NIL, &szLibraryName, 0, 0, 0)); - - // Create the scope name by using the typelib name and adding .dll. - IfFailGo(rScopeName.ReSizeNoThrow(SysStringLen(szLibraryName) + 5 * sizeof(WCHAR))); - StringCchPrintf(rScopeName.Ptr(), rScopeName.Size(), W("%s.dll"), szLibraryName); - - IfFailGo(m_pEmit->SetModuleProps(rScopeName.Ptr())); - -ErrExit: - if (psAttr) - m_pITLB->ReleaseTLibAttr(psAttr); - - if (szLibraryName) - ::SysFreeString(szLibraryName); - - return (hr); -} // HRESULT CImportTlb::_NewLibraryObject() - -//***************************************************************************** -// Define an assembly ref for mscorlib, typeref for Object. -//***************************************************************************** -HRESULT CImportTlb::_DefineSysRefs() -{ - HRESULT hr; // A result. - WCHAR szPath[_MAX_PATH]; - WCHAR szDrive[_MAX_DRIVE]; - WCHAR szDir[_MAX_PATH]; - DWORD dwLen; // Length of system directory name. - IMetaDataDispenserEx *pDisp = 0; // To import mscorlib. - IMetaDataAssemblyImport *pAImp = 0; // To read mscorlib assembly. - IMetaDataAssemblyEmit *pAEmit = 0; // To create mscorlib assembly ref. - ASSEMBLYMETADATA amd = {0}; // Assembly metadata. - mdToken tk; // A token. - const void *pvPublicKey; // Public key. - ULONG cbPublicKey; // Length of public key. - BYTE *pbToken=0; // Compressed token for public key. - ULONG cbToken; // Length of token. - ULONG ulHashAlg; // Hash algorithm. - DWORD dwFlags; // Assembly flags. - - // Get the dispenser. - IfFailGo(g_pCLRRuntime->GetInterface( - CLSID_CorMetaDataDispenser, - IID_IMetaDataDispenserEx, - (void **)&pDisp)); - - // Get the name of mscorlib. - //@todo: define, function, etc., instead of hard coded "mscorlib" - dwLen = lengthof(szPath) - 13; // allow space for "mscorlib" ".dll" "\0" - IfFailGo(pDisp->GetCORSystemDirectory(szPath, dwLen, &dwLen)); - SplitPath(szPath, szDrive, _MAX_DRIVE, szDir, _MAX_PATH, 0, 0, 0, 0); - MakePath(szPath, szDrive, szDir, W("mscorlib"), W(".dll")); - - // Open the scope, get the details. - IfFailGo(pDisp->OpenScope(szPath, 0, IID_IMetaDataAssemblyImport, (IUnknown**)&pAImp)); - IfFailGo(pAImp->GetAssemblyFromScope(&tk)); - IfFailGo(pAImp->GetAssemblyProps(tk, &pvPublicKey,&cbPublicKey, &ulHashAlg, - szPath,lengthof(szPath),&dwLen, &amd, &dwFlags)); - - if (!StrongNameTokenFromPublicKey((BYTE*)(pvPublicKey),cbPublicKey, &pbToken,&cbToken)) - { - hr = StrongNameErrorInfo(); - goto ErrExit; - } - dwFlags &= ~afPublicKey; - - // Define the assembly ref. - IfFailGo(m_pEmit->QueryInterface(IID_IMetaDataAssemblyEmit, (void**)&pAEmit)); - IfFailGo(pAEmit->DefineAssemblyRef(pbToken,cbToken, szPath, &amd,0,0,dwFlags, &m_arSystem)); - - IfFailGo(m_TRMap.DefineTypeRef(m_pEmit, m_arSystem, szObject, &m_trObject)); - - m_tkKnownTypes[VT_DISPATCH] = m_trObject; - m_tkKnownTypes[VT_UNKNOWN] = m_trObject; - m_tkKnownTypes[VT_VARIANT] = m_trObject; - -ErrExit: - if (pbToken) - StrongNameFreeBuffer(pbToken); - if (pDisp) - pDisp->Release(); - if (pAEmit) - pAEmit->Release(); - if (pAImp) - pAImp->Release(); - - return hr; -} // HRESULT CImportTlb::_DefineSysRefs() - -//***************************************************************************** -// Lazily get the token for a CustomAttribute. -//***************************************************************************** -HRESULT CImportTlb::GetAttrType( - int attr, // The attribute for which the type is desired. - mdToken *pTk) // Put the type here. -{ - HRESULT hr = S_OK; // A result. - mdTypeRef tr; // An intermediate typeref. - DWORD dwSigSize; // The size of the sig for special sigs. - DWORD dwMaxSigSize; // The max size of the special sig. - COR_SIGNATURE *pSig; // Pointer to the start of the sig, - COR_SIGNATURE *pCurr; // Current sig pointer. - mdTypeRef trType; // The typeref for System.Type. - - _ASSERTE(attr >= 0); - _ASSERTE(attr < ATTR_COUNT); - - //@todo: globally define these names. -#define INTEROP_ATTRIBUTE(x) static COR_SIGNATURE x##_SIG[] = INTEROP_##x##_SIG; -#define INTEROP_ATTRIBUTE_SPECIAL(x) - INTEROP_ATTRIBUTES(); -#undef INTEROP_ATTRIBUTE -#undef INTEROP_ATTRIBUTE_SPECIAL -#define INTEROP_ATTRIBUTE(x) \ - case ATTR_##x: \ - IfFailGo(m_pEmit->DefineTypeRefByName(m_arSystem, INTEROP_##x##_TYPE_W, &tr)); \ - IfFailGo(m_pEmit->DefineMemberRef(tr, W(".ctor"), x##_SIG, lengthof(x##_SIG), &m_tkAttr[attr])); \ - break; -#define INTEROP_ATTRIBUTE_SPECIAL(x) - - if (IsNilToken(m_tkAttr[attr])) - { - switch (attr) - { - INTEROP_ATTRIBUTES(); - - case ATTR_COMEVENTINTERFACE: - { - // Retrieve token for System.Type. - IfFailGo(GetKnownTypeToken(VT_SLOT_FOR_TYPE, &trType)); - - // Build the sig. - dwMaxSigSize = 5 + sizeof(mdTypeRef) * 2; - pSig = (COR_SIGNATURE*)_alloca(dwMaxSigSize); - pCurr = pSig; - *pCurr++ = IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS; - *pCurr++ = 2; - *pCurr++ = ELEMENT_TYPE_VOID; - *pCurr++ = ELEMENT_TYPE_CLASS; - pCurr += CorSigCompressToken(trType, pCurr); - *pCurr++ = ELEMENT_TYPE_CLASS; - pCurr += CorSigCompressToken(trType, pCurr); - dwSigSize = (DWORD)(pCurr - pSig); - _ASSERTE(dwSigSize <= dwMaxSigSize); - - // Declare the typeref and the member ref for the CA. - IfFailGo(m_pEmit->DefineTypeRefByName(m_arSystem, INTEROP_COMEVENTINTERFACE_TYPE_W, &tr)); \ - IfFailGo(m_pEmit->DefineMemberRef(tr, W(".ctor"), pSig, dwSigSize, &m_tkAttr[attr])); \ - break; - } - - case ATTR_COCLASS: - { - // Retrieve token for System.Type. - IfFailGo(GetKnownTypeToken(VT_SLOT_FOR_TYPE, &trType)); - - // Build the sig. - dwMaxSigSize = 4 + sizeof(mdTypeRef); - pSig = (COR_SIGNATURE*)_alloca(dwMaxSigSize); - pCurr = pSig; - *pCurr++ = IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS; - *pCurr++ = 1; - *pCurr++ = ELEMENT_TYPE_VOID; - *pCurr++ = ELEMENT_TYPE_CLASS; - pCurr += CorSigCompressToken(trType, pCurr); - dwSigSize = (DWORD)(pCurr - pSig); - _ASSERTE(dwSigSize <= dwMaxSigSize); - - // Declare the typeref and the member ref for the CA. - IfFailGo(m_pEmit->DefineTypeRefByName(m_arSystem, INTEROP_COCLASS_TYPE_W, &tr)); \ - IfFailGo(m_pEmit->DefineMemberRef(tr, W(".ctor"), pSig, dwSigSize, &m_tkAttr[attr])); \ - break; - } - } - } -#undef INTEROP_ATTRIBUTE -#undef INTEROP_ATTRIBUTE_SPECIAL - - *pTk = m_tkAttr[attr]; -ErrExit: - return hr; -} // HRESULT CImportTlb::GetAttrType() - -//***************************************************************************** -// Create the TypeDefs. -//***************************************************************************** -HRESULT -CImportTlb::ConvertTypeLib() -{ - HRESULT hr; - int cTi; // Count of TypeInfos. - int i; // Loop control. - - // How many TypeInfos? - IfFailGo(cTi = m_pITLB->GetTypeInfoCount()); - - // Iterate over them. - for (i = 0; i < cTi; ++i) - { - // Get the TypeInfo. - hr = m_pITLB->GetTypeInfo(i, &m_pITI); - if (SUCCEEDED(hr)) - { - // Save up the original TypeInfo (may be later alias-resolved). - _ASSERTE(m_pOrigITI == NULL); - m_pOrigITI = m_pITI; - m_pOrigITI->AddRef(); - - // Retrieve the attributes of the type info. - IfFailGo(m_pITI->GetTypeAttr(&m_psAttr)); - - // Convert the TypeInfo. - hr = ConvertTypeInfo(); - if (FAILED(hr)) - { - if (hr == CEE_E_CVTRES_NOT_FOUND || hr == TLBX_I_RESOLVEREFFAILED) - { // Reflection emit is broken, no need to try to continue. - goto ErrExit; - } - - BSTR szTypeInfoName = NULL; - hr = m_pITI->GetDocumentation(MEMBERID_NIL, &szTypeInfoName, 0, 0, 0); - if (SUCCEEDED(hr)) - { - ReportEvent(NOTIF_CONVERTWARNING, TLBX_E_INVALID_TYPEINFO, szTypeInfoName); - } - else - { - ReportEvent(NOTIF_CONVERTWARNING, TLBX_E_INVALID_TYPEINFO_UNNAMED, i); - } - if (szTypeInfoName != NULL) - ::SysFreeString(szTypeInfoName); -#if defined(_DEBUG) - if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_MD_TlbImp_BreakOnErr)) - _ASSERTE(!"Invalid type"); -#endif - } - - // Release for next TypeInfo. - m_pOrigITI->Release(); - m_pOrigITI = NULL; - - m_pITI->ReleaseTypeAttr(m_psAttr); - m_psAttr = NULL; - m_pITI->Release(); - m_pITI = NULL; - } - } - -ErrExit: - if (m_pOrigITI != NULL) - { - m_pOrigITI->Release(); - m_pOrigITI = NULL; - } - - if (m_psAttr != NULL) - { - m_pITI->ReleaseTypeAttr(m_psAttr); - m_psAttr = NULL; - } - if (m_pITI != NULL) - { - m_pITI->Release(); - m_pITI = NULL; - } - return hr; -} // CImportTlb::ConvertTypeLib - -//***************************************************************************** -// Convert a single ITypeInfo into the scope. -//***************************************************************************** -HRESULT CImportTlb::ConvertTypeInfo() // S_OK or error. -{ - HRESULT hr; // A result. - BSTR bstrManagedName=0; // Managed name (or part thereof). - CQuickArray<WCHAR> qbClassName; // The name of the class. - ULONG ulFlags; // TypeDef flags. - WORD wTypeInfoFlags; // TypeInfo flags. Alias flags, if an alias. - mdToken tkAttr; // Attribute type for flags. - TYPEKIND tkindAlias; // TYPEKIND of an aliased TypeInfo. - GUID guid; // GUID of the typeinfo. - BOOL bConversionLoss=false; // If true, info was lost converting sigs. - mdToken tkParent; // Parent of the typedef. - mdToken td; // For looking up a TypeDef. - ITypeInfo2 *pITI2=0; // For getting custom value. - -#if defined(TLB_STATS) - WCHAR rcStats[16]; // Buffer for stats. - LARGE_INTEGER __startVal; - QueryPerformanceCounter(&__startVal); -#endif - - m_tdTypeDef = mdTypeDefNil; - - // Get some information about the TypeInfo. - IfFailGo(m_pITI->GetDocumentation(MEMBERID_NIL, &m_szName, 0, 0, 0)); - -#if defined(_DEBUG) - LPWSTR strShouldBreakOnTypeName = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_MD_TlbImp_BreakOnTypeImport); - if ((NULL != strShouldBreakOnTypeName) && (wcsncmp(strShouldBreakOnTypeName, m_szName, MAX_CLASSNAME_LENGTH) == 0)) - _ASSERTE(!"MD_TlbImp_BreakOnTypeImport"); -#endif - - // Assume that we will be able to convert the typeinfo. - guid = m_psAttr->guid; - wTypeInfoFlags = m_psAttr->wTypeFlags; - - // If this typeinfo is an alias, see what it is an alias for. If for a built-in - // type, we will just skip it. If for a user-defined type, we will duplicate - // that definition under this alias' name and guid. - if (m_psAttr->typekind == TKIND_ALIAS) - { - hr = _ResolveTypeDescAliasTypeKind(m_pITI, &m_psAttr->tdescAlias, &tkindAlias); - IfFailGo(hr); - if (hr == S_OK) - { - TYPEDESC tdesc = m_psAttr->tdescAlias; - m_pITI->ReleaseTypeAttr(m_psAttr); - m_pITI->Release(); - - IfFailGo(_ResolveTypeDescAlias(m_pOrigITI, &tdesc, &m_pITI, &m_psAttr, &guid)); - // Now m_pOrigITI refers to the alias whereas m_pITI is the TypeInfo of the aliased type. - - // We should no longer have an alias. - _ASSERTE(m_psAttr->typekind == tkindAlias); - _ASSERTE(tkindAlias != TKIND_ALIAS); - - ulFlags = rdwTypeFlags[tkindAlias]; - } - else - ulFlags = ULONG_MAX; - } - else - { - ulFlags = rdwTypeFlags[m_psAttr->typekind]; - } - - // Figure out the name. - - // If the type info is for a CoClass, we need to decorate the name. - if (m_psAttr->typekind == TKIND_COCLASS) - { - // Generate a mangled name for the component. - IfFailGo(GetManagedNameForCoClass(m_pOrigITI, qbClassName)); - m_szMngName = qbClassName.Ptr(); - } - else - { - IfFailGo(GetManagedNameForTypeInfo(m_pOrigITI, m_wzNamespace, NULL, &bstrManagedName)); - m_szMngName = bstrManagedName; - } - - if (m_psAttr->typekind == TKIND_INTERFACE || - (m_psAttr->typekind == TKIND_DISPATCH && m_psAttr->wTypeFlags & TYPEFLAG_FDUAL)) - { - // If the interface is not derived from IUnknown, or not an interface, we can't convert it. - if (IsIUnknownDerived(m_pITI, m_psAttr) != S_OK) - { - ReportEvent(NOTIF_CONVERTWARNING, TLBX_E_NOTIUNKNOWN, m_szName); - ulFlags = ULONG_MAX; - } - // If the interface is not derived from IDispatch, but claims to be [dual], give a warning but convert it. - if ((m_psAttr->wTypeFlags & TYPEFLAG_FDUAL) && IsIDispatchDerived(m_pITI, m_psAttr) != S_OK) - { - ReportEvent(NOTIF_CONVERTWARNING, TLBX_W_DUAL_NOT_DISPATCH, m_szName); - } - } - else - if (m_psAttr->typekind == TKIND_MODULE) - { // If module has no vars, skip it. We currently don't import module functions. - if (m_psAttr->cVars == 0) - ulFlags = ULONG_MAX; - } - - // If something we can convert... - if (ulFlags != ULONG_MAX) - { - // Interfaces derive from nil... - if (IsTdInterface(ulFlags)) - tkParent = mdTypeDefNil; - else // ... enums from Enum, ... - if (m_psAttr->typekind == TKIND_ENUM) - { - if (IsNilToken(m_trEnum)) - IfFailGo(m_TRMap.DefineTypeRef(m_pEmit, m_arSystem, szEnum, &m_trEnum)); - tkParent = m_trEnum; - } - else // ... structs from ValueType, ... - if (m_psAttr->typekind == TKIND_RECORD || m_psAttr->typekind == TKIND_UNION) - { - if (IsNilToken(m_trValueType)) - IfFailGo(m_TRMap.DefineTypeRef(m_pEmit, m_arSystem, szValueType, &m_trValueType)); - tkParent = m_trValueType; - } - else // ... and classes derive from Object. - tkParent = m_trObject; - - // The typelib importer generates metadata into an empty ReflectionEmit scope. Because - // RE manages type names itself, duplicate checking is turned off. Because of user-defined - // names (via CUSTOM), it is possible for the user to declare a duplicate. So, - // before adding the new type, check for duplicates. - hr = m_pImport->FindTypeDefByName(m_szMngName, mdTypeDefNil, &td); - if (hr != CLDB_E_RECORD_NOTFOUND) - { - ReportEvent(NOTIF_CONVERTWARNING, TLBX_E_DUPLICATE_TYPE_NAME, m_szMngName); - IfFailGo(TLBX_E_DUPLICATE_TYPE_NAME); - } - - // Create the typedef. - IfFailGo(m_pEmit->DefineTypeDef(m_szMngName, ulFlags, tkParent, 0, &m_tdTypeDef)); - IfFailGo(_AddGuidCa(m_tdTypeDef, guid)); - - // Save the typeinfo flags. - if (wTypeInfoFlags) - { - IfFailGo(GetAttrType(ATTR_TYPELIBTYPE, &tkAttr)); - DECLARE_CUSTOM_ATTRIBUTE(sizeof(WORD)); - BUILD_CUSTOM_ATTRIBUTE(WORD, wTypeInfoFlags); - FINISH_CUSTOM_ATTRIBUTE(); - IfFailGo(m_pEmit->DefineCustomAttribute(m_tdTypeDef, tkAttr, PTROF_CUSTOM_ATTRIBUTE(), SIZEOF_CUSTOM_ATTRIBUTE(),0)); - } - - // Mark unsafe interfaces (suppressed security runtime checks). - if (m_bUnsafeInterfaces) - { - if (m_tkSuppressCheckAttr == mdTokenNil) - { - mdTypeRef tr; - COR_SIGNATURE rSig[] = {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 0, ELEMENT_TYPE_VOID}; - IfFailGo(m_pEmit->DefineTypeRefByName(m_arSystem, COR_SUPPRESS_UNMANAGED_CODE_CHECK_ATTRIBUTE, &tr)); - IfFailGo(m_pEmit->DefineMemberRef(tr, COR_CTOR_METHOD_NAME_W, rSig, lengthof(rSig), &m_tkSuppressCheckAttr)); - } - - DECLARE_CUSTOM_ATTRIBUTE(0); - FINISH_CUSTOM_ATTRIBUTE(); - IfFailGo(m_pEmit->DefineCustomAttribute(m_tdTypeDef, m_tkSuppressCheckAttr, PTROF_CUSTOM_ATTRIBUTE(), SIZEOF_CUSTOM_ATTRIBUTE(), 0)); - } - - // Fill in the details depending on the type of the TypeInfo. - switch (m_psAttr->typekind) - { - case TKIND_ENUM: - hr = ConvEnum(m_pITI, m_psAttr); - break; - - case TKIND_RECORD: - hr = ConvRecord(m_pITI, m_psAttr, FALSE); - break; - - case TKIND_UNION: - hr = ConvRecord(m_pITI, m_psAttr, TRUE); - break; - - case TKIND_MODULE: - hr = ConvModule(m_pITI, m_psAttr); - break; - - case TKIND_INTERFACE: - hr = ConvIface(m_pITI, m_psAttr); - break; - - case TKIND_DISPATCH: - hr = ConvDispatch(m_pITI, m_psAttr); - break; - - case TKIND_COCLASS: - hr = ConvCoclass(m_pITI, m_psAttr); - break; - - case TKIND_ALIAS: - _ASSERTE(!"Alias should have been resolved!"); - break; - - default: - _ASSERTE(!"Unexpected TYPEKIND"); - break; - } - if (FAILED(hr)) - goto ErrExit; - - if (hr == S_CONVERSION_LOSS) - { - bConversionLoss = true; - IfFailGo(GetAttrType(ATTR_COMCONVERSIONLOSS, &tkAttr)); - DECLARE_CUSTOM_ATTRIBUTE(0); - FINISH_CUSTOM_ATTRIBUTE(); - IfFailGo(m_pEmit->DefineCustomAttribute(m_tdTypeDef, tkAttr, PTROF_CUSTOM_ATTRIBUTE(),SIZEOF_CUSTOM_ATTRIBUTE(),0)); - } - - } - - if (bConversionLoss) - hr = S_CONVERSION_LOSS; - else - hr = S_OK; - -#if defined(TLB_STATS) - LARGE_INTEGER __stopVal; - QueryPerformanceCounter(&__stopVal); - DWORD __delta; - __delta = (DWORD)(__stopVal.QuadPart - __startVal.QuadPart); - StringCchPrintf(rcStats, COUNTOF(rcStats), W(" %.2f"), - ((float)__delta*1000)/(float)m_freqVal.QuadPart); -#endif - - // Report that this type has been converted. - ReportEvent(NOTIF_TYPECONVERTED, TLBX_I_TYPEINFO_IMPORTED, m_szName); - -ErrExit: - if (pITI2) - pITI2->Release(); - if (m_szName) - ::SysFreeString(m_szName), m_szName = 0; - if (bstrManagedName) - ::SysFreeString(bstrManagedName); - return (hr); -} // HRESULT CImportTlb::ConvertTypeInfo() - - -//***************************************************************************** -// Determine if the type explicitly implements IEnumerable. -//***************************************************************************** -HRESULT CImportTlb::ExplicitlyImplementsIEnumerable( - ITypeInfo *pITI, // ITypeInfo* to check for IEnumerable. - TYPEATTR *psAttr, // TYPEATTR of TypeInfo. - BOOL fLookupPartner) // Flag indicating if we should look at the partner itf. -{ - HREFTYPE href; // HREFTYPE of an implemented interface. - ITypeInfo *pItiIface=0; // ITypeInfo for an interface. - TYPEATTR *psAttrIface=0; // TYPEATTR for an interface. - BOOL fFoundImpl = FALSE; - int i = 0; - HRESULT hr = S_OK; - ITypeInfo* pITISelf2 = NULL; - TYPEATTR psAttrSelf2; - int ImplFlags = 0; - - // Look through each of the implemented/inherited interfaces - for (i=0; i<psAttr->cImplTypes && !fFoundImpl; ++i) - { - // Get an interface - IfFailGo(pITI->GetRefTypeOfImplType(i, &href)); - IfFailGo(pITI->GetRefTypeInfo(href, &pItiIface)); - IfFailGo(pItiIface->GetTypeAttr(&psAttrIface)); - IfFailGo(pITI->GetImplTypeFlags(i, &ImplFlags)); - - if (!(ImplFlags & IMPLTYPEFLAG_FSOURCE)) - { - hr = ExplicitlyImplementsIEnumerable(pItiIface, psAttrIface, TRUE); - if (hr == S_OK) - fFoundImpl = TRUE; - - // Check this interface for the IEnumerable. - if (psAttrIface->guid == IID_IEnumerable) - fFoundImpl = TRUE; - } - - pItiIface->ReleaseTypeAttr(psAttrIface); - psAttrIface = 0; - pItiIface->Release(); - pItiIface = 0; - } - - if ( fLookupPartner && (pITI->GetRefTypeOfImplType(-1, &href) == S_OK) ) - { - IfFailGo(pITI->GetRefTypeInfo(href, &pItiIface)); - IfFailGo(pItiIface->GetTypeAttr(&psAttrIface)); - - hr = ExplicitlyImplementsIEnumerable(pItiIface, psAttrIface, FALSE); - if (hr == S_OK) - fFoundImpl = TRUE; - - // Check this interface for the IEnumerable. - if (psAttrIface->guid == IID_IEnumerable) - fFoundImpl = TRUE; - } - - -ErrExit: - if (psAttrIface) - pItiIface->ReleaseTypeAttr(psAttrIface); - if (pItiIface) - pItiIface->Release(); - - return (fFoundImpl) ? S_OK : S_FALSE; -} - - -//***************************************************************************** -// Convert the details for a coclass. -//***************************************************************************** -#ifdef _PREFAST_ -#pragma warning(push) -#pragma warning(disable:21000) // Suppress PREFast warning about overly large function -#endif -HRESULT CImportTlb::ConvCoclass( // S_OK or error. - ITypeInfo *pITI, // ITypeInfo* to convert. - TYPEATTR *psAttr) // TYPEATTR of TypeInfo. -{ - BOOL fHadDefaultItf = FALSE; - HRESULT hr; // A result. - int i; // Loop control. - HREFTYPE href; // HREFTYPE of an implemented interface. - ITypeInfo *pItiIface=0; // ITypeInfo for an interface. - TYPEATTR *psAttrIface=0; // TYPEATTR for an interface. - int ImplFlags; // ImplType flags. - mdToken tkIface; // Token for an interface. - CQuickArray<mdToken> rImpls; // Array of implemented interfaces. - CQuickArray<mdToken> rEvents; // Array of implemented event interfaces. - CQuickArray<mdToken> rTmpImpls; // Temporary array of impls. - CQuickArray<ITypeInfo*> rImplTypes; // Array of implemented ITypeInfo*s. - CQuickArray<ITypeInfo*> rSrcTypes; // Array of source ITypeInfo*s. - int ixSrc; // Index into rSrcTypes for source interfaces. - int ixImpl; // Index into rImpls for implemented interface. - int ixTmpImpl; // Index into rTmpImpls. - mdToken mdCtor; // Dummy token for the object initializer. - mdToken tkAttr; // Token for custom attribute type. - mdToken token; // Dummy token for typeref. - BOOL fInheritsIEnum = FALSE; - -#ifdef _DEBUG - int bImplIEnumerable=0; // If true, the class implements IEnumerable. -#endif - - // Size the rImpls and rSrcs arrays large enough for impls, events, the IEnumerable itf and two ending nulls. - IfFailGo(rImpls.ReSizeNoThrow(psAttr->cImplTypes+2)); - memset(rImpls.Ptr(), 0, (psAttr->cImplTypes+2)*sizeof(mdToken)); - IfFailGo(rEvents.ReSizeNoThrow(psAttr->cImplTypes+1)); - memset(rEvents.Ptr(), 0, (psAttr->cImplTypes+1)*sizeof(mdToken)); - IfFailGo(rTmpImpls.ReSizeNoThrow(psAttr->cImplTypes+3)); - memset(rTmpImpls.Ptr(), 0, (psAttr->cImplTypes+3)*sizeof(mdToken)); - IfFailGo(rImplTypes.ReSizeNoThrow(psAttr->cImplTypes+2)); - memset(rImplTypes.Ptr(), 0, (psAttr->cImplTypes+2)*sizeof(ITypeInfo*)); - IfFailGo(rSrcTypes.ReSizeNoThrow(psAttr->cImplTypes+1)); - memset(rSrcTypes.Ptr(), 0, (psAttr->cImplTypes+1)*sizeof(ITypeInfo*)); - ixImpl = -1; - ixSrc = -1; - ixTmpImpl = -1; - - if (ExplicitlyImplementsIEnumerable(pITI, psAttr) == S_OK) - fInheritsIEnum = TRUE; - - // Build the list of implemented and event interfaces. - // The EE cares about implemented interfaces, so we convert them to actual - // tokens and add them to the typedef. VB cares about event interfaces, - // but we are going to add a list of typeref names as a custom attribute. - // We can't build the list as we go along, because the default may not - // be the first event source. So, we store tokens for the implemented - // interfaces, but ITypeInfo*s for the event sources. - for (i=0; i<psAttr->cImplTypes; ++i) - { - IfFailGo(pITI->GetRefTypeOfImplType(i, &href)); - IfFailGo(pITI->GetRefTypeInfo(href, &pItiIface)); - IfFailGo(pItiIface->GetTypeAttr(&psAttrIface)); - IfFailGo(pITI->GetImplTypeFlags(i, &ImplFlags)); - - // If the interface is derived from IUnknown, or not an interface, we can't use it as an interface. - // Don't add explicit IUnknown or IDispatch. - if ((IsIUnknownDerived(pItiIface, psAttrIface) != S_OK && psAttrIface->typekind != TKIND_DISPATCH) || - psAttrIface->guid == IID_IDispatch || - psAttrIface->guid == IID_IUnknown) - { - pItiIface->ReleaseTypeAttr(psAttrIface); - psAttrIface = 0; - pItiIface->Release(); - pItiIface = 0; - continue; - } - - // Add the event to the impls list or the events list. - if (ImplFlags & IMPLTYPEFLAG_FSOURCE) - { - // Get the token for the event interface. - IfFailGo(_GetTokenForEventItf(pItiIface, &tkIface)); - - // If we've already marked this CoClass as implementing this source interface, don't do so again. - for (int iCheck=0; iCheck <= ixSrc; iCheck++) - { - if (rEvents[iCheck] == tkIface) - goto LoopEnd; - } - - // Add the source interface to the list of source interfaces. - ++ixSrc; - - // If this is explicitly the default source interface... - if (ImplFlags & IMPLTYPEFLAG_FDEFAULT) - { - // Put the def source ITypeInfo at the head of the list of source - // ITypeInfo's. - for (int ix = ixSrc; ix > 0; --ix) - { - rSrcTypes[ix] = rSrcTypes[ix-1]; - rEvents[ix] = rEvents[ix-1]; - } - rEvents[0] = tkIface; - rSrcTypes[0] = pItiIface; - } - else - { - rEvents[ixSrc] = tkIface; - rSrcTypes[ixSrc] = pItiIface; - } - } - else - { - // Get the token for the interface. - IfFailGo(_GetTokenForTypeInfo(pItiIface, FALSE, &tkIface)); - - // If we've already marked this CoClass as implementing this interface, don't do so again. - for (int iCheck=0; iCheck <= ixImpl; iCheck++) - { - if (rImpls[iCheck] == tkIface) - goto LoopEnd; - } - - // Add the implemented interface to the list of implemented interfaces. - ++ixImpl; - - // If this is explicitly the default interface... - if (ImplFlags & IMPLTYPEFLAG_FDEFAULT) - { - fHadDefaultItf = TRUE; - // Put the new interface at the start of the list. - for (int ix=ixImpl; ix > 0; --ix) - { - rImpls[ix] = rImpls[ix-1]; - rImplTypes[ix] = rImplTypes[ix-1]; - } - rImpls[0] = tkIface; - rImplTypes[0] = pItiIface; - } - else - { - rImpls[ixImpl] = tkIface; - rImplTypes[ixImpl] = pItiIface; - } - } - -LoopEnd: - pItiIface->ReleaseTypeAttr(psAttrIface); - psAttrIface = 0; - pItiIface = 0; // Pointer now owned by array. - } - - // Create an interface that will represent the class. - IfFailGo(_CreateClassInterface(pITI, rImplTypes[0], rImpls[0], rEvents[0], &tkIface)); - - // Create a temporary array of interface tokens. - if (fHadDefaultItf) - { - // default interface should be the first interface - rTmpImpls[++ixTmpImpl] = rImpls[0]; - rTmpImpls[++ixTmpImpl] = tkIface; - } - else - { - rTmpImpls[++ixTmpImpl] = tkIface; - if (ixImpl >= 0) - rTmpImpls[++ixTmpImpl] = rImpls[0]; - } - if (ixSrc >= 0) - rTmpImpls[++ixTmpImpl] = rEvents[0]; - if (ixImpl >= 0) - { - memcpy(&rTmpImpls[ixTmpImpl + 1], &rImpls[1], ixImpl * sizeof(mdTypeRef)); - ixTmpImpl += ixImpl; - } - if (ixSrc >= 0) - { - memcpy(&rTmpImpls[ixTmpImpl + 1], &rEvents[1], ixSrc * sizeof(mdTypeRef)); - ixTmpImpl += ixSrc; - } - - // Check to see if the default interface has a member with a DISPID of DISPID_NEWENUM. - BOOL fIEnumFound = FALSE; - if (ixImpl >= 0) - { - // The ITypeInfo for the default interface had better be set. - _ASSERTE(rImplTypes[0]); - - if ( (!fInheritsIEnum) && (HasNewEnumMember(rImplTypes[0]) == S_OK) ) - { - IfFailGo(GetKnownTypeToken(VT_SLOT_FOR_IENUMERABLE, &tkIface)); - rTmpImpls[++ixTmpImpl] = tkIface; - fIEnumFound = TRUE; - } - } - - // Else Check to see if the IEnumerable Custom Value exists on the CoClass. - if (!fIEnumFound) - { - BOOL CVExists = FALSE; - _ForceIEnumerableCVExists(pITI, &CVExists); - if (CVExists && !fInheritsIEnum) - { - IfFailGo(GetKnownTypeToken(VT_SLOT_FOR_IENUMERABLE, &tkIface)); - rTmpImpls[++ixTmpImpl] = tkIface; - fIEnumFound = TRUE; - } - } - - // Add the implemented interfaces and event interfaces to the TypeDef. - IfFailGo(m_pEmit->SetTypeDefProps(m_tdTypeDef, ULONG_MAX/*Classflags*/, - ULONG_MAX, (mdToken*)rTmpImpls.Ptr())); - - // Create an initializer for the class. - ULONG ulFlags; - if (psAttr->wTypeFlags & TYPEFLAG_FCANCREATE) - ulFlags = OBJECT_INITIALIZER_FLAGS; - else - ulFlags = NONCREATABLE_OBJECT_INITIALIZER_FLAGS; - { - IfFailGo(m_pEmit->DefineMethod(m_tdTypeDef, OBJECT_INITIALIZER_NAME, ulFlags, - OBJECT_INITIALIZER_SIG, sizeof(OBJECT_INITIALIZER_SIG), 0/*rva*/, OBJECT_INITIALIZER_IMPL_FLAGS/*flags*/, &mdCtor)); - } - - // Set ClassInterfaceType.None on the generated class. - DECLARE_CUSTOM_ATTRIBUTE(sizeof(short)); - BUILD_CUSTOM_ATTRIBUTE(short, clsIfNone); - IfFailGo(GetAttrType(ATTR_CLASSINTERFACE, &tkAttr)); - FINISH_CUSTOM_ATTRIBUTE(); - IfFailGo(m_pEmit->DefineCustomAttribute(m_tdTypeDef, tkAttr, PTROF_CUSTOM_ATTRIBUTE(), SIZEOF_CUSTOM_ATTRIBUTE(), 0)); - - - if (!m_bPreventClassMembers) - { - // Iterate over the implemented interfaces, and add the members to the coclass. - m_ImplIface = eImplIfaceDefault; - for (i=0; i<=ixImpl; ++i) - { - _ASSERTE(rImplTypes[i]); - - // Interface info. - m_tkInterface = rImpls[i]; - pItiIface = rImplTypes[i]; - rImplTypes[i] = 0; // ownership transferred. - - // Get interface name for decoration. - if (m_szInterface) - ::SysFreeString(m_szInterface), m_szInterface = 0; - IfFailGo(pItiIface->GetDocumentation(MEMBERID_NIL, &m_szInterface, 0,0,0)); - - // Add the interface members to the coclass. - IfFailGo(pItiIface->GetTypeAttr(&psAttrIface)); - switch (psAttrIface->typekind) - { - case TKIND_DISPATCH: - hr = ConvDispatch(pItiIface, psAttrIface, false); - break; - case TKIND_INTERFACE: - hr = ConvIface(pItiIface, psAttrIface, false); - break; - default: - hr = S_OK; - _ASSERTE(!"Unexpected typekind for implemented interface"); - } - pItiIface->ReleaseTypeAttr(psAttrIface); - psAttrIface = 0; - IfFailGo(hr); - m_ImplIface = eImplIface; - rImplTypes[i] = pItiIface; - pItiIface = 0; // ownership transferred back. - } - - // Add the methods of the event interfaces to the class. - for (i=0; i<=ixSrc; ++i) - IfFailGo(_AddSrcItfMembersToClass(rEvents[i])); - } - - // If there are source interfaces, add a custom value for that. - if (ixSrc >= 0) - { - CQuickArray<char> rEvents; // Output buffer. - int cbCur; // Current location in output buffer. - int cbReq; // Size of an individual piece. - CQuickArray<WCHAR> rEvent; - - // Save 6 bytes at the beginning of the buffer for the custom attribute prolog and - // the string length. The string length may require 1, 2, or 4 bytes to express. - cbCur = 6; - - // For each event interface... - for (int ix=0; ix <= ixSrc; ++ix) - { - pItiIface = rSrcTypes[ix]; - rSrcTypes[ix] = 0; - - // Get the typeref name for the interface. - for(;;) - { - int cchReq; - IfFailGo(_GetTokenForTypeInfo(pItiIface, FALSE, &token, rEvent.Ptr(), (int)rEvent.MaxSize(), &cchReq, TRUE)); - if (cchReq <= (int)rEvent.MaxSize()) - break; - IfFailGo(rEvent.ReSizeNoThrow(cchReq)); - } - - // Append to the buffer. See how much space is required, get it. - cbReq = WszWideCharToMultiByte(CP_UTF8,0, rEvent.Ptr(),-1, 0,0, 0,0); - - // make sure we have enough space for the extra terminating 0 and for the 00 00 suffix - size_t cbNewSize; - if (!ClrSafeInt<size_t>::addition(cbCur, cbReq, cbNewSize) || - !ClrSafeInt<size_t>::addition(cbNewSize, 3, cbNewSize)) - { - IfFailGo(COR_E_OVERFLOW); - } - if (cbNewSize > rEvents.MaxSize()) - { - IfFailGo(rEvents.ReSizeNoThrow(cbNewSize)); - } - // Do the conversion. - WszWideCharToMultiByte(CP_UTF8,0, rEvent.Ptr(),-1, rEvents.Ptr()+cbCur,cbReq, 0,0); - cbCur += cbReq; - pItiIface->Release(); - } - pItiIface = 0; - - // Add an extra terminating 0. - *(rEvents.Ptr()+cbCur) = 0; - ++cbCur; - - // Now build the custom attribute. - int iLen = cbCur - 6; - char *pBytes = rEvents.Ptr(); - - // Length may be encoded with less the 4 bytes. - int lenPad = 4 - CPackedLen::Size(iLen); - _ASSERTE(lenPad >= 0); - - pBytes += lenPad; - cbCur -= lenPad; - - // Prologue. - pBytes[0] = 0x01; - pBytes[1] = 0x00; - - CPackedLen::PutLength(pBytes + 2, iLen); - - // Zero named properties/fields. - pBytes[cbCur + 0] = 0x00; - pBytes[cbCur + 1] = 0x00; - cbCur += 2; - - // Finally, store it. - IfFailGo(GetAttrType(ATTR_COMSOURCEINTERFACES, &tkAttr)); - IfFailGo(m_pEmit->DefineCustomAttribute(m_tdTypeDef, tkAttr, pBytes, cbCur, 0)); - } - -ErrExit: - if (psAttrIface) - pItiIface->ReleaseTypeAttr(psAttrIface); - if (pItiIface) - pItiIface->Release(); - // Clean up any left-over ITypeInfo*. - for (ULONG ix=0; ix < rImplTypes.Size(); ++ix) - if (rImplTypes[ix]) - (rImplTypes[ix])->Release(); - for (ULONG ix=0; ix < rSrcTypes.Size(); ++ix) - if (rSrcTypes[ix]) - (rSrcTypes[ix])->Release(); - m_tkInterface = 0; - if (m_szInterface) - ::SysFreeString(m_szInterface), m_szInterface = 0; - m_ImplIface = eImplIfaceNone; - return (hr); -} // HRESULT CImportTlb::ConvCoclass() -#ifdef _PREFAST_ -#pragma warning(pop) -#endif - -//***************************************************************************** -// Convert an enum to a class with fields that have default values. -//***************************************************************************** -HRESULT CImportTlb::ConvEnum( // S_OK or error. - ITypeInfo *pITI, // ITypeInfo* to convert. - TYPEATTR *psAttr) // TYPEATTR of TypeInfo. -{ - HRESULT hr; // A result. - int i; // Loop control. - VARDESC *psVar=0; // VARDESC for a member. - mdFieldDef mdField; // The FieldDef for the enum's type. - - // Create the field definition for the enum type. Always import as an __int32. - IfFailGo(m_pEmit->DefineField(m_tdTypeDef, ENUM_TYPE_NAME, ENUM_TYPE_FLAGS, ENUM_TYPE_SIGNATURE,ENUM_TYPE_SIGNATURE_SIZE, - 0,0, -1, &mdField)); - - // Iterate over the vars. - for (i=0; i<psAttr->cVars; ++i) - { - // Get variable information. - IfFailGo(pITI->GetVarDesc(i, &psVar)); - // Do the conversion. - IfFailGo(_ConvConstant(pITI, psVar, true/*enum member*/)); - // Release for next var. - pITI->ReleaseVarDesc(psVar); - psVar = 0; - } - - hr = S_OK; - -ErrExit: - if (psVar) - pITI->ReleaseVarDesc(psVar); - return (hr); -} // HRESULT CImportTlb::ConvEnum() - -//***************************************************************************** -// Convert a record to a class with fields. -//***************************************************************************** -HRESULT CImportTlb::ConvRecord( // S_OK or error. - ITypeInfo *pITI, // ITypeInfo* to convert. - TYPEATTR *psAttr, // TYPEATTR of TypeInfo. - BOOL bUnion) // Convert as a union? -{ - HRESULT hr=S_OK; // A result. - int i; // Loop control. - VARDESC *psVar=0; // VARDESC for a member. - mdFieldDef mdField; // Token for a given field. - CQuickArray<COR_FIELD_OFFSET> rLayout; // Array for layout information. - BOOL bConversionLoss=false; // If true, some attributes were lost on conversion. - - // Unions with embedded Object Types can't really be converted. Just reserve correct size. - if (bUnion && (HasObjectFields(pITI, psAttr) == S_OK)) - { - IfFailGo(m_pEmit->SetClassLayout(m_tdTypeDef, psAttr->cbAlignment, 0, psAttr->cbSizeInstance)); - goto ErrExit; - } - - // Prepare for layout info. - IfFailGo(rLayout.ReSizeNoThrow(psAttr->cVars+1)); - - // Iterate over the vars. - for (i=0; i<psAttr->cVars; ++i) - { - // Get variable information. - IfFailGo(pITI->GetVarDesc(i, &psVar)); - // Do the conversion. - IfFailGo(_ConvField(pITI, psVar, &mdField, bUnion)); - if (hr == S_CONVERSION_LOSS) - bConversionLoss = true; - // Save the layout info. - rLayout[i].ridOfField = mdField; - rLayout[i].ulOffset = psVar->oInst; - // Release for next var. - pITI->ReleaseVarDesc(psVar); - psVar = 0; - } - - // If it is a union, Save the layout information. - if (bUnion) - { - rLayout[psAttr->cVars].ridOfField = mdFieldDefNil; - IfFailGo(m_pEmit->SetClassLayout(m_tdTypeDef, psAttr->cbAlignment, rLayout.Ptr(), -1)); - } - else // Not a union. Preserve the alignment. - IfFailGo(m_pEmit->SetClassLayout(m_tdTypeDef, psAttr->cbAlignment, 0, -1)); - - // If we are marking these as serializable - do so now. - if (m_bSerializableValueClasses) - { - mdToken tkAttr; - IfFailGo(GetAttrType(ATTR_SERIALIZABLE, &tkAttr)); - DECLARE_CUSTOM_ATTRIBUTE(0); - FINISH_CUSTOM_ATTRIBUTE(); - IfFailGo(m_pEmit->DefineCustomAttribute(m_tdTypeDef, tkAttr, PTROF_CUSTOM_ATTRIBUTE(),SIZEOF_CUSTOM_ATTRIBUTE(),0)); - } - - if (bConversionLoss) - hr = S_CONVERSION_LOSS; - -ErrExit: - if (psVar) - pITI->ReleaseVarDesc(psVar); - return (hr); -} // HRESULT CImportTlb::ConvRecord() - -//***************************************************************************** -// Convert an module to a class with fields that have default values. -// @FUTURE: convert methods as PInvoke methods. -//***************************************************************************** -HRESULT CImportTlb::ConvModule( // S_OK or error. - ITypeInfo *pITI, // ITypeInfo* to convert. - TYPEATTR *psAttr) // TYPEATTR of TypeInfo. -{ - HRESULT hr; // A result. - int i; // Loop control. - VARDESC *psVar=0; // VARDESC for a member. - - // Iterate over the vars. - for (i=0; i<psAttr->cVars; ++i) - { - // Get variable information. - IfFailGo(pITI->GetVarDesc(i, &psVar)); - // Do the conversion. - IfFailGo(_ConvConstant(pITI, psVar)); - // Release for next var. - pITI->ReleaseVarDesc(psVar); - psVar = 0; - } - - hr = S_OK; - -ErrExit: - if (psVar) - pITI->ReleaseVarDesc(psVar); - return (hr); -} // HRESULT CImportTlb::ConvModule() - -//***************************************************************************** -// Convert metadata for an interface. -//***************************************************************************** -HRESULT CImportTlb::ConvIface( // S_OK or error. - ITypeInfo *pITI, // ITypeInfo* to convert. - TYPEATTR *psAttr, // TYPEATTR of TypeInfo. - BOOL bVtblGapFuncs) // Vtable gap functions? -{ - HRESULT hr; // A result. - ITypeInfo *pITIBase=0; // ITypeInfo* of base interface. - TYPEATTR *psAttrBase=0; // TYPEATTR of base interface. - ITypeInfo *pITISelf2=0; // ITypeInfo* of partner. - TYPEATTR *psAttrSelf2=0; // TYPEATTR of partner. - mdToken tkImpls[3]={0,0,0}; // Token of implemented interfaces. - int ixImpls = 0; // Index of current implemented interface. - HREFTYPE href; // href of base interface. - mdToken tkIface; // Token for an interface. - BOOL fInheritsIEnum = FALSE; - - // If there is a partner interface, prefer it. - if (pITI->GetRefTypeOfImplType(-1, &href) == S_OK) - { - IfFailGo(pITI->GetRefTypeInfo(href, &pITISelf2)); - IfFailGo(pITISelf2->GetTypeAttr(&psAttrSelf2)); - } - - // Base interface? - if (psAttr->cImplTypes == 1) - { - IfFailGo(pITI->GetRefTypeOfImplType(0, &href)); - IfFailGo(pITI->GetRefTypeInfo(href, &pITIBase)); - IfFailGo(pITIBase->GetTypeAttr(&psAttrBase)); - - // If this interface extends something other than IDispatch or IUnknown, record that - // fact as an "implemented interface". - if (psAttrBase->guid != IID_IDispatch && psAttrBase->guid != IID_IUnknown) - { - // Get Token of the base interface. - IfFailGo(_GetTokenForTypeInfo(pITIBase, FALSE, &tkImpls[ixImpls++])); - } - else - { // Maybe we're "funky"... - if (pITISelf2) - { - pITIBase->ReleaseTypeAttr(psAttrBase); - pITIBase->Release(); - pITIBase = 0; - psAttrBase = 0; - - if (psAttrSelf2->cImplTypes == 1) - { - IfFailGo(pITISelf2->GetRefTypeOfImplType(0, &href)); - IfFailGo(pITISelf2->GetRefTypeInfo(href, &pITIBase)); - IfFailGo(pITIBase->GetTypeAttr(&psAttrBase)); - - if (psAttrBase->guid != IID_IDispatch && psAttrBase->guid != IID_IUnknown) - { - // Get Token of the base interface. - IfFailGo(_GetTokenForTypeInfo(pITIBase, FALSE, &tkImpls[ixImpls++])); - } - } - else - { - BSTR szTypeInfoName; - pITISelf2->GetDocumentation(MEMBERID_NIL, &szTypeInfoName, 0, 0, 0); - ReportEvent(NOTIF_CONVERTWARNING, TLBX_E_INVALID_TYPEINFO, szTypeInfoName); - SysFreeString(szTypeInfoName); - - IfFailGo(TLBX_E_INVALID_TYPEINFO); - } - } - } - - pITIBase->ReleaseTypeAttr(psAttrBase); - psAttrBase = 0; - pITIBase->Release(); - pITIBase = 0; - } - - if (ExplicitlyImplementsIEnumerable(pITI, psAttr) == S_OK) - fInheritsIEnum = TRUE; - - // If this interface has a NewEnum member then have it implement IEnumerable. - if ( (!fInheritsIEnum) && (HasNewEnumMember(pITI) == S_OK) ) - { - IfFailGo(GetKnownTypeToken(VT_SLOT_FOR_IENUMERABLE, &tkIface)); - tkImpls[ixImpls++] = tkIface; - } - - // If not processing an implemented interface, add additional interface properties. - if (m_ImplIface == eImplIfaceNone) - { - // Set base interface as an implemented interface. - if (tkImpls[0]) - IfFailGo(m_pEmit->SetTypeDefProps(m_tdTypeDef, ULONG_MAX/*flags*/, ULONG_MAX/*extends*/, tkImpls)); - - // If the interface is not derived from IDispatch mark it as IUnknown based. - if (IsIDispatchDerived(pITI, psAttr) == S_FALSE) - { - mdMemberRef mr; - // Note that this is a vtable, but not IDispatch derived. - // Custom attribute buffer. - DECLARE_CUSTOM_ATTRIBUTE(sizeof(short)); - // Set up the attribute. - BUILD_CUSTOM_ATTRIBUTE(short, ifVtable); - // Store the attribute - IfFailGo(GetAttrType(ATTR_INTERFACETYPE, &mr)); - FINISH_CUSTOM_ATTRIBUTE(); - IfFailGo(m_pEmit->DefineCustomAttribute(m_tdTypeDef, mr, PTROF_CUSTOM_ATTRIBUTE(), SIZEOF_CUSTOM_ATTRIBUTE(), 0)); - } - } - - // Convert the members on the interface (and base interfaces). - // If this interface had a "funky partner", base the conversion on that. - if (pITISelf2) - IfFailGo(_ConvIfaceMembers(pITISelf2, psAttrSelf2, bVtblGapFuncs, psAttr->wTypeFlags & TYPEFLAG_FDUAL, fInheritsIEnum)); - else - IfFailGo(_ConvIfaceMembers(pITI, psAttr, bVtblGapFuncs, psAttr->wTypeFlags & TYPEFLAG_FDUAL, fInheritsIEnum)); - -ErrExit: - if (psAttrSelf2) - pITISelf2->ReleaseTypeAttr(psAttrSelf2); - if (pITISelf2) - pITISelf2->Release(); - if (psAttrBase) - pITIBase->ReleaseTypeAttr(psAttrBase); - if (pITIBase) - pITIBase->Release(); - return (hr); -} // HRESULT CImportTlb::ConvIface() - -//***************************************************************************** -// Convert the metadata for a dispinterface. Try to convert as a normal -// interface. -//***************************************************************************** -HRESULT CImportTlb::ConvDispatch( // S_OK or error. - ITypeInfo *pITI, // ITypeInfo* to convert. - TYPEATTR *psAttr, // TYPEATTR of TypeInfo. - BOOL bVtblGapFuncs) // Vtable gap functions for interface implementations? -{ - HRESULT hr; // A result. - HREFTYPE href; // Base interface href. - ITypeInfo *pITIBase=0; // Base interface ITypeInfo. - TYPEATTR *psAttrBase=0; // TYPEATTR of base interface. - mdMemberRef mr; // MemberRef for custom value. - DWORD attr[2] = {0x00010001, 0x00000002}; - BYTE bIface = ifDispatch; // Custom value means "dispinterface" - BOOL fInheritsIEnum = FALSE; - - // If this is a dual interface, treat it like a normal interface. - if ((psAttr->wTypeFlags & TYPEFLAG_FDUAL)) - { - hr = ConvIface(pITI, psAttr, bVtblGapFuncs); - goto ErrExit; - } - - if (ExplicitlyImplementsIEnumerable(pITI, psAttr) == S_OK) - fInheritsIEnum = TRUE; - - // If there is a vtable view of this interface (funky dispinterface). - // @FUTURE: what would be really nice here would be an alias mechanism, so that we could - // just point this dispinterface to that other interface, in those situations that it - // is dual. OTOH, that is probably pretty rare, because if that other interface - // were dual, why would the dispinterface even be needed? - if (pITI->GetRefTypeOfImplType(-1, &href) == S_OK) - { - IfFailGo(pITI->GetRefTypeInfo(href, &pITIBase)); - IfFailGo(pITIBase->GetTypeAttr(&psAttrBase)); - IfFailGo(_ConvIfaceMembers(pITIBase, psAttrBase, bVtblGapFuncs, TRUE, fInheritsIEnum)); - pITIBase->ReleaseTypeAttr(psAttrBase); - psAttrBase = 0; - pITIBase->Release(); - pITIBase = 0; - goto ErrExit; - } - - // If not processing an implemented interface, mark the interface type. - if (m_ImplIface == eImplIfaceNone) - { - // If this interface has a NewEnum member then have it implement IEnumerable. - if ((S_OK == HasNewEnumMember(pITI)) && !fInheritsIEnum) - { - mdToken tkImpl[2] = {0,0}; - IfFailGo(GetKnownTypeToken(VT_SLOT_FOR_IENUMERABLE, &tkImpl[0])); - IfFailGo(m_pEmit->SetTypeDefProps(m_tdTypeDef, ULONG_MAX, ULONG_MAX, tkImpl)); - } - - // Note that this is a dispinterface. - DECLARE_CUSTOM_ATTRIBUTE(sizeof(short)); - // Set up the attribute. - BUILD_CUSTOM_ATTRIBUTE(short, ifDispatch); - // Store the attribute - IfFailGo(GetAttrType(ATTR_INTERFACETYPE, &mr)); - FINISH_CUSTOM_ATTRIBUTE(); - IfFailGo(m_pEmit->DefineCustomAttribute(m_tdTypeDef, mr, PTROF_CUSTOM_ATTRIBUTE(), SIZEOF_CUSTOM_ATTRIBUTE(), 0)); - } - - IfFailGo(_ConvDispatchMembers(pITI, psAttr, fInheritsIEnum)); - -ErrExit: - if (psAttrBase) - pITIBase->ReleaseTypeAttr(psAttrBase); - if (pITIBase) - pITIBase->Release(); - return (hr); -} // HRESULT CImportTlb::ConvDispatch() - -//***************************************************************************** -// Determine if an interface is derived from IUnknown. -//***************************************************************************** -HRESULT CImportTlb::IsIUnknownDerived( - ITypeInfo *pITI, // The containing ITypeInfo. - TYPEATTR *psAttr) // The ITypeInfo's TYPEATTR -{ - HRESULT hr=S_OK; // A result. - - HREFTYPE href; // Base interface href. - ITypeInfo *pITIBase=0; // Base interface ITypeInfo. - TYPEATTR *psAttrBase=0; // TYPEATTR of base interface. - - // This should never be called on CoClasses. - _ASSERTE(psAttr->typekind != TKIND_COCLASS); - - // If IDispatch or IUnknown, we've recursed far enough. - if (IsEqualGUID(psAttr->guid, IID_IUnknown) || IsEqualGUID(psAttr->guid, IID_IDispatch)) - { - goto ErrExit; - } - - // Handle base interface. - if (psAttr->cImplTypes == 1) - { - IfFailGo(pITI->GetRefTypeOfImplType(0, &href)); - IfFailGo(pITI->GetRefTypeInfo(href, &pITIBase)); - IfFailGo(pITIBase->GetTypeAttr(&psAttrBase)); - - // IUnknow derived if base interface is. - hr = IsIUnknownDerived(pITIBase, psAttrBase); - pITIBase->ReleaseTypeAttr(psAttrBase); - psAttrBase = 0; - pITIBase->Release(); - pITIBase = 0; - } - else - { // No base interface, not IUnknown, not IDispatch. Not very COM-ish, so don't try to handle. - hr = S_FALSE; - } - -ErrExit: - if (psAttrBase) - pITIBase->ReleaseTypeAttr(psAttrBase); - if (pITIBase) - pITIBase->Release(); - return (hr); -} // HRESULT CImportTlb::IsIUnknownDerived() - -//***************************************************************************** -// Determine if an interface is derived from IDispatch. Note that a pure -// dispinterface doesn't derive from IDispatch. -//***************************************************************************** -HRESULT CImportTlb::IsIDispatchDerived( - ITypeInfo *pITI, // The containing ITypeInfo. - TYPEATTR *psAttr) // The ITypeInfo's TYPEATTR -{ - HRESULT hr=S_OK; // A result. - - HREFTYPE href; // Base interface href. - ITypeInfo *pITIBase=0; // Base interface ITypeInfo. - TYPEATTR *psAttrBase=0; // TYPEATTR of base interface. - - // If IDispatch, we've recursed far enough. - if (IsEqualGUID(psAttr->guid, IID_IDispatch)) - { - goto ErrExit; - } - - if (psAttr->typekind == TKIND_DISPATCH) - { - IfFailGo(pITI->GetRefTypeOfImplType(-1, &href)); - IfFailGo(pITI->GetRefTypeInfo(href, &pITIBase)); - IfFailGo(pITIBase->GetTypeAttr(&psAttrBase)); - - // IDispatch derived if base interface is. - hr = IsIDispatchDerived(pITIBase, psAttrBase); - pITIBase->ReleaseTypeAttr(psAttrBase); - psAttrBase = 0; - pITIBase->Release(); - pITIBase = 0; - - goto ErrExit; - } - - // Handle base interface. - if (psAttr->cImplTypes == 1) - { - IfFailGo(pITI->GetRefTypeOfImplType(0, &href)); - IfFailGo(pITI->GetRefTypeInfo(href, &pITIBase)); - IfFailGo(pITIBase->GetTypeAttr(&psAttrBase)); - - // IDispatch derived if base interface is. - hr = IsIDispatchDerived(pITIBase, psAttrBase); - pITIBase->ReleaseTypeAttr(psAttrBase); - psAttrBase = 0; - pITIBase->Release(); - pITIBase = 0; - } - else - { // No base interface, not IDispatch. Done. - hr = S_FALSE; - } - -ErrExit: - if (psAttrBase) - pITIBase->ReleaseTypeAttr(psAttrBase); - if (pITIBase) - pITIBase->Release(); - return (hr); -} // HRESULT CImportTlb::IsIDispatchDerived() - -//***************************************************************************** -// Determine if an interface has a member with a DISPID of DISPID_NEWENUM. -//***************************************************************************** -HRESULT CImportTlb::HasNewEnumMember( // S_OK if has NewEnum, S_FALSE otherwise. - ITypeInfo *pItfTI) // The interface in question. -{ - HRESULT hr = S_OK; // A result. - BOOL bHasNewEnumMember=FALSE;// If true, has a NewEnum - TYPEATTR *pAttr = NULL; // A TypeInfo's typeattr - FUNCDESC *pFuncDesc = NULL; // A Function's FuncDesc - VARDESC *pVarDesc = NULL; // A properties VarDesc - int i; // Loop control. - ITypeInfo *pITISelf2=0; // Partner interface. - HREFTYPE href; // HREF of partner. - WCHAR IEnumCA[] = W("{CD2BC5C9-F452-4326-B714-F9C539D4DA58}"); - - - // If there is a partner interface, prefer it. - if (pItfTI->GetRefTypeOfImplType(-1, &href) == S_OK) - { - IfFailGo(pItfTI->GetRefTypeInfo(href, &pITISelf2)); - pItfTI = pITISelf2; - } - - // Retrieve the attributes of the interface. - IfFailGo(pItfTI->GetTypeAttr(&pAttr)); - - if ((pAttr->typekind == TKIND_DISPATCH) || ((pAttr->typekind == TKIND_INTERFACE) && (IsIDispatchDerived(pItfTI, pAttr) == S_OK))) - { - // Check to see if the ForceIEnumerable custom value exists on the type - _ForceIEnumerableCVExists(pItfTI, &bHasNewEnumMember); - - // Check to see if the interface has a function with a DISPID of DISPID_NEWENUM. - for (i = 0; i < pAttr->cFuncs; i++) - { - IfFailGo(TryGetFuncDesc(pItfTI, i, &pFuncDesc)); - - if (FuncIsNewEnum(pItfTI, pFuncDesc, i) == S_OK) - { - // Throw a warning if we find more than one func with DISPID_NEWENUM. - if (bHasNewEnumMember == TRUE) - { - BSTR ObjectName; - pItfTI->GetDocumentation(-1, &ObjectName, NULL, NULL, NULL); - ReportEvent(NOTIF_CONVERTWARNING, TLBX_E_INVALID_TYPEINFO, ObjectName); - SysFreeString(ObjectName); - } - - // The interface has a function with a DISPID of DISPID_NEWENUM. - bHasNewEnumMember = TRUE; - break; - } - - pItfTI->ReleaseFuncDesc(pFuncDesc); - pFuncDesc = NULL; - } - - // Check to see if the interface as a property with a DISPID of DISPID_NEWENUM. - for (i = 0; i < pAttr->cVars; i++) - { - IfFailGo(pItfTI->GetVarDesc(i, &pVarDesc)); - - if (PropertyIsNewEnum(pItfTI, pVarDesc, i) == S_OK) - { - // Throw a warning if we find more than one func with DISPID_NEWENUM. - if (bHasNewEnumMember == TRUE) - { - BSTR ObjectName; - pItfTI->GetDocumentation(-1, &ObjectName, NULL, NULL, NULL); - ReportEvent(NOTIF_CONVERTWARNING, TLBX_E_INVALID_TYPEINFO, ObjectName); - SysFreeString(ObjectName); - } - - // The interface has a property with a DISPID of DISPID_NEWENUM. - bHasNewEnumMember = TRUE; - break; - } - - pItfTI->ReleaseVarDesc(pVarDesc); - pVarDesc = NULL; - } - } - else - { - // Check to see if the ForceIEnumerable custom value exists on the type - // If it does, spit out a warning. - _ForceIEnumerableCVExists(pItfTI, &bHasNewEnumMember); - - if (bHasNewEnumMember) - { - // Invalid custom attribute on the iface. - BSTR CustomValue = SysAllocString((const WCHAR*)&IEnumCA[0]); - BSTR ObjectName; - pItfTI->GetDocumentation(-1, &ObjectName, NULL, NULL, NULL); - - ReportEvent(NOTIF_CONVERTWARNING, TLBX_W_IENUM_CA_ON_IUNK, CustomValue, ObjectName); - - SysFreeString(CustomValue); - SysFreeString(ObjectName); - - bHasNewEnumMember = FALSE; - } - } - - hr = bHasNewEnumMember ? S_OK : S_FALSE; - -ErrExit: - if (pAttr) - pItfTI->ReleaseTypeAttr(pAttr); - if (pFuncDesc) - pItfTI->ReleaseFuncDesc(pFuncDesc); - if (pVarDesc) - pItfTI->ReleaseVarDesc(pVarDesc); - if (pITISelf2) - pITISelf2->Release(); - return hr; -} // HRESULT CImportTlb::HasNewEnumMember(ITypeInfo *pItfTI) - -//***************************************************************************** -// Determine if a given function is a valid NewEnum member. -//***************************************************************************** -HRESULT CImportTlb::FuncIsNewEnum( // S_OK if the function is the NewEnum member S_FALSE otherwise. - ITypeInfo *pITI, // The ITypeInfo that contains the function. - FUNCDESC *pFuncDesc, // The function in question. - DWORD index) // The function index -{ - - HRESULT hr = S_OK; - BOOL bIsValidNewEnum = FALSE; - TYPEDESC* pType = NULL; - TYPEATTR* pAttr = NULL; - ITypeInfo* pITIUD = NULL; - long lDispSet = 0; - - _GetDispIDCA(pITI, index, &lDispSet, TRUE); - - if ((pFuncDesc->memid == DISPID_NEWENUM) || (lDispSet == DISPID_NEWENUM)) - { - if (pFuncDesc->funckind == FUNC_DISPATCH) - { - if ((pFuncDesc->invkind == INVOKE_PROPERTYGET) || (pFuncDesc->invkind == INVOKE_FUNC)) - { - if (pFuncDesc->cParams == 0) - { - pType = &pFuncDesc->elemdescFunc.tdesc; - } - else if ((m_bTransformDispRetVals) && (pFuncDesc->cParams == 1) && (pFuncDesc->lprgelemdescParam[0].paramdesc.wParamFlags & PARAMFLAG_FRETVAL)) - { - pType = pFuncDesc->lprgelemdescParam[0].tdesc.lptdesc; - } - } - } - else if (pFuncDesc->funckind == FUNC_PUREVIRTUAL) - { - if ((pFuncDesc->cParams == 1) && - ((pFuncDesc->invkind == INVOKE_PROPERTYGET) || (pFuncDesc->invkind == INVOKE_FUNC)) && - (pFuncDesc->lprgelemdescParam[0].paramdesc.wParamFlags & PARAMFLAG_FRETVAL) && - (pFuncDesc->lprgelemdescParam[0].tdesc.vt == VT_PTR)) - { - pType = pFuncDesc->lprgelemdescParam[0].tdesc.lptdesc; - } - } - - if (pType) - { - if (pType->vt == VT_UNKNOWN || pType->vt == VT_DISPATCH) - { - // The member returns an IUnknown * or an IDispatch * which is valid. - bIsValidNewEnum = TRUE; - } - else if (pType->vt == VT_PTR) - { - pType = pType->lptdesc; - if (pType->vt == VT_USERDEFINED) - { - IfFailGo(pITI->GetRefTypeInfo(pType->hreftype, &pITIUD)); - IfFailGo(pITIUD->GetTypeAttr(&pAttr)); - if (IsEqualGUID(pAttr->guid, IID_IEnumVARIANT) || - IsEqualGUID(pAttr->guid, IID_IUnknown) || - IsEqualGUID(pAttr->guid, IID_IDispatch)) - { - // The member returns a valid interface type for a NewEnum member. - bIsValidNewEnum = TRUE; - } - } - } - } - } - -ErrExit: - if (pAttr) - pITIUD->ReleaseTypeAttr(pAttr); - if (pITIUD) - pITIUD->Release(); - - if (FAILED(hr)) - return hr; - else - return bIsValidNewEnum ? S_OK : S_FALSE; -} // HRESULT CImportTlb::FuncIsNewEnum(FUNCDESC *pFuncDesc) - -//***************************************************************************** -// Determine if a given function is a valid NewEnum member. -//***************************************************************************** -HRESULT CImportTlb::PropertyIsNewEnum( // S_OK if the function is the NewEnum member S_FALSE otherwise. - ITypeInfo *pITI, // The ITypeInfo that contains the property. - VARDESC *pVarDesc, // The function in question. - DWORD index) // The property index. -{ - HRESULT hr = S_OK; - BOOL bIsValidNewEnum = FALSE; - TYPEDESC* pType = NULL; - TYPEATTR* pAttr = NULL; - ITypeInfo* pITIUD = NULL; - long lDispSet = 0; - - _GetDispIDCA(pITI, index, &lDispSet, FALSE); - - if ( ((pVarDesc->memid == DISPID_NEWENUM) || (lDispSet == DISPID_NEWENUM)) && - (pVarDesc->elemdescVar.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) && - (pVarDesc->wVarFlags & VARFLAG_FREADONLY)) - { - pType = &pVarDesc->elemdescVar.tdesc; - if (pType->vt == VT_UNKNOWN || pType->vt == VT_DISPATCH) - { - // The member returns an IUnknown * or an IDispatch * which is valid. - bIsValidNewEnum = TRUE; - } - else if (pType->vt == VT_PTR) - { - pType = pType->lptdesc; - if (pType->vt == VT_USERDEFINED) - { - IfFailGo(pITI->GetRefTypeInfo(pType->hreftype, &pITIUD)); - IfFailGo(pITIUD->GetTypeAttr(&pAttr)); - if (IsEqualGUID(pAttr->guid, IID_IEnumVARIANT) || - IsEqualGUID(pAttr->guid, IID_IUnknown) || - IsEqualGUID(pAttr->guid, IID_IDispatch)) - { - // The member returns a valid interface type for a NewEnum member. - bIsValidNewEnum = TRUE; - } - } - } - } - -ErrExit: - if (pAttr) - pITIUD->ReleaseTypeAttr(pAttr); - if (pITIUD) - pITIUD->Release(); - - if (FAILED(hr)) - return hr; - else - return bIsValidNewEnum ? S_OK : S_FALSE; -} // HRESULT CImportTlb::FuncIsNewEnum(FUNCDESC *pFuncDesc) - -//***************************************************************************** -// Determine is a TypeInfo has any object fields. -//***************************************************************************** -HRESULT CImportTlb::HasObjectFields( // S_OK, S_FALSE, or error. - ITypeInfo *pITI, // The TypeInfo in question. - TYPEATTR *psAttr) // Attributes of the typeinfo. -{ - HRESULT hr; // A result. - - int i; // Loop control. - VARDESC *psVar=0; // VARDESC for a member. - - // Iterate over the vars. - for (i=0; i<psAttr->cVars; ++i) - { - // Get variable information. - IfFailGo(pITI->GetVarDesc(i, &psVar)); - - // See if it is an object type. - IfFailGo(IsObjectType(pITI, &psVar->elemdescVar.tdesc)); - // If result is S_FALSE, not an Object; keep looking. - if (hr == S_OK) - goto ErrExit; - - // Release for next var. - pITI->ReleaseVarDesc(psVar); - psVar = 0; - } - - hr = S_FALSE; - -ErrExit: - if (psVar) - pITI->ReleaseVarDesc(psVar); - return hr; -} // HRESULT CImportTlb::HasObjectFields() - -//***************************************************************************** -// Is a given type an Object type? -//***************************************************************************** -HRESULT CImportTlb::IsObjectType( // S_OK, S_FALSE, or error. - ITypeInfo *pITI, // The TypeInfo in question. - const TYPEDESC *pType) // The type. -{ - HRESULT hr; // A result. - TYPEDESC tdTemp; // Copy of TYPEDESC, for R/W. - ITypeInfo *pITIAlias=0; // Typeinfo of the aliased type. - TYPEATTR *psAttrAlias=0; // TYPEATTR of the aliased typeinfo. - int bObjectField=false; // The question to be answered. - int iByRef=0; // Indirection. - - // Strip off leading VT_PTR and VT_BYREF - while (pType->vt == VT_PTR) - pType = pType->lptdesc, ++iByRef; - if (pType->vt & VT_BYREF) - { - tdTemp = *pType; - tdTemp.vt &= ~VT_BYREF; - pType = &tdTemp; - ++iByRef; - } - - // Determine if the field is/has object type. - switch (pType->vt) - { - case VT_PTR: - _ASSERTE(!"Should not have VT_PTR here"); - break; - - // These are object types. - case VT_BSTR: - case VT_DISPATCH: - case VT_VARIANT: - case VT_UNKNOWN: - case VT_SAFEARRAY: - case VT_LPSTR: - case VT_LPWSTR: - bObjectField = true; - break; - - // A user-defined may or may not be/contain Object type. - case VT_USERDEFINED: - // User defined type. Get the TypeInfo. - IfFailGo(pITI->GetRefTypeInfo(pType->hreftype, &pITIAlias)); - IfFailGo(pITIAlias->GetTypeAttr(&psAttrAlias)); - - // Some user defined class. Is it a value class, or a VOS class? - switch (psAttrAlias->typekind) - { - // Alias -- Is the aliased thing an Object type? - case TKIND_ALIAS: - hr = IsObjectType(pITIAlias, &psAttrAlias->tdescAlias); - goto ErrExit; - // Record/Enum/Union -- Does it contain an Object type? - case TKIND_RECORD: - case TKIND_ENUM: - case TKIND_UNION: - // Byref/Ptrto record is Object. Contained record might be. - if (iByRef) - bObjectField = true; - else - { - hr = HasObjectFields(pITIAlias, psAttrAlias); - goto ErrExit; - } - break; - // Class/Interface -- An Object Type. - case TKIND_INTERFACE: - case TKIND_DISPATCH: - case TKIND_COCLASS: - bObjectField = true; - break; - default: - //case TKIND_MODULE: -- can't pass one of these as a parameter. - _ASSERTE(!"Unexpected typekind for user defined type"); - bObjectField = true; - } // switch (psAttrAlias->typekind) - break; - - case VT_CY: - case VT_DATE: - case VT_DECIMAL: - // Pointer to the value type is an object. Contained one isn't. - if (iByRef) - bObjectField = true; - else - bObjectField = false; - break; - - // A fixed array is an Object type. - case VT_CARRAY: - bObjectField = true; - break; - - // Other types I4, etc., are not Object types. - default: - bObjectField = false; - break; - } // switch (vt=pType->vt) - - - hr = bObjectField ? S_OK : S_FALSE; - -ErrExit: - if (psAttrAlias) - pITIAlias->ReleaseTypeAttr(psAttrAlias); - if (pITIAlias) - pITIAlias->Release(); - - return hr; -} // HRESULT CImportTlb::IsObjectType() - -//***************************************************************************** -// Convert the functions on an interface. Convert the functions on the -// base interface first, because in COM Classic, parent's functions are also -// in the derived interface's vtable. -//***************************************************************************** -HRESULT CImportTlb::_ConvIfaceMembers( - ITypeInfo *pITI, // The containing ITypeInfo. - TYPEATTR *psAttr, // The ITypeInfo's TYPEATTR - BOOL bVtblGapFuncs, // Add functions for vtblGaps? - BOOL bAddDispIds, // Add DispIds to the member? - BOOL bInheritsIEnum) // Inherits from IEnumerable. -{ - HRESULT hr=S_OK; // A result. - int i; // Loop control. - FUNCDESC *psFunc=0; // FUNCDESC for a member. - - HREFTYPE href; // Base interface href. - ITypeInfo *pITIBase=0; // Base interface ITypeInfo. - TYPEATTR *psAttrBase=0; // TYPEATTR of base interface. - BOOL bConversionLoss=false; // If true, some attributes were lost on conversion. - - _ASSERTE( (psAttr->typekind == TKIND_INTERFACE) || (psAttr->typekind == TKIND_DISPATCH) ); - - // If IDispatch or IUnknown, we've recursed far enough. - if (IsEqualGUID(psAttr->guid, IID_IUnknown) || IsEqualGUID(psAttr->guid, IID_IDispatch)) - { - if (m_cbVtableSlot == 0) - { - m_cbVtableSlot = psAttr->cbSizeInstance; - } - m_Slot = (psAttr->cbSizeVft / m_cbVtableSlot); - goto ErrExit; - } - - // Handle base interface. - if (psAttr->cImplTypes == 1) - { - IfFailGo(pITI->GetRefTypeOfImplType(0, &href)); - IfFailGo(pITI->GetRefTypeInfo(href, &pITIBase)); - IfFailGo(pITIBase->GetTypeAttr(&psAttrBase)); - - IfFailGo(_ConvIfaceMembers(pITIBase, psAttrBase, bVtblGapFuncs, bAddDispIds, bInheritsIEnum)); - - pITIBase->ReleaseTypeAttr(psAttrBase); - psAttrBase = 0; - pITIBase->Release(); - pITIBase = 0; - } - else - { // No base interface, not IUnknown, not IDispatch. We shouldn't be here. - m_Slot = 0; - if (m_cbVtableSlot == 0) - { - m_cbVtableSlot = psAttr->cbSizeInstance; - } - _ASSERTE(!"Interface does not derive from IUnknown."); - } - - // Loop over functions. - IfFailGo(_FindFirstUserMethod(pITI, psAttr, &i)); - IfFailGo(BuildMemberList(pITI, i, psAttr->cFuncs, bInheritsIEnum)); - - BOOL bAllowIEnum = !bInheritsIEnum; - for (i=0; i<(int)m_MemberList.Size(); ++i) - { - // Convert the function. - IfFailGo(_ConvFunction(pITI, &m_MemberList[i], bVtblGapFuncs, bAddDispIds, FALSE, &bAllowIEnum)); - if (hr == S_CONVERSION_LOSS) - bConversionLoss = true; - } - - // Add the property info. - IfFailGo(_ConvPropertiesForFunctions(pITI, psAttr)); - - if (bConversionLoss) - hr = S_CONVERSION_LOSS; - -ErrExit: - // Release FuncDescs. - FreeMemberList(pITI); - - if (psAttrBase) - pITIBase->ReleaseTypeAttr(psAttrBase); - if (pITIBase) - pITIBase->Release(); - if (psFunc) - pITI->ReleaseFuncDesc(psFunc); - return (hr); -} // HRESULT CImportTlb::_ConvIfaceMembers() - -//***************************************************************************** -// Convert the functions on a source interface to add_ and remove_ method. -// Convert the functions on the base interface first, because in COM Classic, -// parent's functions are also in the derived interface's vtable. -//***************************************************************************** -HRESULT CImportTlb::_ConvSrcIfaceMembers( - ITypeInfo *pITI, // The containing ITypeInfo. - TYPEATTR *psAttr, // The ITypeInfo's TYPEATTR - BOOL fInheritsIEnum) -{ - HRESULT hr=S_OK; // A result. - int i; // Loop control. - FUNCDESC *psFunc=0; // FUNCDESC for a member. - HREFTYPE href; // Base interface href. - ITypeInfo *pITIBase=0; // Base interface ITypeInfo. - TYPEATTR *psAttrBase=0; // TYPEATTR of base interface. - BOOL bConversionLoss=false; // If true, some attributes were lost on conversion. - - _ASSERTE( (psAttr->typekind == TKIND_INTERFACE) || (psAttr->typekind == TKIND_DISPATCH) ); - - // If IDispatch or IUnknown, we've recursed far enough. - if (IsEqualGUID(psAttr->guid, IID_IUnknown) || IsEqualGUID(psAttr->guid, IID_IDispatch)) - { - if (m_cbVtableSlot == 0) - { - m_cbVtableSlot = psAttr->cbSizeInstance; - } - m_Slot = (psAttr->cbSizeVft / m_cbVtableSlot); - goto ErrExit; - } - - // Handle base interface. - if (psAttr->cImplTypes == 1) - { - IfFailGo(pITI->GetRefTypeOfImplType(0, &href)); - IfFailGo(pITI->GetRefTypeInfo(href, &pITIBase)); - IfFailGo(pITIBase->GetTypeAttr(&psAttrBase)); - - IfFailGo(_ConvSrcIfaceMembers(pITIBase, psAttrBase, fInheritsIEnum)); - pITIBase->ReleaseTypeAttr(psAttrBase); - psAttrBase = 0; - pITIBase->Release(); - pITIBase = 0; - } - else - { // No base interface, not IUnknown, not IDispatch. We shouldn't be here. - m_Slot = 0; - if (m_cbVtableSlot == 0) - { - m_cbVtableSlot = psAttr->cbSizeInstance; - } - _ASSERTE(!"Interface does not derive from IUnknown."); - } - - // Loop over functions. - IfFailGo(_FindFirstUserMethod(pITI, psAttr, &i)); - IfFailGo(BuildMemberList(pITI, i, psAttr->cFuncs, fInheritsIEnum)); - - // If we have any properties, we want to skip them. Should we add gaps? - if (m_cMemberProps != 0) - { - ReportEvent(NOTIF_CONVERTWARNING, TLBX_W_NO_PROPS_IN_EVENTS, m_szName); - bConversionLoss = true; - } - - for (i = m_cMemberProps; i<(int)m_MemberList.Size(); ++i) - { - // Convert the function. - IfFailGo(_GenerateEvent(pITI, &m_MemberList[i], fInheritsIEnum)); - if (hr == S_CONVERSION_LOSS) - bConversionLoss = true; - } - - if (bConversionLoss) - hr = S_CONVERSION_LOSS; - -ErrExit: - // Release FuncDescs. - FreeMemberList(pITI); - - if (psAttrBase) - pITIBase->ReleaseTypeAttr(psAttrBase); - if (pITIBase) - pITIBase->Release(); - if (psFunc) - pITI->ReleaseFuncDesc(psFunc); - return (hr); -} // HRESULT CImportTlb::_ConvIfaceMembers() - -//***************************************************************************** -// Add the property definitions for property functions. -//***************************************************************************** -HRESULT CImportTlb::_ConvPropertiesForFunctions( - ITypeInfo *pITI, // ITypeInfo* being converted. - TYPEATTR *psAttr) // TypeAttr for the typeinfo. -{ - HRESULT hr=S_OK; // A result. - int ix; // Loop control. - int ix2; // More loop control. - mdProperty pd; // A property token. - USHORT ms; // Some method's semantics. - mdToken tk; // A method's token. - mdMethodDef mdFuncs[6] ={0}; // Array of setter, getter, other. - FUNCDESC *psF=0; // FUNCDESC of Get, Put, or PutRef. - TYPEDESC *pProperty; // TYPEDESC of property type. - BOOL bPropRetval; // Is the property type a [retval]? - ULONG ixValue; // Index of the value parameter for putters. - int ixVarArg; // Index of vararg param, if any. - CQuickBytes qbComSig; // new signature - BYTE *pbSig; // Pointer into the signature. - ULONG sigFlags; // Signature handling flags. - ULONG cbTotal; // Size of the signature. - ULONG cb; // Size of a signature element. - LPWSTR pszName; // Possibly decorated name of property. - CQuickArray<WCHAR> qbName; // Buffer for name decoration. - int iSrcParam; // Param count, as looping through params. - int cDestParams; // Count of destination params. - CQuickArray<BYTE> qbDummyNativeTypeBuf; // A dummy native type array. - ULONG iNativeOfs=0; // Current offset in native type buffer. - BOOL bNewEnumMember=FALSE; // Is this a NewEnum property? - BOOL bConversionLoss=FALSE; // Was some type not fully converted? - int cFound; // Functions found matching a given property. - - // Using semantics as an index, so be sure array is big enough. - _ASSERTE(lengthof(mdFuncs) > msOther); - - for (ix=m_cMemberProps; ix<(int)m_MemberList.Size(); ++ix) - { // See if this one needs to be processed. - if (m_MemberList[ix].m_mdFunc == 0) - continue; - - MemberInfo *pMember = &m_MemberList[ix]; - pMember->GetFuncInfo(tk, ms); - - // Get the name. - if (m_szMember) - ::SysFreeString(m_szMember), m_szMember = 0; - IfFailGo(pITI->GetDocumentation(pMember->m_psFunc->memid, &m_szMember, 0,0,0)); - - // Found one. Put in the right slot. - _ASSERTE(ms == msGetter || ms == msSetter || ms==msOther); - mdFuncs[msSetter] = mdFuncs[msGetter] = mdFuncs[msOther] = 0; - mdFuncs[ms] = tk; - pMember->m_mdFunc = 0; - - // Look for related functions. - cFound = 1; - for (ix2=ix+1; ix2<(int)m_MemberList.Size(); ++ix2) - { - MemberInfo *pMember2 = &m_MemberList[ix2]; - if (pMember2->m_mdFunc != 0 && pMember2->m_psFunc->memid == pMember->m_psFunc->memid) - { // Found a related function. - pMember2->GetFuncInfo(tk, ms); - _ASSERTE(ms == msGetter || ms == msSetter || ms==msOther); - _ASSERTE(mdFuncs[ms] == 0); - mdFuncs[ms] = tk; - pMember2->m_mdFunc = 0; - // If have found all three, don't bother looking for more. - if (++cFound == 3) - break; - } - } - - // Build the signature for the property. - hr = _GetFunctionPropertyInfo(pMember->m_psFunc, &ms, &psF, &pProperty, &bPropRetval, TRUE, m_szMember); - - // The function really should have a property associated with it, to get here. Check anyway. - _ASSERTE(pProperty); - if (!pProperty) - continue; - - // Some sort of property accessor. - IfFailGo(qbComSig.ReSizeNoThrow(CB_MAX_ELEMENT_TYPE + 1)); - pbSig = (BYTE *)qbComSig.Ptr(); - cbTotal = cb = CorSigCompressData((ULONG)IMAGE_CEE_CS_CALLCONV_PROPERTY, pbSig); - // Count of parameters. - - // If this is a getter, see if there is a retval. - if (psF->invkind == INVOKE_PROPERTYGET) - { // Examine each param, and count all except the [retval]. - for (cDestParams=iSrcParam=0; iSrcParam<psF->cParams; ++iSrcParam) - { - if ((psF->lprgelemdescParam[iSrcParam].paramdesc.wParamFlags & NON_CONVERTED_PARAMS_FLAGS) == 0) - ++cDestParams; - } - // There is no new value param for getters. - ixValue = -1; - } - else - { - // This is a putter, so 1 param is new value, others are indices (or lcid). - for (cDestParams=iSrcParam=0; iSrcParam<psF->cParams-1; ++iSrcParam) - { - if ((psF->lprgelemdescParam[iSrcParam].paramdesc.wParamFlags & NON_CONVERTED_PARAMS_FLAGS) == 0) - ++cDestParams; - } - // The last parameter is the new value. - ixValue = psF->cParams - 1; - } - - //------------------------------------------------------------------------- - // See if there is a vararg param. - ixVarArg = psF->cParams + 1; - if (psF->cParamsOpt == -1) - { - // If this is a PROPERTYPUT or PROPERTYPUTREF, skip the last non-retval parameter (it - // is the new value to be set). - BOOL bPropVal = (psF->invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF)) ? TRUE : FALSE; - // Find the vararg param. - for (iSrcParam=psF->cParams-1; iSrcParam>=0; --iSrcParam) - { - // The count of optional params does not include any lcid params, nor does - // it include the return value, so skip those. - if ((psF->lprgelemdescParam[iSrcParam].paramdesc.wParamFlags & (PARAMFLAG_FRETVAL|PARAMFLAG_FLCID)) != 0) - continue; - // If haven't yet seen the property value, this param is it, so skip it, too. - if (bPropVal) - { - bPropVal = FALSE; - continue; - } - ixVarArg = iSrcParam; - break; - } // for (iSrcParam=cParams-1... - } - - // Put in the count of index parameters. - _ASSERTE(cDestParams >= 0); - cb = CorSigCompressData(cDestParams, &pbSig[cbTotal]); - cbTotal += cb; - - // Create the signature for the property type. - sigFlags = SIG_ELEM | (bPropRetval ? SIG_RET : (SigFlags)0); - IfFailGo(_ConvSignature(pITI, pProperty, sigFlags, qbComSig, cbTotal, &cbTotal, qbDummyNativeTypeBuf, 0, &iNativeOfs, bNewEnumMember)); - if (hr == S_CONVERSION_LOSS) - bConversionLoss = true; - - // Fill in the "index" part of the property's signature. - for (iSrcParam=0; iSrcParam<psF->cParams; ++iSrcParam) - { - if (psF->lprgelemdescParam[iSrcParam].paramdesc.wParamFlags & NON_CONVERTED_PARAMS_FLAGS) - continue; - if (iSrcParam == static_cast<int>(ixValue)) - continue; - sigFlags = SIG_FUNC | SIG_USE_BYREF; - if (iSrcParam == ixVarArg) - sigFlags |= SIG_VARARG; - IfFailGo(_ConvSignature(pITI, &psF->lprgelemdescParam[iSrcParam].tdesc, sigFlags, qbComSig, cbTotal, &cbTotal, qbDummyNativeTypeBuf, 0, &iNativeOfs, bNewEnumMember)); - if (hr == S_CONVERSION_LOSS) - bConversionLoss = true; - } - - // Get the property name. Add interface name and make unique, if needed. - // m_szInterface should be non-null if processing an implemented interface; should be null otherwise. - _ASSERTE(m_ImplIface == eImplIfaceNone || m_szInterface != 0); - IfFailGo(qbName.ReSizeNoThrow(wcslen(m_szMember)+2)); - wcscpy_s(qbName.Ptr(), wcslen(m_szMember)+2, m_szMember); - IfFailGo(GenerateUniqueMemberName(qbName, (PCCOR_SIGNATURE)qbComSig.Ptr(), cbTotal, m_szInterface, mdtProperty)); - pszName = qbName.Ptr(); - - // Define the property. - IfFailGo(m_pEmit->DefineProperty(m_tdTypeDef, pszName, 0/*dwFlags*/, - (PCCOR_SIGNATURE) qbComSig.Ptr(), cbTotal, 0, 0, -1, - mdFuncs[msSetter], mdFuncs[msGetter], &mdFuncs[msOther], - &pd)); - - // Handle dispids for non-implemented interfaces, and for default interface - if (m_ImplIface != eImplIface) - { - // Set the dispid CA on the property. - long lDispSet = 1; - _SetDispIDCA(pITI, pMember->m_iMember, psF->memid, pd, TRUE, &lDispSet, TRUE); - - // If this property is default property, add a custom attribute to the class. - if (lDispSet == DISPID_VALUE) - IfFailGo(_AddDefaultMemberCa(m_tdTypeDef, m_szMember)); - } - - // Add the alias information if the type is an alias. - IfFailGo(_HandleAliasInfo(pITI, pProperty, pd)); - } - - if (bConversionLoss) - hr = S_CONVERSION_LOSS; - -ErrExit: - if (m_szMember) - ::SysFreeString(m_szMember), m_szMember=0; - - return hr; -} // HRESULT CImportTlb::_ConvPropertiesForFunctions() - -//***************************************************************************** -// Convert the vars and functions of a dispinterface. Vars actually turn -// into a getter and possibly a setter. -//***************************************************************************** -HRESULT CImportTlb::_ConvDispatchMembers( - ITypeInfo *pITI, // ITypeInfo* to convert. - TYPEATTR *psAttr, // TypeAttr of ITypeInfo. - BOOL fInheritsIEnum) -{ - HRESULT hr; // A result. - int i; // Loop control. - BOOL bConversionLoss=FALSE; // If true, some attributes were lost on conversion. - - IfFailGo(_FindFirstUserMethod(pITI, psAttr, &i)); - IfFailGo(BuildMemberList(pITI, i, psAttr->cFuncs, fInheritsIEnum)); - - // Dispatch members really have no slot. - m_Slot = 0; - - // Loop over properties. - for (i=0; i<m_cMemberProps; ++i) - { - IfFailGo(_ConvProperty(pITI, &m_MemberList[i])); - } - - // Loop over functions. - BOOL bAllowIEnum = !fInheritsIEnum; - for (; i<(int)m_MemberList.Size(); ++i) - { - // Get variable information. - IfFailGo(_ConvFunction(pITI, &m_MemberList[i], FALSE, TRUE, FALSE, &bAllowIEnum)); - if (hr == S_CONVERSION_LOSS) - bConversionLoss = TRUE; - } - - // Add the property info. - IfFailGo(_ConvPropertiesForFunctions(pITI, psAttr)); - - if (bConversionLoss) - hr = S_CONVERSION_LOSS; - -ErrExit: - // Free the func descs. - FreeMemberList(pITI); - - return (hr); -} // HRESULT CImportTlb::_ConvDispatchMembers() - -//***************************************************************************** -// Examine the functions on an interface, and skip the first 3 or first 7 -// if the functions are IUnknown or IDispatch members. -//***************************************************************************** -HRESULT CImportTlb::_FindFirstUserMethod( - ITypeInfo *pITI, // The Typedef to examine. - TYPEATTR *psAttr, // TYPEATTR for the typedef. - int *pIx) // Put index of first user function here. -{ - HRESULT hr = S_OK; // A result. - int i; // Loop control. - FUNCDESC *psFunc=0; // FUNCDESC for a member. - BSTR szName=0; // A function's name. - - // Note: this is a terrible workaround, but in some situations the methods from IUnknown / IDispatch will - // show up as though native dispatch functions. - i = 0; - if (psAttr->cFuncs >= 3) - { - IfFailGo(TryGetFuncDesc(pITI, i, &psFunc)); - if (psFunc->memid == 0x60000000 && - psFunc->elemdescFunc.tdesc.vt == VT_VOID && - psFunc->cParams == 2 && - psFunc->lprgelemdescParam[0].tdesc.vt == VT_PTR && // -> VT_USERDEFINED - psFunc->lprgelemdescParam[1].tdesc.vt == VT_PTR && // -> VT_PTR -> VT_VOID - SUCCEEDED(pITI->GetDocumentation(psFunc->memid, &szName, 0,0,0)) && - (wcscmp(szName, W("QueryInterface")) == 0) ) - i = 3; - pITI->ReleaseFuncDesc(psFunc); - psFunc=0; - if (szName) - ::SysFreeString(szName); - szName = 0; - if (psAttr->cFuncs >= 7) - { - IfFailGo(TryGetFuncDesc(pITI, i, &psFunc)); - if (psFunc->memid == 0x60010000 && - psFunc->elemdescFunc.tdesc.vt == VT_VOID && - psFunc->cParams == 1 && - psFunc->lprgelemdescParam[0].tdesc.vt == VT_PTR && // -> VT_UINT - SUCCEEDED(pITI->GetDocumentation(psFunc->memid, &szName, 0,0,0)) && - (wcscmp(szName, W("GetTypeInfoCount")) == 0) ) - i = 7; - pITI->ReleaseFuncDesc(psFunc); - psFunc=0; - if (szName) - ::SysFreeString(szName); - szName = 0; - } - } - - *pIx = i; - -ErrExit: - if (psFunc) - pITI->ReleaseFuncDesc(psFunc); - if (szName) - ::SysFreeString(szName); - return (hr); -} // HRESULT CImportTlb::_FindFirstUserMethod() - -//***************************************************************************** -// Given a FUNCDESC that is has INVOKE_PROPERTY* decoration, determine -// the role of the function, and the property signature type. -//***************************************************************************** -HRESULT CImportTlb::_GetFunctionPropertyInfo( - FUNCDESC *psFunc, // Function for which to get info. - USHORT *pSemantics, // Put appropriate semantics here. - FUNCDESC **ppSig, // Put FUNCDESC for signature here. - TYPEDESC **ppProperty, // Put TYPEDESC for return here. - BOOL *pbRetval, // If true, the type is [retval] - BOOL fUseLastParam, // If true, default to the last parameter as the return value - BSTR strName) // Name of the property -{ - FUNCDESC *psTmp; // FUNCDESC for some method. - FUNCDESC *psGet=0; // FUNCDESC for Get method defining a property. - FUNCDESC *psPut=0; // FUNCDESC for Put method defining a property. - FUNCDESC *psPutRef=0; // FUNCDESC for PutRef method defining a property. - FUNCDESC *psF; // A FUNCDESC. - TYPEDESC *pReturn=0; // The FUNCDESC's return type. - int cFound=0; // Count of functions found. - int i; // Loop control. - HRESULT hr = S_OK; - - if (psFunc->invkind & INVOKE_PROPERTYGET) - { // A "Get", so return type is property type. - *ppSig = psFunc; - *pSemantics = msGetter; - } - else - { - _ASSERTE(psFunc->invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF)); - // Search for the "best" method from which to grab the signature. We prefer the Get(), - // Followed by the Put(), followed by the PutRef() - // Also look for Put() and PutRef(), so we can - for (int iFunc=0; iFunc<(int)m_MemberList.Size() && cFound<3; ++iFunc) - { - // Get a FUNCDESC from the list. - psTmp = m_MemberList[iFunc].m_psFunc; - - // Is it for the same func? - if (psTmp->memid != psFunc->memid) - continue; - - // Is it the Get()? If so, it is the one we want. - if (psTmp->invkind & INVOKE_PROPERTYGET) - { - psGet = psTmp; - ++cFound; - continue; - } - - // Is it the Put()? Use it if we don't find a Get(). - if (psTmp->invkind & INVOKE_PROPERTYPUT) - { - psPut = psTmp; - ++cFound; - continue; - } - - // Is it the PutRef()? Keep track of it. - if (psTmp->invkind & INVOKE_PROPERTYPUTREF) - { - psPutRef = psTmp; - ++cFound; - } - } - // Get the best FUNCDESC for the signature. - *ppSig = psGet ? psGet : (psPut ? psPut : psFunc); - - // Determine whether this is a the "Set" or "VB specific Let" function. - if (psFunc->invkind & INVOKE_PROPERTYPUTREF) - { // This function is the PROPERTYPUTREF. Make it the setter. If - // there is also a PROPERTYPUT, it will be the "letter". - *pSemantics = msSetter; - } - else - { // We are looking at the PROPERTYPUT function (the "Let" function in native VB6.). - - // If there is also a PROPERTYPUTREF, make this the "VB Specific Let" function. - if (psPutRef) - { // A PPROPERTYPUTREF also exists, so make this the "Let" function. - *pSemantics = msOther; - } - else - { // There is no PROPERTYPUTREF, so make this the setter. - *pSemantics = msSetter; - } - } - } - - // Occasionally there is a property with no discernable type. In that case, lose the - // property on conversion. - - // Determine the type of the property, based on the "best" accessor. - psF = *ppSig; - *pbRetval = FALSE; - if (psF->invkind & INVOKE_PROPERTYGET) - { // look for [retval]. - for (i=psF->cParams-1; i>=0; --i) - { - if (psF->lprgelemdescParam[i].paramdesc.wParamFlags & PARAMFLAG_FRETVAL) - { // will consume a level of indirection (later). - *pbRetval = TRUE; - pReturn = &psF->lprgelemdescParam[i].tdesc; - break; - } - } - // If no [retval], check return type. - if (!pReturn && psF->elemdescFunc.tdesc.vt != VT_VOID && psF->elemdescFunc.tdesc.vt != VT_HRESULT) - pReturn = &psF->elemdescFunc.tdesc; - - if (fUseLastParam) - { - // We may have stripped the [retval] if this is a disp-only interface. Just use the last parameter. - if (!pReturn && (psF->cParams > 0)) - pReturn = &psF->lprgelemdescParam[psF->cParams-1].tdesc; - } - else - { - // If there is no type, don't try to set the getter. - if (pReturn && pReturn->vt == VT_VOID) - pReturn = NULL; - } - - if (!pReturn) - { - ReportEvent(NOTIF_CONVERTWARNING, TLBX_E_PROPGET_WITHOUT_RETURN, strName, m_szMngName); - } - } - else - { // Find lastmost param that isn't [retval]. (Should be the last param, but it is - // possible to write an IDL with a PROPERTYPUT that has a [retval]. - for (i=psF->cParams-1; i>=0; --i) - { - if ((psF->lprgelemdescParam[psF->cParams-1].paramdesc.wParamFlags & PARAMFLAG_FRETVAL) == 0) - { - { // First, and possibly only, param. - pReturn = &psF->lprgelemdescParam[i].tdesc; - break; - } - } - } - } - -//ErrExit: - if (pReturn == 0) - *pSemantics = 0; - *ppProperty = pReturn; - - return hr; -} // HRESULT CImportTlb::_GetFunctionPropertyInfo() - -//***************************************************************************** -// Convert a function description to metadata entries. -// -// This can be rather involved. If the function is a INVOKE_PROPERTY*, -// determine if it will be converted as a COM+ property, and if so, which -// of up to three functions will be selected to provide the property -// signature. -// The function return type is found by scaning the parameters looking for -// [retval]s. -//***************************************************************************** -#ifdef _PREFAST_ -#pragma warning(push) -#pragma warning(disable:21000) // Suppress PREFast warning about overly large function -#endif -HRESULT CImportTlb::_ConvFunction( - ITypeInfo *pITI, // Containing TypeInfo. - MemberInfo *pMember, // iNFO for the function. - BOOL bVtblGapFuncs, // Add functions for vtblGaps? - BOOL bAddDispIds, // Add DispIds to the member? - BOOL bDelegateInvokeMeth, // Convert function for a delegate invoke - BOOL* bAllowIEnum) // Allowed to change this function to GetEnumerator -{ - HRESULT hr; // A result. - int iSrcParam; // Param count, as looping through params. - int iDestParam; // Param count, as looping through params. - int cDestParams; // Count of destination params. - int ixOpt; // Index of first param that is optional due to cParamsOpt. - int ixVarArg; // Index of vararg param, if any. - mdMethodDef mdFunc; // Token of new member. - BSTR szTypeName=0; // Name of the type. - DWORD dwFlags=0; // Member flags. - DWORD dwImplFlags=0; // The impl flags. - WCHAR *pszName=0; // Possibly decorated name of member. - CQuickArray<WCHAR> qbName; // Buffer for decorated name. - TYPEDESC *pReturn=0; // Return type. - int bRetval=false; // Is the return result a [retval] parameter? - int ixRetval; // Which param is the [retval]? - TYPEDESC *pReturnRetval=0; // Return type from [retval] (incl. indirection). - WORD wRetFlags=0; // Return type flags. - ULONG offset=0; // Offset of function - BSTR *rszParamNames=0; // Parameter names. - UINT iNames; // Count of actual names. - CQuickBytes qbComSig; // new signature - BYTE *pbSig; // Pointer into the signature. - ULONG sigFlags; // Signature handling flags. - CQuickArray<BYTE> qbNativeBuf; // Native type buffer. - CQuickArray<BYTE> qbDummyNativeTypeBuf; // A dummy native type array. - CQuickArray<ULONG> qbNativeOfs; // Offset of native type for each param. - CQuickArray<ULONG> qbNativeLen; // Length of native type for each param. - ULONG iNativeOfs=0; // Current offset in native type buffer. - ULONG iNewNativeOfs=0; // New offset in native type buffer. - ULONG cb; // Size of an element. - ULONG cbTotal = 0; // Size of the signature. - int bOleCall=false; // Is the implementation OLE style?(HRESULT or IDispatch) - USHORT msSemantics=0; // Property's methodsemantics. - WCHAR szSpecial[40]; // To build name of special function. - mdToken tkAttr; // Token for custom attribute type. - BOOL bConversionLoss=false; // If true, some attributes were lost on conversion. - enum {ParamRetval=-1, ParamNone=-2}; - int iParamError=ParamNone; // Index of param with conversion error. - BOOL bNewEnumMember = FALSE; // A flag indicating if the member is the NewEnum member. - int iLCIDParam = -1; // Index of the LCID parameter. - FUNCDESC *psFunc = pMember->m_psFunc; - - // If we might insert vtable gaps, then we'd better have initialized the vtable slot size. - _ASSERTE(!bVtblGapFuncs || (m_cbVtableSlot != 0)); - - // Retrieve the member name from the member info. - IfNullGo(m_szMember = SysAllocString(bDelegateInvokeMeth ? DELEGATE_INVOKE_METH_NAME : pMember->m_pName)); - -#ifdef _DEBUG - LPWSTR funcName = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_TlbImpShouldBreakOnConvFunction); - if (funcName) - { - if (wcscmp(funcName, pMember->m_pName) == 0) - _ASSERTE(!"TlbImpBreakOnConvFunction"); - - delete [] funcName; - } -#endif //_DEBUG - - // Determine if the member is the new enum member. - if ((*bAllowIEnum)) - { - bNewEnumMember = FuncIsNewEnum(pITI, psFunc, pMember->m_iMember) == S_OK; - - // Once a method is converted in this interface, don't convert any more. - if (bNewEnumMember) - *bAllowIEnum = FALSE; - } - - - // We should NEVER have a new enum member when we are dealing with a delegate invoke meth. - if (bNewEnumMember && bDelegateInvokeMeth) - { - // Get the real name of the method - BSTR szTypeInfoName = NULL; - BSTR szMemberName = NULL; - hr = m_pITI->GetDocumentation(MEMBERID_NIL, &szTypeInfoName, 0, 0, 0); - if (FAILED(hr)) - szTypeInfoName = SysAllocString(W("???")); - - ReportEvent(NOTIF_CONVERTWARNING, TLBX_E_EVENT_WITH_NEWENUM, szTypeInfoName); - - SysFreeString(szMemberName); - SysFreeString(szTypeInfoName); - - IfFailGo(TLBX_E_EVENT_WITH_NEWENUM); - } - - // If there is a gap in the vtable, emit a special function. - if (bVtblGapFuncs) - { - if ((psFunc->oVft / m_cbVtableSlot) != m_Slot) - { - ULONG n = psFunc->oVft / m_cbVtableSlot; - // Make sure slot numbers are monotonically increasing. - if (n < m_Slot) - { - IfFailGo(pITI->GetDocumentation(MEMBERID_NIL, &szTypeName, 0, 0, 0)); - IfFailGo(PostError(TLBX_E_BAD_VTABLE, m_szMember, szTypeName, m_szLibrary)); - } - - n -= m_Slot; - if (n == 1) - _snwprintf_s(szSpecial, lengthof(szSpecial), lengthof(szSpecial) - 1, VTBL_GAP_FORMAT_1, VTBL_GAP_FUNCTION, m_Slot); - else - _snwprintf_s(szSpecial, lengthof(szSpecial), lengthof(szSpecial) - 1, VTBL_GAP_FORMAT_N, VTBL_GAP_FUNCTION, m_Slot, n); - IfFailGo(m_pEmit->DefineMethod(m_tdTypeDef, szSpecial, VTBL_GAP_FUNCTION_FLAGS, VTBL_GAP_SIGNATURE,sizeof(VTBL_GAP_SIGNATURE), - 0/* rva*/, VTBL_GAP_FUNC_IMPL_FLAGS, &mdFunc)); - m_Slot += n; - } - // What we will expect next time. - ++m_Slot; - } - - //------------------------------------------------------------------------- - // Determine the return type. - // If this is an hresult function, prepare to munge return, params. - if (psFunc->elemdescFunc.tdesc.vt == VT_HRESULT) - { - bOleCall = true; - } - else - { - if ((psFunc->elemdescFunc.tdesc.vt != VT_VOID) && (psFunc->elemdescFunc.tdesc.vt != VT_HRESULT)) - pReturn = &psFunc->elemdescFunc.tdesc; - } - - // Look for [RETVAL]. - for (iSrcParam=0; iSrcParam<psFunc->cParams; ++iSrcParam) - { - if (psFunc->lprgelemdescParam[iSrcParam].paramdesc.wParamFlags & PARAMFLAG_FRETVAL) - { - // If already have a return, or a DISPATCH function, error. - if (pReturn != 0) - { // Unexpected return found. - ReportEvent(NOTIF_CONVERTWARNING, TLBX_E_AMBIGUOUS_RETURN, m_szName, m_szMember); - IfFailGo(TLBX_E_AMBIGUOUS_RETURN); - } - else - { // Found a return type. - wRetFlags = psFunc->lprgelemdescParam[iSrcParam].paramdesc.wParamFlags; - pReturn = &psFunc->lprgelemdescParam[iSrcParam].tdesc; - bRetval = true; - ixRetval = iSrcParam; - } - break; - } - } - - // Check to see if there is an LCID parameter. - for (iSrcParam=0;iSrcParam<psFunc->cParams;iSrcParam++) - { - if (psFunc->lprgelemdescParam[iSrcParam].paramdesc.wParamFlags & PARAMFLAG_FLCID) - { - if (iLCIDParam != -1) - IfFailGo(PostError(TLBX_E_MULTIPLE_LCIDS, m_szName, m_szMember)); - iLCIDParam = iSrcParam; - } - } - - //------------------------------------------------------------------------- - // Size buffers to accomodate parameters. - // Resize the native type length array. - IfFailGo(qbNativeBuf.ReSizeNoThrow(1)); - IfFailGo(qbNativeLen.ReSizeNoThrow(psFunc->cParams + 1)); - IfFailGo(qbNativeOfs.ReSizeNoThrow(psFunc->cParams + 1)); - memset(qbNativeLen.Ptr(), 0, (psFunc->cParams + 1)*sizeof(int)); - memset(qbNativeOfs.Ptr(), 0, (psFunc->cParams + 1)*sizeof(int)); - - // resize to make room for calling convention and count of argument - IfFailGo(qbComSig.ReSizeNoThrow(CB_MAX_ELEMENT_TYPE + 1)); - pbSig = (BYTE *)qbComSig.Ptr(); - - //------------------------------------------------------------------------- - // Determine which params need to be marked optional, by virtue of cParamsOpt count. - if (psFunc->cParamsOpt == 0) - ixVarArg = ixOpt = psFunc->cParams + 1; - else - { - if (psFunc->cParamsOpt == -1) - { // Varargs. - ixVarArg = ixOpt = psFunc->cParams + 1; - // If this is a PROPERTYPUT or PROPERTYPUTREF, skip the last non-retval parameter (it - // is the new value to be set). - BOOL bPropVal = (psFunc->invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF)) ? TRUE : FALSE; - // Find the vararg param. - for (iSrcParam=psFunc->cParams-1; iSrcParam>=0; --iSrcParam) - { - // The count of optional params does not include any lcid params, nor does - // it include the return value, so skip those. - if ((psFunc->lprgelemdescParam[iSrcParam].paramdesc.wParamFlags & (PARAMFLAG_FRETVAL|PARAMFLAG_FLCID)) != 0) - continue; - // If haven't yet seen the property value, this param is it, so skip it, too. - if (bPropVal) - { - bPropVal = FALSE; - continue; - } - ixVarArg = iSrcParam; - break; - } // for (iSrcParam=cParams-1... - } - else - { // ixOpt will be index of first optional parameter. - short cOpt = psFunc->cParamsOpt; - ixOpt = 0; - ixVarArg = psFunc->cParams + 1; - for (iSrcParam=psFunc->cParams-1; iSrcParam>=0; --iSrcParam) - { - // The count of optional params does not include any lcid params, nor does - // it include the return value, so skip those. - if ((psFunc->lprgelemdescParam[iSrcParam].paramdesc.wParamFlags & (PARAMFLAG_FRETVAL|PARAMFLAG_FLCID)) == 0) - { - if (--cOpt == 0) - { - ixOpt = iSrcParam; - break; - } - } - } // for (iSrcParam=cParams-1... - } - } - - - //------------------------------------------------------------------------- - // Get the parameter names. - rszParamNames = reinterpret_cast<BSTR*>(_alloca((psFunc->cParams+1) * sizeof(BSTR*))); - - // Get list of names. - IfFailGo(pITI->GetNames(psFunc->memid, rszParamNames, psFunc->cParams+1, &iNames)); - - // zero name pointer for non-named params. - for (iSrcParam=iNames; iSrcParam<=psFunc->cParams; ++iSrcParam) - rszParamNames[iSrcParam] = 0; - - //------------------------------------------------------------------------- - // Convert the calling convention, param count, and return type. - cDestParams = psFunc->cParams; - if (bRetval) - --cDestParams; - if (iLCIDParam != -1) - --cDestParams; - - if (pReturn) - { - // Param count - cbTotal = cb = CorSigCompressData((ULONG)IMAGE_CEE_CS_CALLCONV_DEFAULT | IMAGE_CEE_CS_CALLCONV_HASTHIS, pbSig); - cb = CorSigCompressData(cDestParams, &(pbSig[cbTotal])); - cbTotal += cb; - // Return type or [retval]. - if (bRetval) - sigFlags = (SigFlags)(wRetFlags & SIG_FLAGS_MASK) | SIG_FUNC, iParamError=ixRetval; - else - sigFlags = SIG_FUNC, iParamError=ParamRetval; - IfFailGo(_ConvSignature(pITI, pReturn, sigFlags, qbComSig, cbTotal, &cbTotal, qbNativeBuf, iNativeOfs, &iNewNativeOfs, bNewEnumMember)); - qbNativeLen[0] = iNewNativeOfs - iNativeOfs; - qbNativeOfs[0] = iNativeOfs; - iNativeOfs = iNewNativeOfs; - if (hr == S_CONVERSION_LOSS) - bConversionLoss = true; - } - else - { // No return value - cbTotal = cb = CorSigCompressData((ULONG)IMAGE_CEE_CS_CALLCONV_DEFAULT | IMAGE_CEE_CS_CALLCONV_HASTHIS, pbSig); - cb = CorSigCompressData(cDestParams, &(pbSig[cbTotal])); - cbTotal += cb; - cb = CorSigCompressData(ELEMENT_TYPE_VOID, &pbSig[cbTotal]); - cbTotal += cb; - } - - //------------------------------------------------------------------------- - // Translate each parameter. - for (iSrcParam=0, iDestParam=0; iSrcParam<psFunc->cParams; ++iSrcParam) - { - if (!(psFunc->lprgelemdescParam[iSrcParam].paramdesc.wParamFlags & NON_CONVERTED_PARAMS_FLAGS)) - { - sigFlags = (SigFlags)(psFunc->lprgelemdescParam[iSrcParam].paramdesc.wParamFlags & SIG_FLAGS_MASK) | SIG_FUNC | SIG_USE_BYREF; - if (iSrcParam == ixVarArg) - sigFlags |= SIG_VARARG; - iParamError = iSrcParam; - IfFailGo(_ConvSignature(pITI, &psFunc->lprgelemdescParam[iSrcParam].tdesc, sigFlags, qbComSig, cbTotal, &cbTotal, qbNativeBuf, iNativeOfs, &iNewNativeOfs, bNewEnumMember)); - qbNativeLen[iDestParam+1] = iNewNativeOfs - iNativeOfs; - qbNativeOfs[iDestParam+1] = iNativeOfs; - iNativeOfs = iNewNativeOfs; - iDestParam++; - if (hr == S_CONVERSION_LOSS) - bConversionLoss = true; - } - } - iParamError = ParamNone; - - //------------------------------------------------------------------------- - // Get the previously decorated name. Add interface name and make unique. - if (bDelegateInvokeMeth) - { - pszName = (WCHAR*)DELEGATE_INVOKE_METH_NAME; - } - else - { - // m_szInterface should be non-null if processing an implemented interface; should be null otherwise. - _ASSERTE(m_ImplIface == eImplIfaceNone || m_szInterface != 0); - IfFailGo(qbName.ReSizeNoThrow(wcslen(pMember->m_pName)+2)); - wcscpy_s(qbName.Ptr(), wcslen(pMember->m_pName)+2, pMember->m_pName); - IfFailGo(GenerateUniqueMemberName(qbName, (PCCOR_SIGNATURE)qbComSig.Ptr(), cbTotal, m_szInterface, mdtMethodDef)); - pszName = qbName.Ptr(); - } - - // Determine the function's semantics, flags and impl flags. - if (!bDelegateInvokeMeth) - { - msSemantics = pMember->m_msSemantics; - dwImplFlags = DEFAULT_ITF_FUNC_IMPL_FLAGS; - dwFlags = msSemantics ? DEFAULT_PROPERTY_FUNC_FLAGS : DEFAULT_INTERFACE_FUNC_FLAGS; - // If processing an implemented interface, remove the abstract bit. Methods on classes are not abstract. - if (m_ImplIface != eImplIfaceNone) - dwFlags &= ~mdAbstract; - } - else - { - msSemantics = 0; - dwImplFlags = miRuntime; - dwFlags = DELEGATE_INVOKE_FUNC_FLAGS; - } - - //------------------------------------------------------------------------- - // Create the function definition in the metadata. - IfFailGo(m_pEmit->DefineMethod(m_tdTypeDef, pszName, dwFlags, (PCCOR_SIGNATURE) qbComSig.Ptr(),cbTotal, - 0 /* rva*/, dwImplFlags | (bOleCall ? 0 : miPreserveSig), &mdFunc)); - - // If the method is part of a property, save info to set up the property. - if (msSemantics) - pMember->SetFuncInfo(mdFunc, msSemantics); - - // Handle dispids for non-implemented interfaces, and for default interface - if (m_ImplIface != eImplIface) - { - // Add the DispIds if the flag is set. - long lDispSet = 1; - _SetDispIDCA(pITI, pMember->m_iMember, psFunc->memid, mdFunc, bAddDispIds, &lDispSet, TRUE); - - // If this method is the default, and not a property accessor, add a custom attribute to the class. - if (lDispSet == DISPID_VALUE && msSemantics == 0) - IfFailGo(_AddDefaultMemberCa(m_tdTypeDef, m_szMember)); - } - - DECLARE_CUSTOM_ATTRIBUTE(sizeof(int)); - - // If this method has an LCID then set the LCIDConversion attribute. - if (iLCIDParam != -1) - { - // Dispid for the function. - BUILD_CUSTOM_ATTRIBUTE(int, iLCIDParam); - IfFailGo(GetAttrType(ATTR_LCIDCONVERSION, &tkAttr)); - FINISH_CUSTOM_ATTRIBUTE(); - IfFailGo(m_pEmit->DefineCustomAttribute(mdFunc, tkAttr, PTROF_CUSTOM_ATTRIBUTE(), SIZEOF_CUSTOM_ATTRIBUTE(), 0)); - } - - // Save the func flags for anyone that needs typelib's flags. - if (psFunc->wFuncFlags) - { - IfFailGo(GetAttrType(ATTR_TYPELIBFUNC, &tkAttr)); - INIT_CUSTOM_ATTRIBUTE(sizeof(WORD)); - BUILD_CUSTOM_ATTRIBUTE(WORD, psFunc->wFuncFlags); - FINISH_CUSTOM_ATTRIBUTE(); - IfFailGo(m_pEmit->DefineCustomAttribute(mdFunc, tkAttr, PTROF_CUSTOM_ATTRIBUTE(), SIZEOF_CUSTOM_ATTRIBUTE(),0)); - } - - //------------------------------------------------------------------------- - // Convert the param info for the return type. - if (pReturn) - { // store return value parameter as sequence 0 - if (bRetval) - { - hr = _IsAlias(pITI, &psFunc->lprgelemdescParam[ixRetval].tdesc); - IfFailGo(hr); - if (qbNativeLen[0] || hr == S_OK) - { - IfFailGo(_ConvParam(pITI, mdFunc, 0, &psFunc->lprgelemdescParam[ixRetval], ParamNormal, 0 /*rszParamNames[ixRetval+1]*/, - &qbNativeBuf[qbNativeOfs[0]], qbNativeLen[0])); - } - } - else - { - hr = _IsAlias(pITI, &psFunc->elemdescFunc.tdesc); - IfFailGo(hr); - if (qbNativeLen[0] || hr == S_OK) - { - IfFailGo(_ConvParam(pITI, mdFunc, 0, &psFunc->elemdescFunc, ParamNormal, 0, - &qbNativeBuf[qbNativeOfs[0]], qbNativeLen[0])); - } - } - } - - //------------------------------------------------------------------------- - // Convert parameter info (flags, native type, default value). - for (iSrcParam=iDestParam=0; iSrcParam<psFunc->cParams; ++iSrcParam) - { - if ((psFunc->lprgelemdescParam[iSrcParam].paramdesc.wParamFlags & NON_CONVERTED_PARAMS_FLAGS) == 0) - { - ParamOpts opt = ParamNormal; - if (iSrcParam >= ixOpt) - opt = ParamOptional; - else - if (iSrcParam == ixVarArg) - opt = ParamVarArg; - iDestParam++; - IfFailGo(_ConvParam(pITI, mdFunc, iDestParam, &psFunc->lprgelemdescParam[iSrcParam], opt, rszParamNames[iSrcParam + 1], - &qbNativeBuf[qbNativeOfs[iDestParam]], qbNativeLen[iDestParam])); - } - } - - - //------------------------------------------------------------------------- - // If processing an implemented interface, set up MethodImpls. - if (m_ImplIface != eImplIfaceNone) - { - // Define a memberref on the implemented interface. - mdToken mrItfMember; - IfFailGo(m_pEmit->DefineMemberRef(m_tkInterface, pMember->m_pName, (PCCOR_SIGNATURE) qbComSig.Ptr(),cbTotal, &mrItfMember)); - - // Define a method impl. - IfFailGo(m_pEmit->DefineMethodImpl(m_tdTypeDef, mdFunc, mrItfMember)); - } - - if (bConversionLoss) - { - hr = S_CONVERSION_LOSS; - ReportEvent(NOTIF_CONVERTWARNING, TLBX_I_UNCONVERTABLE_ARGS, m_szName, m_szMember); - } - -ErrExit: - // Special case for typeload load failures -- they're very hard to diagnose. - if (hr == TYPE_E_CANTLOADLIBRARY) - { - if (iParamError >= 0 && iParamError < psFunc->cParams && rszParamNames[iParamError+1]) - ReportEvent(NOTIF_CONVERTWARNING, TLBX_E_PARAM_ERROR_NAMED, m_szName, rszParamNames[iParamError+1], m_szMember); - else - ReportEvent(NOTIF_CONVERTWARNING, TLBX_E_PARAM_ERROR_UNNAMED, m_szName, iParamError, m_szMember); - } - if (rszParamNames) - { - for (iSrcParam=0; iSrcParam<=psFunc->cParams; ++iSrcParam) - if (rszParamNames[iSrcParam]) - ::SysFreeString(rszParamNames[iSrcParam]); - } - if (m_szMember) - ::SysFreeString(m_szMember), m_szMember=0; - if (szTypeName) - ::SysFreeString(szTypeName); - - return (hr); -} // HRESULT CImportTlb::_ConvFunction() -#ifdef _PREFAST_ -#pragma warning(pop) -#endif - - -HRESULT CImportTlb::_SetHiddenCA(mdTypeDef token) -{ - mdToken tkAttr; - HRESULT hr = S_OK; - - DECLARE_CUSTOM_ATTRIBUTE(sizeof(short)); - BUILD_CUSTOM_ATTRIBUTE(short, TYPEFLAG_FHIDDEN); - IfFailGo(GetAttrType(ATTR_TYPELIBTYPE, &tkAttr)); - FINISH_CUSTOM_ATTRIBUTE(); - m_pEmit->DefineCustomAttribute(token, tkAttr, PTROF_CUSTOM_ATTRIBUTE(), SIZEOF_CUSTOM_ATTRIBUTE(), 0); - -ErrExit: - return S_OK; -} - -HRESULT CImportTlb::_ForceIEnumerableCVExists(ITypeInfo* pITI, BOOL* CVExists) -{ - ITypeInfo2 *pITI2 = 0; - *CVExists = FALSE; - HRESULT hr = S_OK; - - pITI->QueryInterface(IID_ITypeInfo2, reinterpret_cast<void**>(&pITI2)); - - if (pITI2) - { - VARIANT vCustomData; - VariantInit(&vCustomData); - - IfFailGo(pITI2->GetCustData(GUID_ForceIEnumerable, &vCustomData)); - - if (V_VT(&vCustomData) != VT_EMPTY) - *CVExists = TRUE; - - VariantClear(&vCustomData); - } - -ErrExit: - if (pITI2) - pITI2->Release(); - - return S_OK; -} - - -HRESULT CImportTlb::_GetDispIDCA( - ITypeInfo* pITI, - int iMember, - long* lDispSet, - BOOL bFunc - ) -{ - ITypeInfo2 *pITI2=0; // For getting custom value. - HRESULT hr = S_OK; - long lDispId = DISPID_UNKNOWN; - - // Get the ITypeInfo2 interface if possible - pITI->QueryInterface(IID_ITypeInfo2, reinterpret_cast<void**>(&pITI2)); - - if (pITI2) - { - VARIANT vCustomData; - VariantInit(&vCustomData); - - if (bFunc) - IfFailGo(pITI2->GetFuncCustData(iMember, GUID_DispIdOverride, &vCustomData)); - else - IfFailGo(pITI2->GetVarCustData(iMember, GUID_DispIdOverride, &vCustomData)); - - if ((V_VT(&vCustomData) == VT_I2) || (V_VT(&vCustomData) == VT_I4)) - { - hr = VariantChangeType(&vCustomData, &vCustomData, 0, VT_I4); - if (hr == S_OK) - lDispId = vCustomData.lVal; - } - - VariantClear(&vCustomData); - } - -ErrExit: - if (lDispSet != NULL) - *lDispSet = lDispId; - - if (pITI2) - pITI2->Release(); - - return S_OK; -} - - - -HRESULT CImportTlb::_SetDispIDCA( - ITypeInfo* pITI, - int iMember, - long lDispId, - mdToken func, - BOOL fAlwaysAdd, - long* lDispSet, - BOOL bFunc - ) -{ - WCHAR DispIDCA[] = W("{CD2BC5C9-F452-4326-B714-F9C539D4DA58}"); - ITypeInfo2 *pITI2=0; // For getting custom value. - HRESULT hr = S_OK; - - // Get the ITypeInfo2 interface if possible - pITI->QueryInterface(IID_ITypeInfo2, reinterpret_cast<void**>(&pITI2)); - - if (pITI2) - { - VARIANT vCustomData; - VariantInit(&vCustomData); - - if (bFunc) - IfFailGo(pITI2->GetFuncCustData(iMember, GUID_DispIdOverride, &vCustomData)); - else - IfFailGo(pITI2->GetVarCustData(iMember, GUID_DispIdOverride, &vCustomData)); - - if ((V_VT(&vCustomData) == VT_I2) || (V_VT(&vCustomData) == VT_I4)) - { - hr = VariantChangeType(&vCustomData, &vCustomData, 0, VT_I4); - if (hr == S_OK) - { - lDispId = vCustomData.lVal; - fAlwaysAdd = true; - } - } - else if (V_VT(&vCustomData) != VT_EMPTY) - { - // Invalid Variant type on the data - spit out a warning. - BSTR CustomValue = SysAllocString((const WCHAR*)&DispIDCA[0]); - BSTR ObjectName; - IfFailGo(pITI2->GetDocumentation(iMember+1, &ObjectName, NULL, NULL, NULL)); - - ReportEvent(NOTIF_CONVERTWARNING, TLBX_W_NON_INTEGRAL_CA_TYPE, CustomValue, ObjectName); - - SysFreeString(CustomValue); - SysFreeString(ObjectName); - } - - VariantClear(&vCustomData); - } - - // Set the dispid CA on the property. - if (fAlwaysAdd) - { - mdToken tkAttr; - DECLARE_CUSTOM_ATTRIBUTE(sizeof(DISPID)); - BUILD_CUSTOM_ATTRIBUTE(DISPID, lDispId); - IfFailGo(GetAttrType(ATTR_DISPID, &tkAttr)); - FINISH_CUSTOM_ATTRIBUTE(); - IfFailGo(m_pEmit->DefineCustomAttribute(func, tkAttr, PTROF_CUSTOM_ATTRIBUTE(), SIZEOF_CUSTOM_ATTRIBUTE(), 0)); - } - -ErrExit: - if (lDispSet != NULL) - { - *lDispSet = lDispId; - } - - if (pITI2) - pITI2->Release(); - - return S_OK; -} - - -HRESULT CImportTlb::_CheckForPropertyCustomAttributes(ITypeInfo* pITI, int index, INVOKEKIND* ikind) -{ - HRESULT hr; - VARIANT vCustomData; - ITypeInfo2* pITI2 = 0; - BOOL found = FALSE; - - VariantInit(&vCustomData); - - // Get the ITypeInfo2 interface if possible - pITI->QueryInterface(IID_ITypeInfo2, reinterpret_cast<void**>(&pITI2)); - if (pITI2) - { - // First, check for PropGet - hr = pITI2->GetFuncCustData(index, GUID_PropGetCA, &vCustomData); - IfFailGo(hr); - if (V_VT(&vCustomData) != VT_EMPTY) - { - *ikind = INVOKE_PROPERTYGET; - found = TRUE; - goto ErrExit; - } - - // Second, check for PropPut - VariantClear(&vCustomData); - hr = pITI2->GetFuncCustData(index, GUID_PropPutCA, &vCustomData); - IfFailGo(hr); - if (V_VT(&vCustomData) != VT_EMPTY) - { - *ikind = INVOKE_PROPERTYPUT; - found = TRUE; - goto ErrExit; - } - } - -ErrExit: - VariantClear(&vCustomData); - - if (pITI2) - pITI2->Release(); - - if (found) - return S_OK; - - return S_FALSE; -} - -//***************************************************************************** -// Generate an event with an add and remove method -//***************************************************************************** -HRESULT CImportTlb::_GenerateEvent( - ITypeInfo *pITI, // Containing TypeInfo. - MemberInfo *pMember, // Info for the function - BOOL fInheritsIEnum) -{ - HRESULT hr = S_OK; // A result. - mdMethodDef mdAdd; // Token of add_XXX method. - mdMethodDef mdRemove; // Token of remove_XXX method. - CQuickArray<WCHAR> qbName; // Buffer for decorated name. - CQuickArray<BYTE> qbSig; // The signature. - ULONG cb; // Size of an element. - ULONG cbTotal = 0; // Size of the signature. - mdTypeDef tdDelegate; // The delegate type def. - mdEvent tkEvent; // The token for the event. - - // If this method is a property method, then skip the event. - // Also look at the property semantic - it might be we couldn't import this as a property - // and fell back to a method. - if ((pMember->m_psFunc->invkind != INVOKE_FUNC) && (pMember->m_msSemantics != 0)) - { - ReportEvent(NOTIF_CONVERTWARNING, TLBX_W_NO_PROPS_IN_EVENTS, m_szName); - return S_CONVERSION_LOSS; - } - - // Generate the delegate. - IfFailGo(_GenerateEventDelegate(pITI, pMember, &tdDelegate, fInheritsIEnum)); - - // Generate the sig for the add and remove methods. - IfFailGo(qbSig.ReSizeNoThrow(CB_MAX_ELEMENT_TYPE * 2 + 1)); - cbTotal = CorSigCompressData((ULONG)IMAGE_CEE_CS_CALLCONV_DEFAULT | IMAGE_CEE_CS_CALLCONV_HASTHIS, qbSig.Ptr()); - cb = CorSigCompressData(1, &(qbSig[cbTotal])); - cbTotal += cb; - cb = CorSigCompressData(ELEMENT_TYPE_VOID, &qbSig[cbTotal]); - cbTotal += cb; - cb = CorSigCompressData(ELEMENT_TYPE_CLASS, &qbSig[cbTotal]); - cbTotal += cb; - cb = CorSigCompressToken(tdDelegate, &qbSig[cbTotal]); - cbTotal += cb; - - // Generate the add method. - IfFailGo(qbName.ReSizeNoThrow(EVENT_ADD_METH_PREFIX_LENGTH + wcslen(pMember->m_pName) + 1)); - StringCchPrintf(qbName.Ptr(), qbName.Size(), W("%s%s"), EVENT_ADD_METH_PREFIX, pMember->m_pName); - IfFailGo(m_pEmit->DefineMethod(m_tdTypeDef, qbName.Ptr(), DEFAULT_INTERFACE_FUNC_FLAGS, - qbSig.Ptr(), cbTotal, 0 /* rva*/, DEFAULT_ITF_FUNC_IMPL_FLAGS, &mdAdd)); - - // Generate the remove method. - IfFailGo(qbName.ReSizeNoThrow(EVENT_REM_METH_PREFIX_LENGTH + wcslen(pMember->m_pName) + 1)); - StringCchPrintf(qbName.Ptr(), qbName.Size(), W("%s%s"), EVENT_REM_METH_PREFIX, pMember->m_pName); - IfFailGo(m_pEmit->DefineMethod(m_tdTypeDef, qbName.Ptr(), DEFAULT_INTERFACE_FUNC_FLAGS, - qbSig.Ptr(), cbTotal, 0 /* rva*/, DEFAULT_ITF_FUNC_IMPL_FLAGS, &mdRemove)); - - // Define the event itself. - IfFailGo(m_pEmit->DefineEvent(m_tdTypeDef, pMember->m_pName, 0, tdDelegate, - mdAdd, mdRemove, mdTokenNil, NULL, &tkEvent)); - -ErrExit: - - return (hr); -} // HRESULT CImportTlb::_GenerateEvent() - -//***************************************************************************** -// Generate an add and remove method -//***************************************************************************** -HRESULT CImportTlb::_GenerateEventDelegate( - ITypeInfo *pITI, // Containing TypeInfo. - MemberInfo *pMember, // Info for the source interface func - mdTypeDef *ptd, // The output typedef. - BOOL fInheritsIEnum) -{ - HRESULT hr = S_OK; // A result. - BSTR bstrSrcItfName = NULL; // The name of the source interface. - CQuickArray<WCHAR> qbEventHandlerName; // The name of the event handler. - BSTR szOldName = NULL; // The old value m_tdTypeDef. - mdTypeDef tdOldTypeDef = NULL; // The old value m_szName. - CQuickArray<BYTE> qbSig; // The signature. - ULONG cb; // Size of an element. - ULONG cbTotal = 0; // Total size of signature. - mdMethodDef mdFunc; // The defined function. - mdTypeRef trMulticastDelegate; // The type ref for System.MulticastDelegate. - mdToken tkAttr; // Custom attribute type. - - // Store the old values of the ITypeInfo name and of the current type def. - szOldName = m_szName; - tdOldTypeDef = m_tdTypeDef; - m_szName = NULL; - - // Retrieve the full name of the source interface. - IfFailGo(GetManagedNameForTypeInfo(pITI, m_wzNamespace, NULL, &bstrSrcItfName)); - - // Generate a unique name for the event handler which will be of the form: - // <SrcItfName>_<MethodName>_EventHandler<PotentialSuffix> - IfFailGo(qbEventHandlerName.ReSizeNoThrow(wcslen(bstrSrcItfName) + wcslen(pMember->m_pName) + EVENT_HANDLER_SUFFIX_LENGTH + 6)); - StringCchPrintf(qbEventHandlerName.Ptr(), qbEventHandlerName.Size(), W("%s_%s%s"), bstrSrcItfName, pMember->m_pName, EVENT_HANDLER_SUFFIX); - IfFailGo(GenerateUniqueTypeName(qbEventHandlerName)); - - // Set the information on the current type. - IfNullGo(m_szName = SysAllocString(qbEventHandlerName.Ptr())); - - // Retrieve the parent type ref. - IfFailGo(GetKnownTypeToken(VT_SLOT_FOR_MULTICASTDEL, &trMulticastDelegate)); - - // Create the typedef for the event interface. - IfFailGo(m_pEmit->DefineTypeDef(m_szName, tdPublic | tdSealed, trMulticastDelegate, NULL, &m_tdTypeDef)); - - // Hide the interface from Object Browsers (EventHandler) - _SetHiddenCA(m_tdTypeDef); - - // Make the interface ComVisible(false). - { - DECLARE_CUSTOM_ATTRIBUTE(sizeof(BYTE)); - BUILD_CUSTOM_ATTRIBUTE(BYTE, FALSE); - IfFailGo(GetAttrType(ATTR_COMVISIBLE, &tkAttr)); - FINISH_CUSTOM_ATTRIBUTE(); - IfFailGo(m_pEmit->DefineCustomAttribute(m_tdTypeDef, tkAttr, PTROF_CUSTOM_ATTRIBUTE(), SIZEOF_CUSTOM_ATTRIBUTE(), 0)); - } - - // Generate the sig for the constructor. - IfFailGo(qbSig.ReSizeNoThrow(CB_MAX_ELEMENT_TYPE * 2 + 1)); - cbTotal = CorSigCompressData((ULONG)IMAGE_CEE_CS_CALLCONV_DEFAULT | IMAGE_CEE_CS_CALLCONV_HASTHIS, qbSig.Ptr()); - cb = CorSigCompressData(2, &(qbSig[cbTotal])); - cbTotal += cb; - cb = CorSigCompressData(ELEMENT_TYPE_VOID, &qbSig[cbTotal]); - cbTotal += cb; - cb = CorSigCompressData(ELEMENT_TYPE_OBJECT, &qbSig[cbTotal]); - cbTotal += cb; - cb = CorSigCompressData(ELEMENT_TYPE_U, &qbSig[cbTotal]); - cbTotal += cb; - - // Generate the constructor. - IfFailGo(m_pEmit->DefineMethod(m_tdTypeDef, OBJECT_INITIALIZER_NAME, OBJECT_INITIALIZER_FLAGS, - qbSig.Ptr(), cbTotal, 0 /* rva*/, miRuntime, &mdFunc)); - - // Generate the invoke method. - BOOL bAllowIEnum = !fInheritsIEnum; - IfFailGo(_ConvFunction(pITI, pMember, FALSE, FALSE, TRUE, &bAllowIEnum)); - - // Set the output typedef. - *ptd = m_tdTypeDef; - -ErrExit: - if (m_szName) - ::SysFreeString(m_szName); - if (m_szMember) - ::SysFreeString(m_szMember); m_szMember=0; - if (bstrSrcItfName) - ::SysFreeString(bstrSrcItfName); - - // Restore the initial values for the ITypeInfo name and the type def. - m_szName = szOldName; - m_tdTypeDef = tdOldTypeDef; - - return (hr); -} // HRESULT CImportTlb::_GenerateEventDelegate() - -//***************************************************************************** -//***************************************************************************** -struct MDTOKENHASH : HASHLINK -{ - mdToken tkKey; - mdToken tkData; -}; // struct MDTOKENHASH : HASHLINK - -class CTokenHash : public CChainedHash<MDTOKENHASH> -{ -public: - virtual bool InUse(MDTOKENHASH *pItem) - { return (pItem->tkKey != NULL); } - - virtual void SetFree(MDTOKENHASH *pItem) - { - pItem->tkKey = NULL; - pItem->tkKey = NULL; - } - - virtual ULONG Hash(const void *pData) - { - // Do case-insensitive hash - return (ULONG)(ULONG_PTR)pData; - } - - virtual int Cmp(const void *pData, void *pItem){ - return (mdToken)(ULONG_PTR)pData != reinterpret_cast<MDTOKENHASH*>(pItem)->tkKey; - } -}; // CTokenHash : public CChainedHash<MDTOKENHASH> - -//***************************************************************************** -// Copy methods and events from a source interface to a class that sources the -// given interface. -//***************************************************************************** -HRESULT CImportTlb::_AddSrcItfMembersToClass( // S_OK or error. - mdTypeRef trSrcItf) // Typeref of the source interface. -{ - HRESULT hr=S_OK; // A result. - ULONG i; // Generic counter. - HCORENUM MemberEnum = NULL; // The enum of members. - ULONG cMembers = 0; // Temp count of members. - mdTypeDef tdSrcItf; // A type def to the interface. - mdEvent tkItfEvent; // The token of the interface event. - mdEvent tkClassEvent; // The token of the class event. - mdToken tkEventType; // The event type. - mdMethodDef mdItfMethod; // The method def of the interface method. - mdMethodDef mdAddMethod; // The add method. - mdMethodDef mdRemoveMethod; // The remove method. - mdMethodDef mdFireMethod; // The fire method. - mdMethodDef mdClassMethod; // The method def of the class method. - CQuickArray<mdMethodDef> qbOtherMethods; // The other methods for the property. - ULONG cchOtherMethods; // The cound of other methods. - CQuickArray<WCHAR> qbMemberName; // Name of the member. - CQuickArray<WCHAR> qbEventItfFullName; // Full name of the event interface. - CQuickArray<WCHAR> qbEventItfName; // Name of the event interface. - ULONG cchName; // Length of a name, in wide chars. - ULONG ItfMemberAttr; // The attributes of the interface member. - ULONG ItfMemberImplFlags; // The impl flags of the interface member. - PCCOR_SIGNATURE ItfMemberSig; // The signature of the interface member. - ULONG ItfMemberSigSize; // The size of the member signature. - mdMemberRef mrItfMember; // A member ref to the interface member def. - BSTR bstrSrcItfName = NULL; // The name of the CoClass. - mdAssemblyRef ar; // The assembly ref. - CTokenHash ItfMDToClassMDMap; // The interface MD to class MD map. - MDTOKENHASH * pItem; // An item in the token hashtable. - - // Retrieve the name of the event interface. - do { - IfFailGo(m_pImport->GetTypeRefProps( - trSrcItf, - &ar, - qbEventItfFullName.Ptr(), - (ULONG)qbEventItfFullName.MaxSize(), - &cchName)); - if (hr == CLDB_S_TRUNCATION) - { - IfFailGo(qbEventItfFullName.ReSizeNoThrow(cchName)); - continue; - } - break; - } while (1); - IfFailGo(qbEventItfName.ReSizeNoThrow(cchName)); - ns::SplitPath(qbEventItfFullName.Ptr(), NULL, 0, qbEventItfName.Ptr(), (int)qbEventItfName.Size()); - - // Resolve the typeref to a typedef. - IfFailGo(m_pImport->FindTypeDefByName(qbEventItfFullName.Ptr(), mdTokenNil, &tdSrcItf)); - - // Define methods and method impl's for all the methods in the interface. - while ((hr = m_pImport->EnumMethods(&MemberEnum, tdSrcItf, &mdItfMethod, 1, &cMembers)) == S_OK) - { - // Retrieve the method properties. - do { - IfFailGo(m_pImport->GetMethodProps( - mdItfMethod, - NULL, - qbMemberName.Ptr(), - (ULONG)qbMemberName.MaxSize(), - &cchName, - &ItfMemberAttr, - &ItfMemberSig, - &ItfMemberSigSize, - NULL, - &ItfMemberImplFlags)); - if (hr == CLDB_S_TRUNCATION) - { - IfFailGo(qbMemberName.ReSizeNoThrow(cchName)); - continue; - } - break; - } while (1); - - // Define a member ref on the class to the interface member def. - IfFailGo(m_pEmit->DefineMemberRef(trSrcItf, qbMemberName.Ptr(), ItfMemberSig, ItfMemberSigSize, &mrItfMember)); - - // Generate a unique name for the class member. - IfFailGo(GenerateUniqueMemberName(qbMemberName, NULL, 0, qbEventItfName.Ptr(), mdtMethodDef)); - - // Define a member on the class. - IfFailGo(m_pEmit->DefineMethod(m_tdTypeDef, qbMemberName.Ptr(), ItfMemberAttr & ~mdAbstract, - ItfMemberSig, ItfMemberSigSize, 0/*rva*/, ItfMemberImplFlags, &mdClassMethod)); - - // Define a method impl. - IfFailGo(m_pEmit->DefineMethodImpl(m_tdTypeDef, mdClassMethod, mrItfMember)); - - // Add the interface member to the map. - if ((pItem = ItfMDToClassMDMap.Add((const void *)(ULONG_PTR)mdItfMethod)) == NULL) - IfFailGo(E_FAIL); - PREFIX_ASSUME(pItem != NULL); - pItem->tkKey = mdItfMethod; - pItem->tkData = mdClassMethod; - } - IfFailGo(hr); - - m_pImport->CloseEnum(MemberEnum); - MemberEnum = NULL; - - // Define all the events in the interface on the class. - while ((hr = m_pImport->EnumEvents(&MemberEnum, tdSrcItf, &tkItfEvent, 1, &cMembers)) == S_OK) - { - // Retrieve the properties of the property. - do { - IfFailGo(m_pImport->GetEventProps( - tkItfEvent, - NULL, - qbMemberName.Ptr(), - (ULONG)qbMemberName.MaxSize(), - &cchName, - &ItfMemberAttr, - &tkEventType, - &mdAddMethod, - &mdRemoveMethod, - &mdFireMethod, - qbOtherMethods.Ptr(), - (ULONG)qbOtherMethods.MaxSize(), - &cchOtherMethods)); - if (hr == CLDB_S_TRUNCATION) - { - IfFailGo(qbMemberName.ReSizeNoThrow(cchName)); - IfFailGo(qbOtherMethods.ReSizeNoThrow(cchOtherMethods)); - continue; - } - break; - } while (1); - - // NULL terminate the array of other methods. - IfFailGo(qbOtherMethods.ReSizeNoThrow(cchOtherMethods + 1)); - qbOtherMethods[cchOtherMethods] = NULL; - - // Replace all the interface method def's with the equivalent class method def's. - if (!IsNilToken(mdAddMethod)) - { - pItem = ItfMDToClassMDMap.Find((const void *)(ULONG_PTR)mdAddMethod); - _ASSERTE(pItem); - mdAddMethod = pItem->tkData; - } - if (!IsNilToken(mdRemoveMethod)) - { - pItem = ItfMDToClassMDMap.Find((const void *)(ULONG_PTR)mdRemoveMethod); - _ASSERTE(pItem); - mdRemoveMethod = pItem->tkData; - } - _ASSERTE(IsNilToken(mdFireMethod)); - _ASSERTE(cchOtherMethods == 0); - - // Generate a unique name for the event. - IfFailGo(GenerateUniqueMemberName(qbMemberName, NULL, 0, qbEventItfName.Ptr(), mdtEvent)); - - // Define property on the class. - IfFailGo(m_pEmit->DefineEvent(m_tdTypeDef, qbMemberName.Ptr(), ItfMemberAttr, - tkEventType, mdAddMethod, mdRemoveMethod, mdFireMethod, qbOtherMethods.Ptr(), &tkClassEvent)); - } - IfFailGo(hr); - - m_pImport->CloseEnum(MemberEnum); - MemberEnum = NULL; - -ErrExit: - if (MemberEnum) - m_pImport->CloseEnum(MemberEnum); - if (bstrSrcItfName) - ::SysFreeString(bstrSrcItfName); - - return hr; - -#undef ITF_MEMBER_SIG -#undef ITF_MEMBER_SIG_SIZE -} // HRESULT CImportTlb::_AddSrcItfMembersToClass() - -//***************************************************************************** -// Compare the two signatures ignoring the return type. If the signatures -// match then TRUE will be returned, FALSE will be returned otherwise. -// This method assumes the two signatures are in the same scope. -//***************************************************************************** -HRESULT CImportTlb::CompareSigsIgnoringRetType( - PCCOR_SIGNATURE pbSig1, // The 1st method signature. - ULONG cbSig1, // Size of the 1st method signature. - PCCOR_SIGNATURE pbSig2, // The 2nd method signature. - ULONG cbSig2) // Size of the 2nd method signature. -{ - HRESULT hr = S_OK; - PCCOR_SIGNATURE pbSig1Start; - PCCOR_SIGNATURE pbSig2Start; - ULONG Sig1ParamCount; - ULONG Sig2ParamCount; - ULONG cbSig1RetType; - ULONG cbSig2RetType; - - // Save the start of the signatures. - pbSig1Start = pbSig1; - pbSig2Start = pbSig2; - - // Skip the calling conventions. - CorSigUncompressData(pbSig1); - CorSigUncompressData(pbSig2); - - // Compare the param count. - Sig1ParamCount = CorSigUncompressData(pbSig1); - Sig2ParamCount = CorSigUncompressData(pbSig2); - if (Sig1ParamCount != Sig2ParamCount) - return S_FALSE; - - // Skip the return type. - cbSig1RetType = cbSig1 - (ULONG)(pbSig1 - pbSig1Start); - IfFailGo(_CountBytesOfOneArg(pbSig1, &cbSig1RetType)); - pbSig1 += cbSig1RetType; - cbSig2RetType = cbSig2 - (ULONG)(pbSig2 - pbSig2Start); - IfFailGo(_CountBytesOfOneArg(pbSig2, &cbSig2RetType)); - pbSig2 += cbSig2RetType; - - // Update the remaining sig sizes. - cbSig1 -= (ULONG) (pbSig1 - pbSig1Start); - cbSig2 -= (ULONG) (pbSig2 - pbSig2Start); - - // If the remaining sig sizes are different then the sigs don't match. - if (cbSig1 != cbSig2) - return S_FALSE; - - // Compare the rest of the sigs using memcmp. - if (memcmp(pbSig1, pbSig2, cbSig1) != 0) - return S_FALSE; - - // The parameters match. - return S_OK; - -ErrExit: - // An error occurred. - return hr; -} // HRESULT CImportTlb::CompareSigsIgnoringRetType() - -//***************************************************************************** -// Look up a method in the emit scope. This lookup method does not take the -// return type into account when comparing using a sig. So 2 methods with -// the same name, same parameters and a different return type will be -// considered the same. -//***************************************************************************** -HRESULT CImportTlb::FindMethod( // S_OK or CLDB_E_RECORD_NOTFOUND, or error. - mdTypeDef td, // The method typedef. - LPCWSTR szName, // The method name. - PCCOR_SIGNATURE pbReqSig, // The method signature. - ULONG cbReqSig, // Size of the method signature. - mdMethodDef *pmb) // Put the method here. -{ - HRESULT hr = S_OK; // A result. - PCCOR_SIGNATURE pbFoundSig = NULL; - ULONG cbFoundSig = 0; - ULONG MethodAttr; - ULONG MethodImplFlags; - mdMethodDef md; - CQuickArray<WCHAR> qbMethodName; - HCORENUM MethodEnum = NULL; - ULONG cMethods = 0; - ULONG cchName; - BOOL bMethodFound = FALSE; - - // Go through all the methods on the class looking for one with the - // same name and same parameters. - while ((hr = m_pImport->EnumMethods(&MethodEnum, td, &md, 1, &cMethods)) == S_OK) - { - // Retrieve the method properties. - do { - IfFailGo(m_pImport->GetMethodProps( - md, - NULL, - qbMethodName.Ptr(), - (ULONG)qbMethodName.MaxSize(), - &cchName, - &MethodAttr, - &pbFoundSig, - &cbFoundSig, - NULL, - &MethodImplFlags)); - if (hr == CLDB_S_TRUNCATION) - { - IfFailGo(qbMethodName.ReSizeNoThrow(cchName)); - continue; - } - break; - } while (1); - - // Compare the name of the method. - if (wcscmp(szName, qbMethodName.Ptr()) != 0) - continue; - - // If the signature of the requested method is specified, then compare - // the signature against the signature of the found method ignoring - // the return type. - if (pbReqSig) - { - IfFailGo(hr = CompareSigsIgnoringRetType(pbReqSig, cbReqSig, pbFoundSig, cbFoundSig)); - if (hr == S_FALSE) - continue; - } - - // We have found the member. - bMethodFound = TRUE; - break; - } - IfFailGo(hr); - -ErrExit: - if (MethodEnum) - m_pImport->CloseEnum(MethodEnum); - - return bMethodFound ? S_OK : CLDB_E_RECORD_NOTFOUND; -} - -//***************************************************************************** -// Look up a property in the emit scope. -//***************************************************************************** -HRESULT CImportTlb::FindProperty( // S_OK or CLDB_E_RECORD_NOTFOUND, or error. - mdTypeDef td, // The property typedef. - LPCWSTR szName, // The property name. - PCCOR_SIGNATURE pbSig, // The property signature. - ULONG cbSig, // Size of the property signature. - mdProperty *ppr) // Put the property here. -{ - HRESULT hr; // A result. - RegMeta *pRegMeta = (RegMeta*)(m_pEmit); - LPUTF8 szNameAnsi; - - if (szName == NULL) - { - return CLDB_E_RECORD_NOTFOUND; - } - UTF8STR(szName, szNameAnsi); - - hr = ImportHelper::FindProperty( - &(pRegMeta->GetMiniStgdb()->m_MiniMd), - m_tdTypeDef, - szNameAnsi, - pbSig, - cbSig, - ppr); - return hr; -} // HRESULT CImportTlb::FindProperty() - -//***************************************************************************** -// Look up a event in the emit scope. -//***************************************************************************** -HRESULT CImportTlb::FindEvent( // S_OK or CLDB_E_RECORD_NOTFOUND, or error. - mdTypeDef td, // The event typedef. - LPCWSTR szName, // The event name. - mdEvent *pev) // Put the event here. -{ - HRESULT hr; // A result. - RegMeta *pRegMeta = (RegMeta*)(m_pEmit); - LPUTF8 szNameAnsi; - - if (szName == NULL) - { - return CLDB_E_RECORD_NOTFOUND; - } - UTF8STR(szName, szNameAnsi); - - hr = ImportHelper::FindEvent( - &(pRegMeta->GetMiniStgdb()->m_MiniMd), - m_tdTypeDef, - szNameAnsi, - pev); - return hr; -} // HRESULT CImportTlb::FindEvent() - -//***************************************************************************** -// Checks to see if the specified TYPEDESC is an alias. -//***************************************************************************** -HRESULT CImportTlb::_IsAlias( - ITypeInfo *pITI, // The ITypeInfo containing the TYPEDESC. - TYPEDESC *pTypeDesc) // The token of the param, field, etc. -{ - HRESULT hr = S_FALSE; // A result. - ITypeInfo *pTypeITI=0; // The ITypeInfo of the type. - ITypeLib *pTypeTLB=0; // The TLB that contains the type. - TYPEATTR *psTypeAttr=0; // TYPEATTR of the type. - - // Drill down to the actual type that is pointed to. - while (pTypeDesc->vt == VT_PTR) - pTypeDesc = pTypeDesc->lptdesc; - - // If the parameter is an alias then we need to add a custom attribute to the - // parameter that describes the alias. - if (pTypeDesc->vt == VT_USERDEFINED) - { - IfFailGo(pITI->GetRefTypeInfo(pTypeDesc->hreftype, &pTypeITI)); - IfFailGo(pTypeITI->GetTypeAttr(&psTypeAttr)); - if (psTypeAttr->typekind == TKIND_ALIAS) - { - hr = S_OK; - } - } - -ErrExit: - if (psTypeAttr) - pTypeITI->ReleaseTypeAttr(psTypeAttr); - if (pTypeITI) - pTypeITI->Release(); - return hr; -} // HRESULT CImportTlb::_IsAlias() - -//***************************************************************************** -// Add alias information if the TYPEDESC represents an alias. -//***************************************************************************** -HRESULT CImportTlb::_HandleAliasInfo( - ITypeInfo *pITI, // The ITypeInfo containing the TYPEDESC. - TYPEDESC *pTypeDesc, // The TYPEDESC. - mdToken tk) // The token of the param, field, etc. -{ - HRESULT hr = S_OK; // A result. - ITypeInfo *pTypeITI=0; // The ITypeInfo of the type. - ITypeLib *pTypeTLB=0; // The TLB that contains the type. - TYPEATTR *psTypeAttr=0; // TYPEATTR of the type. - BSTR bstrAliasTypeName=0; // The name of the alias type. - BSTR bstrAliasTypeLibName=0; // The name of the typelib that contains the alias type. - - // Drill down to the actual type that is pointed to. - while (pTypeDesc->vt == VT_PTR) - pTypeDesc = pTypeDesc->lptdesc; - - // If the parameter is an alias then we need to add a custom attribute to the - // parameter that describes the alias. - if (pTypeDesc->vt == VT_USERDEFINED) - { - IfFailGo(pITI->GetRefTypeInfo(pTypeDesc->hreftype, &pTypeITI)); - IfFailGo(pTypeITI->GetTypeAttr(&psTypeAttr)); - if (psTypeAttr->typekind == TKIND_ALIAS) - { - // Retrieve the name of the alias type. - IfFailGo(pTypeITI->GetContainingTypeLib(&pTypeTLB, NULL)); - IfFailGo(GetNamespaceOfRefTlb(pTypeTLB, &bstrAliasTypeLibName, NULL)); - IfFailGo(GetManagedNameForTypeInfo(pTypeITI, bstrAliasTypeLibName, NULL, &bstrAliasTypeName)); - - // Add the ComAliasName CA to the parameter. - _AddStringCa(ATTR_COMALIASNAME, tk, bstrAliasTypeName); - } - } - -ErrExit: - if (psTypeAttr) - pTypeITI->ReleaseTypeAttr(psTypeAttr); - if (pTypeITI) - pTypeITI->Release(); - if (pTypeTLB) - pTypeTLB->Release(); - if (bstrAliasTypeLibName) - ::SysFreeString(bstrAliasTypeLibName); - if (bstrAliasTypeName) - ::SysFreeString(bstrAliasTypeName); - return hr; -} // HRESULT CImportTlb::_HandleAliasInfo() - -//***************************************************************************** -// Convert one of a function's parameters. -//***************************************************************************** -HRESULT CImportTlb::_ConvParam( - ITypeInfo *pITI, // Containing TypeInfo. - mdMethodDef mdFunc, // Owning member. - int iSequence, // Parameter sequence. - const ELEMDESC *pdesc, // Param flags, default value. - ParamOpts paramOpts, // Is param normal, optional, or vararg? - LPCWSTR szName, // Name of the parameter. - BYTE *pbNative, // Native type info, if any. - ULONG cbNative) // Size of native type info. -{ - HRESULT hr; // A result. - mdParamDef pdParam; // Token of the parameter. - DWORD dwFlags; // Param flags. - USHORT Sequence = static_cast<USHORT>(iSequence); - BYTE cvType = ELEMENT_TYPE_VOID; // ELEMENT_TYPE_* flag for constant value - void *pcvValue=0; // constant value blob - __int64 d; // For cases where value is a date. - int bDecimal=0; // If true, constant is a decimal. - mdToken tkAttr; // For custom attribute token. - DECIMAL decVal; // Decimal constant value. - - // Compute the flags. Only make sense on non-return params. - dwFlags = 0; - if (iSequence > 0) - { - if (pdesc->paramdesc.wParamFlags & PARAMFLAG_FIN) - dwFlags |= pdIn; - if (pdesc->paramdesc.wParamFlags & PARAMFLAG_FOUT) - dwFlags |= pdOut; - if (pdesc->paramdesc.wParamFlags & PARAMFLAG_FOPT) - dwFlags |= pdOptional; - if (paramOpts == ParamOptional) - dwFlags |= pdOptional; - } - - // Get any default values. Return type, param with iSequence==0, has no default. - if (pdesc->paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT && iSequence != 0) - { - switch (pdesc->paramdesc.pparamdescex->varDefaultValue.vt) - { - case VT_CY: - case VT_DECIMAL: - case VT_DATE: - case VT_UNKNOWN: - case VT_DISPATCH: - break; - default: - // This workaround is because a typelib can store anything that can convert to VT_I4 with a value of 0 - // for the default value of an interface pointer. But, a VT_I2(0) confuses the consumers - // of the managed wrapper dll. So, if it is an interface on the unmanaged side, make - // the constant value an ET_CLASS. - if (cbNative > 0 && (*pbNative == NATIVE_TYPE_INTF || - *pbNative == NATIVE_TYPE_IUNKNOWN || - *pbNative == NATIVE_TYPE_IDISPATCH)) - { - cvType = ELEMENT_TYPE_CLASS; - pcvValue = 0; - } - else - IfFailGo( _UnpackVariantToConstantBlob(&pdesc->paramdesc.pparamdescex->varDefaultValue, &cvType, &pcvValue, &d) ); - } - } - - // Create the param definition. - IfFailGo(m_pEmit->DefineParam(mdFunc, iSequence, szName, dwFlags, cvType, pcvValue, -1, &pdParam)); - - // Add the native type if it there is any. - if (cbNative > 0) - IfFailGo(m_pEmit->SetFieldMarshal(pdParam, (PCCOR_SIGNATURE) pbNative, cbNative)); - - if (pdesc->paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT && iSequence != 0) - { - switch (pdesc->paramdesc.pparamdescex->varDefaultValue.vt) - { - case VT_CY: - IfFailGo(VarDecFromCy(pdesc->paramdesc.pparamdescex->varDefaultValue.cyVal, &decVal)); - IfFailGo(DecimalCanonicalize(&decVal)); - goto StoreDecimal; - case VT_DECIMAL: - // If there is a decimal constant value, set it as a custom attribute. - { - decVal = pdesc->paramdesc.pparamdescex->varDefaultValue.decVal; - StoreDecimal: - DECLARE_CUSTOM_ATTRIBUTE(sizeof(BYTE)+sizeof(BYTE)+sizeof(UINT)+sizeof(UINT)+sizeof(UINT)); - BUILD_CUSTOM_ATTRIBUTE(BYTE, decVal.scale); - BUILD_CUSTOM_ATTRIBUTE(BYTE, decVal.sign); - BUILD_CUSTOM_ATTRIBUTE(UINT, decVal.Hi32); - BUILD_CUSTOM_ATTRIBUTE(UINT, decVal.Mid32); - BUILD_CUSTOM_ATTRIBUTE(UINT, decVal.Lo32); - IfFailGo(GetAttrType(ATTR_DECIMALVALUE, &tkAttr)); - FINISH_CUSTOM_ATTRIBUTE(); - IfFailGo(m_pEmit->DefineCustomAttribute(pdParam, tkAttr, PTROF_CUSTOM_ATTRIBUTE(), SIZEOF_CUSTOM_ATTRIBUTE(),0)); - } - break; - case VT_DATE: - { - DECLARE_CUSTOM_ATTRIBUTE(sizeof(__int64)); - __int64 date = _DoubleDateToTicks(pdesc->paramdesc.pparamdescex->varDefaultValue.date); - BUILD_CUSTOM_ATTRIBUTE(__int64, date); - IfFailGo(GetAttrType(ATTR_DATETIMEVALUE, &tkAttr)); - FINISH_CUSTOM_ATTRIBUTE(); - IfFailGo(m_pEmit->DefineCustomAttribute(pdParam, tkAttr, PTROF_CUSTOM_ATTRIBUTE(), SIZEOF_CUSTOM_ATTRIBUTE(),0)); - } - break; - case VT_UNKNOWN: - { - DECLARE_CUSTOM_ATTRIBUTE(0); - IfFailGo(GetAttrType(ATTR_IUNKNOWNVALUE, &tkAttr)); - FINISH_CUSTOM_ATTRIBUTE(); - IfFailGo(m_pEmit->DefineCustomAttribute(pdParam, tkAttr, PTROF_CUSTOM_ATTRIBUTE(), SIZEOF_CUSTOM_ATTRIBUTE(),0)); - } - break; - case VT_DISPATCH: - { - DECLARE_CUSTOM_ATTRIBUTE(0); - IfFailGo(GetAttrType(ATTR_IDISPATCHVALUE, &tkAttr)); - FINISH_CUSTOM_ATTRIBUTE(); - IfFailGo(m_pEmit->DefineCustomAttribute(pdParam, tkAttr, PTROF_CUSTOM_ATTRIBUTE(), SIZEOF_CUSTOM_ATTRIBUTE(),0)); - } - break; - default: - break; - } - } - - // Add the alias information if the param is an alias. - IfFailGo(_HandleAliasInfo(pITI, (TYPEDESC*)&pdesc->tdesc, pdParam)); - - // If a vararg param, set the custom attribute. - if (paramOpts == ParamVarArg) - { - mdToken tkAttribute; - DECLARE_CUSTOM_ATTRIBUTE(0); - FINISH_CUSTOM_ATTRIBUTE(); - IfFailGo(GetAttrType(ATTR_PARAMARRAY, &tkAttribute)); - IfFailGo(m_pEmit->DefineCustomAttribute(pdParam, tkAttribute, PTROF_CUSTOM_ATTRIBUTE(), SIZEOF_CUSTOM_ATTRIBUTE(), 0)); - } - -ErrExit: - return hr; -} // HRESULT CImportTlb::_ConvParam() - -//***************************************************************************** -// Convert a constant into a field with a default value. -//***************************************************************************** -HRESULT CImportTlb::_ConvConstant( - ITypeInfo *pITI, // Containing TypeInfo. - VARDESC *psVar, // VARDESC for the property. - BOOL bEnumMember) // If true, type is containing class. -{ - HRESULT hr; // A result. - mdFieldDef mdField; // Token of the new field. - DWORD dwFlags; // Member flags. - CQuickBytes qbComSig; // The COM+ Signature of the field. - ULONG cb, cbTotal; - BYTE cvType = ELEMENT_TYPE_VOID; // E_T_Type for constant value - void *pcvValue; // Pointer to constant value data. - mdToken tkAttr; // Type for custom attribute. - __int64 d; // For cases where value is a date. - BOOL bConversionLoss=false; // If true, some attributes were lost on conversion. - BYTE *pbSig; // Pointer to signature bytes. - CQuickArray<BYTE> qbNativeBuf; // Native type buffer. - ULONG cbNative = 0; // Size of native type. - int bDecimal = 0; // If the value is a decimal. - DECIMAL decVal; // Decimal constant value. - - // Information about the member. - IfFailGo(pITI->GetDocumentation(psVar->memid, &m_szMember, 0,0,0)); - - // resize to make room for calling convention and count of argument - IfFailGo(qbComSig.ReSizeNoThrow(CB_MAX_ELEMENT_TYPE * 4)); - pbSig = (BYTE *)qbComSig.Ptr(); - - // Compute properties. - dwFlags = DEFAULT_CONST_FIELD_FLAGS; - - // Build the signature. - cbTotal = cb = CorSigCompressData((ULONG)IMAGE_CEE_CS_CALLCONV_FIELD, pbSig); - if (bEnumMember) - { - cb = CorSigCompressData(ELEMENT_TYPE_VALUETYPE, &pbSig[cbTotal]); - cbTotal += cb; - cb = CorSigCompressToken(m_tdTypeDef, reinterpret_cast<ULONG*>(&pbSig[cbTotal])); - cbTotal += cb; - } - else - { - // Use the conversion function to get the signature. - ULONG cbSave = cbTotal; - IfFailGo(_ConvSignature(pITI, &psVar->elemdescVar.tdesc, SIG_FLAGS_NONE, qbComSig, cbTotal, &cbTotal, qbNativeBuf, 0, &cbNative, FALSE)); - if (hr == S_CONVERSION_LOSS) - bConversionLoss = true; - - if (psVar->elemdescVar.tdesc.vt == VT_DATE) - { - // But for dates, convert it as float -- DateTime is reported as R4 in a typelib! - cbTotal = cbSave; - cb = CorSigCompressData(ELEMENT_TYPE_R4, &pbSig[cbTotal]); - cbTotal += cb; - } - } - - // Get the default value. - switch (psVar->lpvarValue->vt) - { - case VT_CY: - case VT_DECIMAL: - case VT_DATE: - case VT_UNKNOWN: - case VT_DISPATCH: - break; - default: - // This workaround is because a typelib can store anything that can convert to VT_I4 with a value of 0 - // for the default value of an interface pointer. But, a VT_I2(0) confuses the consumers - // of the managed wrapper dll. So, if it is an interface on the unmanaged side, make - // the constant value an ET_CLASS. - BYTE *pbNative = NULL; - pbNative = qbNativeBuf.Ptr(); - if (cbNative > 0 && (*pbNative == NATIVE_TYPE_INTF || - *pbNative == NATIVE_TYPE_IUNKNOWN || - *pbNative == NATIVE_TYPE_IDISPATCH)) - { - cvType = ELEMENT_TYPE_CLASS; - pcvValue = 0; - } - else - IfFailGo( _UnpackVariantToConstantBlob(psVar->lpvarValue, &cvType, &pcvValue, &d) ); - } - - // Create the field definition. - IfFailGo(m_pEmit->DefineField(m_tdTypeDef, m_szMember, dwFlags, (PCCOR_SIGNATURE)pbSig, cbTotal, - cvType, pcvValue, -1, &mdField)); - - switch (psVar->lpvarValue->vt) - { - case VT_CY: - IfFailGo(VarDecFromCy(psVar->lpvarValue->cyVal, &decVal)); - IfFailGo(DecimalCanonicalize(&decVal)); - goto StoreDecimal; - case VT_DECIMAL: - // If there is a decimal constant value, set it as a custom attribute. - { - decVal = psVar->lpvarValue->decVal; - StoreDecimal: - DECLARE_CUSTOM_ATTRIBUTE(sizeof(BYTE)+sizeof(BYTE)+sizeof(UINT)+sizeof(UINT)+sizeof(UINT)); - BUILD_CUSTOM_ATTRIBUTE(BYTE, decVal.scale); - BUILD_CUSTOM_ATTRIBUTE(BYTE, decVal.sign); - BUILD_CUSTOM_ATTRIBUTE(UINT, decVal.Hi32); - BUILD_CUSTOM_ATTRIBUTE(UINT, decVal.Mid32); - BUILD_CUSTOM_ATTRIBUTE(UINT, decVal.Lo32); - IfFailGo(GetAttrType(ATTR_DECIMALVALUE, &tkAttr)); - FINISH_CUSTOM_ATTRIBUTE(); - IfFailGo(m_pEmit->DefineCustomAttribute(mdField, tkAttr, PTROF_CUSTOM_ATTRIBUTE(), SIZEOF_CUSTOM_ATTRIBUTE(),0)); - } - break; - case VT_DATE: - { - DECLARE_CUSTOM_ATTRIBUTE(sizeof(__int64)); - __int64 date = _DoubleDateToTicks(psVar->lpvarValue->date); - BUILD_CUSTOM_ATTRIBUTE(__int64, date); - IfFailGo(GetAttrType(ATTR_DATETIMEVALUE, &tkAttr)); - FINISH_CUSTOM_ATTRIBUTE(); - IfFailGo(m_pEmit->DefineCustomAttribute(mdField, tkAttr, PTROF_CUSTOM_ATTRIBUTE(), SIZEOF_CUSTOM_ATTRIBUTE(),0)); - } - break; - case VT_UNKNOWN: - { - DECLARE_CUSTOM_ATTRIBUTE(0); - IfFailGo(GetAttrType(ATTR_IUNKNOWNVALUE, &tkAttr)); - FINISH_CUSTOM_ATTRIBUTE(); - IfFailGo(m_pEmit->DefineCustomAttribute(mdField, tkAttr, PTROF_CUSTOM_ATTRIBUTE(), SIZEOF_CUSTOM_ATTRIBUTE(),0)); - } - break; - case VT_DISPATCH: - { - DECLARE_CUSTOM_ATTRIBUTE(0); - IfFailGo(GetAttrType(ATTR_IDISPATCHVALUE, &tkAttr)); - FINISH_CUSTOM_ATTRIBUTE(); - IfFailGo(m_pEmit->DefineCustomAttribute(mdField, tkAttr, PTROF_CUSTOM_ATTRIBUTE(), SIZEOF_CUSTOM_ATTRIBUTE(),0)); - } - break; - default: - break; - } - - // Save the field flags. - if (psVar->wVarFlags) - { - IfFailGo(GetAttrType(ATTR_TYPELIBVAR, &tkAttr)); - DECLARE_CUSTOM_ATTRIBUTE(sizeof(WORD)); - BUILD_CUSTOM_ATTRIBUTE(WORD, psVar->wVarFlags); - FINISH_CUSTOM_ATTRIBUTE(); - IfFailGo(m_pEmit->DefineCustomAttribute(mdField, tkAttr, PTROF_CUSTOM_ATTRIBUTE(), SIZEOF_CUSTOM_ATTRIBUTE(),0)); - } - - // Set up the native description, if any. - if (cbNative > 0) - IfFailGo(m_pEmit->SetFieldMarshal(mdField, (PCCOR_SIGNATURE) qbNativeBuf.Ptr(), cbNative)); - - // Add the alias information if the type is an alias. - IfFailGo(_HandleAliasInfo(pITI, &psVar->elemdescVar.tdesc, mdField)); - - if (bConversionLoss) - { - hr = S_CONVERSION_LOSS; - ReportEvent(NOTIF_CONVERTWARNING, TLBX_I_UNCONVERTABLE_FIELD, m_szName, m_szMember); - } - -ErrExit: - if (m_szMember) - ::SysFreeString(m_szMember), m_szMember=0; - return (hr); -} // HRESULT CImportTlb::_ConvConstant() - -//***************************************************************************** -// Convert a (record) field into a member. -//***************************************************************************** -HRESULT CImportTlb::_ConvField( - ITypeInfo *pITI, // Containing TypeInfo. - VARDESC *psVar, // VARDESC for the property. - mdFieldDef *pmdField, // Put field token here. - BOOL bUnion) // Convert as a union? -{ - HRESULT hr; // A result. - DWORD dwFlags; // Member flags. - CQuickBytes qbComSig; // The COM+ Signature of the field. - ULONG cb, cbTotal; // Size of a sig element, signature. - BYTE *pbSig; // Pointer to signature bytes. - CQuickArray<BYTE> qbNativeBuf; // Native type buffer. - ULONG cbNative; // Size of native type. - mdToken tkAttr; // CustomAttribute type. - BOOL bConversionLoss=false; // If true, some attributes were lost on conversion. - - // Information about the member. - IfFailGo(pITI->GetDocumentation(psVar->memid, &m_szMember, 0,0,0)); - - // Compute properties. - dwFlags = DEFAULT_RECORD_FIELD_FLAGS; - - // resize to make room for calling convention and count of argument - IfFailGo(qbComSig.ReSizeNoThrow(CB_MAX_ELEMENT_TYPE * 2)); - pbSig = (BYTE *)qbComSig.Ptr(); - - // Build the signature. - cbTotal = cb = CorSigCompressData((ULONG)IMAGE_CEE_CS_CALLCONV_FIELD, pbSig); - IfFailGo(_ConvSignature(pITI, &psVar->elemdescVar.tdesc, SIG_FIELD, qbComSig, cbTotal, &cbTotal, qbNativeBuf, 0, &cbNative, FALSE)); - if (hr == S_CONVERSION_LOSS) - bConversionLoss = true; - - // Create the field definition. - IfFailGo(m_pEmit->DefineField(m_tdTypeDef, m_szMember, dwFlags, (PCCOR_SIGNATURE) qbComSig.Ptr(),cbTotal, - ELEMENT_TYPE_VOID, NULL, -1, pmdField)); - - // Save the field flags. - if (psVar->wVarFlags) - { - IfFailGo(GetAttrType(ATTR_TYPELIBVAR, &tkAttr)); - DECLARE_CUSTOM_ATTRIBUTE(sizeof(WORD)); - BUILD_CUSTOM_ATTRIBUTE(WORD, psVar->wVarFlags); - FINISH_CUSTOM_ATTRIBUTE(); - IfFailGo(m_pEmit->DefineCustomAttribute(*pmdField, tkAttr, PTROF_CUSTOM_ATTRIBUTE(), SIZEOF_CUSTOM_ATTRIBUTE(),0)); - } - - if (bConversionLoss) - { - IfFailGo(GetAttrType(ATTR_COMCONVERSIONLOSS, &tkAttr)); - DECLARE_CUSTOM_ATTRIBUTE(0); - FINISH_CUSTOM_ATTRIBUTE(); - IfFailGo(m_pEmit->DefineCustomAttribute(*pmdField, tkAttr, PTROF_CUSTOM_ATTRIBUTE(),SIZEOF_CUSTOM_ATTRIBUTE(),0)); - } - - // Set up the native description, if any. - if (cbNative > 0) - IfFailGo(m_pEmit->SetFieldMarshal(*pmdField, (PCCOR_SIGNATURE) qbNativeBuf.Ptr(), cbNative)); - - // Add the alias information if the type is an alias. - IfFailGo(_HandleAliasInfo(pITI, &psVar->elemdescVar.tdesc, *pmdField)); - - if (bConversionLoss) - { - hr = S_CONVERSION_LOSS; - ReportEvent(NOTIF_CONVERTWARNING, TLBX_I_UNCONVERTABLE_FIELD, m_szName, m_szMember); - } - -ErrExit: - if (m_szMember) - ::SysFreeString(m_szMember), m_szMember=0; - return (hr); -} // HRESULT CImportTlb::_ConvField() - -//***************************************************************************** -// Convert a dispatch property into a pair of get/set functions. -//***************************************************************************** -HRESULT CImportTlb::_ConvProperty( - ITypeInfo *pITI, // Containing TypeInfo. - MemberInfo *pMember) // VARDESC for the property. -{ - HRESULT hr; // A result. - mdMethodDef mdFuncGet; // A get function. - mdMethodDef mdFuncSet; // A set function. - mdProperty pdProperty; // Property on the two functions. - DWORD dwFlags; // Function flags. - WCHAR *pszName=0; // Decorated name of member. - CQuickArray<WCHAR> qbName; // Buffer for decorated name. - CQuickBytes qbComSig; // com signature buffer - ULONG cb; // Size of an element. - ULONG cbTotal = 0; // Total size of signature. - BYTE *pbSig; // Pointer to signature buffer. - BOOL bConversionLoss=false; // If true, some attributes were lost on conversion. - CQuickArray<BYTE> qbNativeBuf; // Native type buffer. - ULONG iNativeOfs=0; // Current offset in native type buffer. - VARDESC *psVar = pMember->m_psVar; - - // Check to see if the property is the NewEnum member. - if (PropertyIsNewEnum(pITI, psVar, pMember->m_iMember) == S_OK) - return _ConvNewEnumProperty(pITI, psVar, pMember); - - // Get the name. - IfFailGo(pITI->GetDocumentation(psVar->memid, &m_szMember, 0,0,0)); - - // Create the get signature. - IfFailGo(qbComSig.ReSizeNoThrow(CB_MAX_ELEMENT_TYPE * 2)); - pbSig = reinterpret_cast<BYTE*>(qbComSig.Ptr()); - cbTotal = cb = CorSigCompressData((ULONG)IMAGE_CEE_CS_CALLCONV_DEFAULT | IMAGE_CEE_CS_CALLCONV_HASTHIS, pbSig); - // Getter takes zero parameters. - cb = CorSigCompressData(0, &(pbSig[cb])); - cbTotal += cb; - // Getter returns the property type. - IfFailGo(_ConvSignature(pITI, &psVar->elemdescVar.tdesc, SIG_ELEM, qbComSig, cbTotal, &cbTotal, qbNativeBuf, 0, &iNativeOfs, FALSE)); - if (hr == S_CONVERSION_LOSS) - bConversionLoss = true; - - // Getter properties. - dwFlags = DEFAULT_PROPERTY_FUNC_FLAGS; - // If processing an implemented interface, remove the abstract bit. Methods on classes are not abstract. - if (m_ImplIface != eImplIfaceNone) - dwFlags &= ~mdAbstract; - - // Get the previously decorated name. Add interface name and make unique. - // m_szInterface should be non-null if processing an implemented interface; should be null otherwise. - _ASSERTE(m_ImplIface == eImplIfaceNone || m_szInterface != 0); - IfFailGo(qbName.ReSizeNoThrow(wcslen(pMember->m_pName)+2)); - wcscpy_s(qbName.Ptr(), wcslen(pMember->m_pName)+2, pMember->m_pName); - IfFailGo(GenerateUniqueMemberName(qbName, (PCCOR_SIGNATURE)qbComSig.Ptr(), cbTotal, m_szInterface, mdtMethodDef)); - pszName = qbName.Ptr(); - - // Create the get Accessor. - IfFailGo(m_pEmit->DefineMethod(m_tdTypeDef, pszName, dwFlags, (PCCOR_SIGNATURE) qbComSig.Ptr(), cbTotal, - 0/*RVA*/, DEFAULT_ITF_FUNC_IMPL_FLAGS, &mdFuncGet)); - - // Handle dispids for non-implemented interfaces, and for default interface - if (m_ImplIface != eImplIface) - { - // Set the Dispid CA. - _SetDispIDCA(pITI, pMember->m_iMember, psVar->memid, mdFuncGet, TRUE, NULL, FALSE); - } - - // If processing an implemented interface, set up MethodImpls. - if (m_ImplIface != eImplIfaceNone) - { - // Define a memberref on the implemented interface. - mdToken mrItfMember; - IfFailGo(m_pEmit->DefineMemberRef(m_tkInterface, pMember->m_pName, (PCCOR_SIGNATURE) qbComSig.Ptr(),cbTotal, &mrItfMember)); - - // Define a method impl. - IfFailGo(m_pEmit->DefineMethodImpl(m_tdTypeDef, mdFuncGet, mrItfMember)); - } - - // If not a read-only var, create the setter. - if ((psVar->wVarFlags & VARFLAG_FREADONLY) == 0) - { - // Create the setter signature. - IfFailGo(qbComSig.ReSizeNoThrow(CB_MAX_ELEMENT_TYPE * 3)); - pbSig = reinterpret_cast<BYTE*>(qbComSig.Ptr()); - cbTotal = cb = CorSigCompressData((ULONG)IMAGE_CEE_CS_CALLCONV_DEFAULT | IMAGE_CEE_CS_CALLCONV_HASTHIS, pbSig); - // Setter takes one parameter. - cb = CorSigCompressData(1, &(pbSig[cb])); - cbTotal += cb; - // Setter returns nothing. - cb = CorSigCompressData(ELEMENT_TYPE_VOID, &pbSig[cbTotal]); - cbTotal += cb; - // Setter takes the property type. - IfFailGo(_ConvSignature(pITI, &psVar->elemdescVar.tdesc, SIG_ELEM, qbComSig, cbTotal, &cbTotal, qbNativeBuf, 0, &iNativeOfs, FALSE)); - if (hr == S_CONVERSION_LOSS) - bConversionLoss = true; - - // Setter properties. - dwFlags = DEFAULT_PROPERTY_FUNC_FLAGS; - // If processing an implemented interface, remove the abstract bit. Methods on classes are not abstract. - if (m_ImplIface != eImplIfaceNone) - dwFlags &= ~mdAbstract; - - // Get the previously decorated name. Add interface name and make unique. - // m_szInterface should be non-null if processing an implemented interface; should be null otherwise. - _ASSERTE(m_ImplIface == eImplIfaceNone || m_szInterface != 0); - IfFailGo(qbName.ReSizeNoThrow(wcslen(pMember->m_pName2)+2)); - wcscpy_s(qbName.Ptr(), wcslen(pMember->m_pName2)+2, pMember->m_pName2); - IfFailGo(GenerateUniqueMemberName(qbName, (PCCOR_SIGNATURE)qbComSig.Ptr(), cbTotal, m_szInterface, mdtMethodDef)); - pszName = qbName.Ptr(); - - // Create the setter Accessor. - IfFailGo(m_pEmit->DefineMethod(m_tdTypeDef, pszName, dwFlags, (PCCOR_SIGNATURE) qbComSig.Ptr(),cbTotal, - 0/*RVA*/, DEFAULT_ITF_FUNC_IMPL_FLAGS, &mdFuncSet)); - - // Handle dispids for non-implemented interfaces, and for default interface - if (m_ImplIface != eImplIface) - { - // Set the Dispid CA. - _SetDispIDCA(pITI, pMember->m_iMember, psVar->memid, mdFuncSet, TRUE, NULL, FALSE); - } - - // If processing an implemented interface, set up MethodImpls. - if (m_ImplIface != eImplIfaceNone) - { - // Define a memberref on the implemented interface. - mdToken mrItfMember; - IfFailGo(m_pEmit->DefineMemberRef(m_tkInterface, pMember->m_pName2, (PCCOR_SIGNATURE) qbComSig.Ptr(),cbTotal, &mrItfMember)); - - // Define a method impl. - IfFailGo(m_pEmit->DefineMethodImpl(m_tdTypeDef, mdFuncSet, mrItfMember)); - } - } - else - { // read-only, setter method is nil. - mdFuncSet = mdMethodDefNil; - } - - // Create the property signature: 'type', or <fieldcallconv><type> - cbTotal = cb = CorSigCompressData((ULONG)IMAGE_CEE_CS_CALLCONV_PROPERTY, pbSig); - cb = CorSigCompressData(0, &(pbSig[cb])); - cbTotal += cb; - // Property is just the property type. - IfFailGo(_ConvSignature(pITI, &psVar->elemdescVar.tdesc, SIG_ELEM, qbComSig, cbTotal, &cbTotal, qbNativeBuf, 0, &iNativeOfs, FALSE)); - if (hr == S_CONVERSION_LOSS) - bConversionLoss = true; - - // Get the property name. Add interface name and make unique, if needed. - // m_szInterface should be non-null if processing an implemented interface; should be null otherwise. - _ASSERTE(m_ImplIface == eImplIfaceNone || m_szInterface != 0); - IfFailGo(qbName.ReSizeNoThrow(wcslen(m_szMember)+2)); - wcscpy_s(qbName.Ptr(), wcslen(m_szMember)+2, m_szMember); - IfFailGo(GenerateUniqueMemberName(qbName, (PCCOR_SIGNATURE)qbComSig.Ptr(), cbTotal, m_szInterface, mdtProperty)); - pszName = qbName.Ptr(); - - // Set up the Property on the two methods. - IfFailGo(m_pEmit->DefineProperty(m_tdTypeDef, pszName, 0/*dwFlags*/, (PCCOR_SIGNATURE) qbComSig.Ptr(),cbTotal, ELEMENT_TYPE_VOID, NULL/*default*/, -1, - mdFuncSet, mdFuncGet, NULL, &pdProperty)); - - // Handle dispids for non-implemented interfaces, and for default interface - if (m_ImplIface != eImplIface) - { - // Set the Dispid CA on the property. - long lDispSet = 1; - _SetDispIDCA(pITI, pMember->m_iMember, psVar->memid, pdProperty, TRUE, &lDispSet, FALSE); - - // If this property is default property, add a custom attribute to the class. - if (lDispSet == DISPID_VALUE) - IfFailGo(_AddDefaultMemberCa(m_tdTypeDef, m_szMember)); - } - - // Add the alias information if the type is an alias. - IfFailGo(_HandleAliasInfo(pITI, &psVar->elemdescVar.tdesc, pdProperty)); - - if (bConversionLoss) - { - hr = S_CONVERSION_LOSS; - ReportEvent(NOTIF_CONVERTWARNING, TLBX_I_UNCONVERTABLE_ARGS, m_szName, m_szMember); - } - -ErrExit: - if (m_szMember) - ::SysFreeString(m_szMember), m_szMember=0; - return (hr); -} // HRESULT CImportTlb::_ConvProperty() - -//***************************************************************************** -// Convert the NewEnum dispatch property into the GetEnumerator method. -//***************************************************************************** -HRESULT CImportTlb::_ConvNewEnumProperty( - ITypeInfo *pITI, // Containing TypeInfo. - VARDESC *psVar, // VARDESC for the property. - MemberInfo *pMember) -{ - HRESULT hr; // A result. - mdMethodDef mdGetEnum; // The GetEnumerator method. - CQuickBytes qbComSig; // com signature buffer - ULONG cb; // Size of an element. - ULONG cbTotal = 0; // Total size of signature. - BYTE *pbSig; // Pointer to signature buffer. - BOOL bConversionLoss=false; // If true, some attributes were lost on conversion. - CQuickArray<BYTE> qbNativeBuf; // Native type buffer. - ULONG iNativeOfs=0; // Current offset in native type buffer. - - // Get the name. - IfFailGo(pITI->GetDocumentation(psVar->memid, &m_szMember, 0,0,0)); - - // Create the GetEnumerator signature. - IfFailGo(qbComSig.ReSizeNoThrow(CB_MAX_ELEMENT_TYPE * 2)); - pbSig = reinterpret_cast<BYTE*>(qbComSig.Ptr()); - cbTotal = cb = CorSigCompressData((ULONG)IMAGE_CEE_CS_CALLCONV_DEFAULT | IMAGE_CEE_CS_CALLCONV_HASTHIS, pbSig); - - // GetEnumerator takes zero parameters. - cb = CorSigCompressData(0, &(pbSig[cb])); - cbTotal += cb; - - // Getter returns the property type. - IfFailGo(_ConvSignature(pITI, &psVar->elemdescVar.tdesc, SIG_ELEM, qbComSig, cbTotal, &cbTotal, qbNativeBuf, 0, &iNativeOfs, TRUE)); - if (hr == S_CONVERSION_LOSS) - bConversionLoss = true; - - // Create the GetEnumerator method. - IfFailGo(m_pEmit->DefineMethod(m_tdTypeDef, GET_ENUMERATOR_MEMBER_NAME, DEFAULT_INTERFACE_FUNC_FLAGS, (PCCOR_SIGNATURE) qbComSig.Ptr(), cbTotal, - 0/*RVA*/, DEFAULT_ITF_FUNC_IMPL_FLAGS, &mdGetEnum)); - - // Set the Dispid CA. - _SetDispIDCA(pITI, pMember->m_iMember, psVar->memid, mdGetEnum, TRUE, NULL, FALSE); - - // Add the alias information if the type is an alias. - IfFailGo(_HandleAliasInfo(pITI, &psVar->elemdescVar.tdesc, mdGetEnum)); - - if (bConversionLoss) - { - hr = S_CONVERSION_LOSS; - ReportEvent(NOTIF_CONVERTWARNING, TLBX_I_UNCONVERTABLE_ARGS, m_szName, m_szMember); - } - -ErrExit: - if (m_szMember) - ::SysFreeString(m_szMember), m_szMember=0; - return (hr); -} // HRESULT CImportTlb::_ConvNewEnumProperty() - -//***************************************************************************** -// Given an ITypeLib*, come up with a namespace name. Use the typelib name -// unless there is one specified via custom attribute. -// -// NOTE: This returns the member variable m_wzNamespace if the typelib -// is the importing typelib. That must not be freed! -//***************************************************************************** -HRESULT CImportTlb::GetNamespaceOfRefTlb( - ITypeLib *pITLB, // TypeLib for which to get namespace name. - BSTR *pwzNamespace, // Put the name here. - CImpTlbDefItfToClassItfMap **ppDefItfToClassItfMap) // Put def itf to class itf map here. -{ - mdAssemblyRef arDummy; - BSTR wzAsmName = NULL; - HRESULT hr = S_OK; - - // If already resolved, just return assembly ref. - if (!m_LibRefs.Find(pITLB, &arDummy, pwzNamespace, &wzAsmName, NULL, ppDefItfToClassItfMap)) - { - // Add a reference to the typelib. - IfFailGo(_AddTlbRef(pITLB, &arDummy, pwzNamespace, &wzAsmName, ppDefItfToClassItfMap)); - } - -ErrExit: - if (wzAsmName) - ::SysFreeString(wzAsmName); - - return hr; -} // HRESULT CImportTlb::GetNamespaceOfRefTlb() - -//***************************************************************************** -// Given a TYPEDESC, resolve the USERDEFINED to the TYPEKIND. -//***************************************************************************** -HRESULT CImportTlb::_ResolveTypeDescAliasTypeKind( - ITypeInfo *pITIAlias, // The typeinfo containing the typedesc. - TYPEDESC *ptdesc, // The typedesc. - TYPEKIND *ptkind) // Put the aliased typekind. -{ - HRESULT hr; // A result. - ITypeInfo *pTIResolved=0; // The resolved ITypeInfo. - TYPEATTR *psResolved=0; // The resolved TypeInfo's TYPEATTR - - if (ptdesc->vt != VT_USERDEFINED) - { - *ptkind = TKIND_MAX; - return S_FALSE; - } - - hr = _ResolveTypeDescAlias(pITIAlias, ptdesc, &pTIResolved, &psResolved); - if (hr == S_OK) - *ptkind = psResolved->typekind; - else - *ptkind = TKIND_MAX; - - if (psResolved) - pTIResolved->ReleaseTypeAttr(psResolved); - if (pTIResolved) - pTIResolved->Release(); - - return hr; -} // HRESULT CImportTlb::_ResolveTypeDescAliasTypeKind() - -//***************************************************************************** -// Given a TYPEDESC in a TypeInfo, eliminate aliases (get to the aliased -// type). -//***************************************************************************** -HRESULT CImportTlb::_ResolveTypeDescAlias( - ITypeInfo *pITIAlias, // The typeinfo containing the typedesc. - const TYPEDESC *ptdesc, // The typedesc. - ITypeInfo **ppTIResolved, // Put the aliased ITypeInfo here. - TYPEATTR **ppsAttrResolved, // Put the ITypeInfo's TYPEATTR here. - GUID *pGuid) // Caller may want aliased object's guid. -{ - HRESULT hr; // A result. - ITypeInfo *pITI=0; // Referenced typeinfo. - TYPEATTR *psAttr=0; // TYPEATTR of referenced typeinfo. - - // If the TDESC isn't a USERDEFINED, it is already resolved. - if (ptdesc->vt != VT_USERDEFINED) - { - *ppTIResolved = pITIAlias; - pITIAlias->AddRef(); - // Need to addref the [out] psAttr. Only way to do it: - IfFailGo(pITIAlias->GetTypeAttr(ppsAttrResolved)); - hr = S_FALSE; - goto ErrExit; - } - - // The TYPEDESC is a USERDEFINED. Get the TypeInfo. - IfFailGo(pITIAlias->GetRefTypeInfo(ptdesc->hreftype, &pITI)); - IfFailGo(pITI->GetTypeAttr(&psAttr)); - - // If the caller needs the aliased object's guid, get it now. - if (pGuid && *pGuid == GUID_NULL && psAttr->guid != GUID_NULL) - *pGuid = psAttr->guid; - - // If the userdefined typeinfo is not itself an alias, then it is what the alias aliases. - // Also, if the userdefined typeinfo is an alias to a builtin type, then the builtin - // type is what the alias aliases. - if (psAttr->typekind != TKIND_ALIAS || psAttr->tdescAlias.vt != VT_USERDEFINED) - { - *ppsAttrResolved = psAttr; - *ppTIResolved = pITI; - if (psAttr->typekind == TKIND_ALIAS) - hr = S_FALSE; - psAttr = 0; - pITI = 0; - goto ErrExit; - } - - // The userdefined type was itself an alias to a userdefined type. Alias to what? - hr = _ResolveTypeDescAlias(pITI, &psAttr->tdescAlias, ppTIResolved, ppsAttrResolved, pGuid); - -ErrExit: - if (psAttr) - pITI->ReleaseTypeAttr(psAttr); - if (pITI) - pITI->Release(); - return hr; -} // HRESULT CImportTlb::_ResolveTypeDescAlias() - -//***************************************************************************** -// Create the TypeInfo records (AKA classes, AKA critters). -//***************************************************************************** -HRESULT CImportTlb::GetKnownTypeToken( - VARTYPE vt, // The type for which the token is desired. - mdTypeRef *ptr) // Put the token here. -{ - HRESULT hr = S_OK; // A result. - - _ASSERTE( - (vt >= VT_CY && vt <= VT_DECIMAL) || (vt == VT_SAFEARRAY) || (vt == VT_SLOT_FOR_GUID) || - (vt == VT_SLOT_FOR_IENUMERABLE) || (vt == VT_SLOT_FOR_MULTICASTDEL) || (vt == VT_SLOT_FOR_TYPE) || - (vt == VT_SLOT_FOR_STRINGBUF)); - - // If it has already been added, just return it. - if (m_tkKnownTypes[vt]) - { - *ptr = m_tkKnownTypes[vt]; - goto ErrExit; - } - - // Not yet created, so create the typeref now. - switch (vt) - { - //=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ - // WARNING: the VT_EMPTY slot is used for System.GUID!! - case VT_SLOT_FOR_GUID: - _ASSERTE(VT_SLOT_FOR_GUID == VT_EMPTY); - IfFailGo(m_TRMap.DefineTypeRef( - m_pEmit, // The emit scope. - m_arSystem, // The system assemblyref. - TLB_CLASSLIB_GUID, // URL of the TypeDef, wide chars. - &m_tkKnownTypes[VT_SLOT_FOR_GUID])); // Put mdTypeRef here - break; - - // WARNING: the VT_NULL slot is used for System.Collections.IEnumerable!! - case VT_SLOT_FOR_IENUMERABLE: - _ASSERTE(VT_SLOT_FOR_IENUMERABLE == VT_NULL); - IfFailGo(m_TRMap.DefineTypeRef( - m_pEmit, // The emit scope. - m_arSystem, // The system assemblyref. - TLB_CLASSLIB_IENUMERABLE, // URL of the TypeDef, wide chars. - &m_tkKnownTypes[VT_SLOT_FOR_IENUMERABLE])); // Put mdTypeRef here - break; - - // WARNING: the VT_I2 slot is used for System.MulticastDelegate!! - case VT_SLOT_FOR_MULTICASTDEL: - _ASSERTE(VT_SLOT_FOR_MULTICASTDEL == VT_I2); - IfFailGo(m_TRMap.DefineTypeRef( - m_pEmit, // The emit scope. - m_arSystem, // The system assemblyref. - TLB_CLASSLIB_MULTICASTDELEGATE, // URL of the TypeDef, wide chars. - &m_tkKnownTypes[VT_SLOT_FOR_MULTICASTDEL])); // Put mdTypeRef here - break; - - // WARNING: the VT_I4 slot is used for System.Type!! - case VT_SLOT_FOR_TYPE: - _ASSERTE(VT_SLOT_FOR_TYPE == VT_I4); - IfFailGo(m_TRMap.DefineTypeRef( - m_pEmit, // The emit scope. - m_arSystem, // The system assemblyref. - TLB_CLASSLIB_TYPE, // URL of the TypeDef, wide chars. - &m_tkKnownTypes[VT_SLOT_FOR_TYPE])); // Put mdTypeRef here - break; - - // WARNING: the VT_I8 slot is used for System.Text.StringBuilder!! - case VT_SLOT_FOR_STRINGBUF: - _ASSERTE(VT_SLOT_FOR_STRINGBUF == VT_I8); - IfFailGo(m_TRMap.DefineTypeRef( - m_pEmit, // The emit scope. - m_arSystem, // The system assemblyref. - TLB_CLASSLIB_STRINGBUFFER, // URL of the TypeDef, wide chars. - &m_tkKnownTypes[VT_SLOT_FOR_STRINGBUF])); // Put mdTypeRef here - break; - - case VT_CY: - IfFailGo(m_TRMap.DefineTypeRef( - m_pEmit, // The emit scope. - m_arSystem, // The system assemblyref. - TLB_CLASSLIB_DECIMAL, // URL of the TypeDef, wide chars. - &m_tkKnownTypes[VT_CY])); // Put mdTypeRef here - break; - - case VT_DATE: - IfFailGo(m_TRMap.DefineTypeRef( - m_pEmit, // The emit scope. - m_arSystem, // The system assemblyref. - TLB_CLASSLIB_DATE, // URL of the TypeDef, wide chars. - &m_tkKnownTypes[VT_DATE])); // Put mdTypeRef here - break; - - case VT_DECIMAL: - IfFailGo(m_TRMap.DefineTypeRef( - m_pEmit, // The emit scope. - m_arSystem, // The system assemblyref. - TLB_CLASSLIB_DECIMAL, // URL of the TypeDef, wide chars. - &m_tkKnownTypes[VT_DECIMAL])); // Put mdTypeRef here - break; - - case VT_SAFEARRAY: - IfFailGo(m_TRMap.DefineTypeRef( - m_pEmit, // The emit scope. - m_arSystem, // The system assemblyref. - TLB_CLASSLIB_ARRAY, // URL of the TypeDef, wide chars. - &m_tkKnownTypes[VT_SAFEARRAY])); // Put mdTypeRef here - break; - - default: - _ASSERTE(!"Unknown type in GetKnownTypes"); - IfFailGo(E_INVALIDARG); - } - - _ASSERTE(!IsNilToken(m_tkKnownTypes[vt])); - *ptr = m_tkKnownTypes[vt]; - -ErrExit: - return hr; -} // HRESULT CImportTlb::GetKnownTypeToken() - - -//***************************************************************************** -// Given an ITypeInfo for a coclass, return an ITypeInfo for the default -// interface. This is either the explicitly marked default, or the first -// non-source interface. -//***************************************************************************** -HRESULT CImportTlb::GetDefaultInterface( // Error, S_OK or S_FALSE. - ITypeInfo *pCoClassTI, // The TypeInfo of the coclass. - ITypeInfo **pDefaultItfTI) // The returned default interface. -{ - HRESULT hr; // A result - HREFTYPE href; // HREFTYPE of an implemented interface. - INT ImplFlags; // ImplType flags. - ITypeInfo *pITI=NULL; // ITypeInfo for an interface. - TYPEATTR *pCoClassTypeAttr; // The type attributes of the coclass. - int NumInterfaces; // The number of interfaces on the coclass. - int i; // A counter. - - // Initialize the default interface to NULL. - *pDefaultItfTI = NULL; - - // Retrieve the number of interfaces the coclass has - IfFailGo(pCoClassTI->GetTypeAttr(&pCoClassTypeAttr)); - NumInterfaces = pCoClassTypeAttr->cImplTypes; - pCoClassTI->ReleaseTypeAttr(pCoClassTypeAttr); - - for (i=0; i < NumInterfaces; i++) - { - IfFailGo(pCoClassTI->GetImplTypeFlags(i, &ImplFlags)); - - if ((ImplFlags & (IMPLTYPEFLAG_FSOURCE | IMPLTYPEFLAG_FDEFAULT)) == IMPLTYPEFLAG_FDEFAULT) - { - // We have found a default interface. - if (*pDefaultItfTI) - (*pDefaultItfTI)->Release(); - - IfFailGo(pCoClassTI->GetRefTypeOfImplType(i, &href)); - IfFailGo(pCoClassTI->GetRefTypeInfo(href, pDefaultItfTI)); - break; - } - else if (!(ImplFlags & IMPLTYPEFLAG_FSOURCE) && !(*pDefaultItfTI)) - { - // If this is the first normal interface we encounter then we need to - // hang on to it in case we don't find any default interfaces. If that - // happens then this is the one that will be returned. - IfFailGo(pCoClassTI->GetRefTypeOfImplType(i, &href)); - IfFailGo(pCoClassTI->GetRefTypeInfo(href, pDefaultItfTI)); - } - } - - // Return either S_OK or S_FALSE depending on if we have found a default interface. - if (*pDefaultItfTI) - return S_OK; - else - return S_FALSE; - -ErrExit: - if (pITI) - pITI->Release(); - - return hr; -} // HRESULT CImportTlb::GetDefaultInterface() - -//***************************************************************************** -// Given a TypeInfo, return a TypeDef/TypeRef token. -//***************************************************************************** -HRESULT CImportTlb::_GetTokenForTypeInfo( - ITypeInfo *pITI, // ITypeInfo for which to get token. - BOOL bConvDefItfToClassItf, // If TRUE, convert the def itf to its class itf. - mdToken *pToken, // Put the token here. - __out_ecount (chTypeRef) __out_opt LPWSTR pszTypeRef, // Optional, put the name here. - int chTypeRef, // Size of the name buffer in characters. - int *pchTypeRef, // Optional, put size of name here. - BOOL bAsmQualifiedName) // Assembly qualified name or not? -{ - HRESULT hr; // A result. - ITypeLib *pITLB=0; // Containing typelib. - BSTR bstrNamespace=0; // Namespace of the type. - BSTR bstrFullName=0; // Fully qualified name of type. - BSTR bstrTempName=0; // Temp name. - BSTR bstrAsmName=0; // Assembly name. - LPCWSTR strTypeName=0; // The type name. - mdAssemblyRef ar; // The typelib's assembly ref. - TYPEATTR* psAttr = 0; // The TYPEATTR for the type info. - CImpTlbDefItfToClassItfMap *pDefItfToClassItfMap; // The default interface to class interface map. - - // Get the library. - IfFailGo(pITI->GetContainingTypeLib(&pITLB, 0)); - - // Resolve the external reference. - IfFailGo(_AddTlbRef(pITLB, &ar, &bstrNamespace, &bstrAsmName, &pDefItfToClassItfMap)); - - // If are converting default interfaces to class interfaces, then check - // to see if we need to do the convertion for the current ITypeInfo. - if (bConvDefItfToClassItf) - { - // Retrieve the TYPEATTR. - IfFailGo(pITI->GetTypeAttr(&psAttr)); - - // If we are dealing with an interface, then check to see if there - // is a class interface we should use. - if (psAttr->typekind == TKIND_INTERFACE || psAttr->typekind == TKIND_DISPATCH) - { - strTypeName = pDefItfToClassItfMap->GetClassItfName(psAttr->guid); - } - } - - // If we haven't found a class interface, then use the current interface. - if (!strTypeName) - { - // Get the name of the typeinfo. - IfFailGo(GetManagedNameForTypeInfo(pITI, bstrNamespace, NULL, &bstrFullName)); - strTypeName = bstrFullName; - } - - // Give name back to caller, if desired. - if (pszTypeRef) - wcsncpy_s(pszTypeRef, chTypeRef, strTypeName, chTypeRef-1); - if (pchTypeRef) - *pchTypeRef = (int)(wcslen(pszTypeRef) + 1); - - // Define the TypeRef (will return any existing typeref). - IfFailGo(m_TRMap.DefineTypeRef(m_pEmit, ar, strTypeName, pToken)); - - // If the caller desires an assembly qualified name, then provide it. - if (bAsmQualifiedName) - { - int cchAsmQualifiedName = SysStringLen(bstrFullName) + SysStringLen(bstrAsmName) + 2; - IfNullGo(bstrTempName = ::SysAllocStringLen(0, cchAsmQualifiedName)); - ns::MakeAssemblyQualifiedName(bstrTempName, cchAsmQualifiedName + 1, bstrFullName, SysStringLen(bstrFullName), bstrAsmName, SysStringLen(bstrAsmName)); - SysFreeString(bstrFullName); - bstrFullName = bstrTempName; - } - - // Give name back to caller, if desired. - if (pszTypeRef) - wcsncpy_s(pszTypeRef, chTypeRef, bstrFullName, chTypeRef-1); - if (pchTypeRef) - *pchTypeRef = (int)(wcslen(pszTypeRef) + 1); - -ErrExit: - if (bstrNamespace) - ::SysFreeString(bstrNamespace); - if (bstrFullName) - ::SysFreeString(bstrFullName); - if (bstrAsmName) - ::SysFreeString(bstrAsmName); - if (pITLB) - pITLB->Release(); - if (psAttr) - pITI->ReleaseTypeAttr(psAttr); - - return (hr); -} // HRESULT CImportTlb::_GetTokenForTypeInfo() - -//***************************************************************************** -// Given a TypeInfo for a source interface, creates a new event interface -// if none exists or returns an existing one. -//***************************************************************************** -HRESULT CImportTlb::_GetTokenForEventItf(ITypeInfo *pSrcItfITI, mdTypeRef *ptr) -{ -#ifndef DACCESS_COMPILE - HRESULT hr = S_OK; // A result. - ImpTlbEventInfo* pEventInfo; // The event information. - BSTR bstrSrcItfName = NULL; // The name of the CoClass. - CQuickArray<WCHAR> qbEventItfName; // The name of the event interface. - CQuickArray<WCHAR> qbEventProviderName; // The name of the event provider. - mdToken tkAttr; // Custom attribute type. - BSTR szOldName = NULL; // The old value m_tdTypeDef. - mdTypeDef tdOldTypeDef = NULL; // The old value m_szName. - TYPEATTR* psAttr = 0; // The TYPEATTR for the source interface. - mdTypeRef trEventItf; // A type ref to the event interface. - ITypeLib* pTypeTLB; // The typelib containing this interface. - mdAssemblyRef ar; // Dummy AssmRef. - BSTR wzNamespace=0; // Namespace of the event interface assembly. - BSTR wzAsmName=0; // Assembly name of the event interface assembly. - Assembly* SrcItfAssembly=0; // The Source Event Interface assembly. - CQuickArray<WCHAR> qbSrcItfName; // The name of the source interface. - CImpTlbDefItfToClassItfMap *pDefItfToClassItfMap; // The default interface to class interface map. - BOOL fInheritsIEnum = FALSE; - - // Retrieve the namespace of the typelib containing this source interface. - IfFailGo(pSrcItfITI->GetContainingTypeLib(&pTypeTLB, NULL)); - - // Resolve the external reference. - IfFailGo(_AddTlbRef(pTypeTLB, &ar, &wzNamespace, &wzAsmName, &pDefItfToClassItfMap)); - - // Get the assembly + namespace the source interface resides in. - // May return all NULL - indicating the importing assembly. - m_LibRefs.Find(pTypeTLB, &ar, &wzNamespace, &wzAsmName, &SrcItfAssembly, NULL); - if (SrcItfAssembly == NULL) - SrcItfAssembly = m_pAssembly; - - // Retrieve the full name of the source interface. - if (wzNamespace) - IfFailGo(GetManagedNameForTypeInfo(pSrcItfITI, (WCHAR*)wzNamespace, NULL, &bstrSrcItfName)); - else - IfFailGo(GetManagedNameForTypeInfo(pSrcItfITI, m_wzNamespace, NULL, &bstrSrcItfName)); - - // Start by looking up the event information for the source itf type info. - pEventInfo = m_EventInfoMap.FindEventInfo(bstrSrcItfName); - if (pEventInfo) - { - SysFreeString(bstrSrcItfName); - *ptr = pEventInfo->trEventItf; - return S_OK; - } - - // Store the old values of the ITypeInfo name and of the current type def. - szOldName = m_szName; - tdOldTypeDef = m_tdTypeDef; - m_szName = NULL; - - // Get some information about the TypeInfo. - IfFailGo(pSrcItfITI->GetDocumentation(MEMBERID_NIL, &m_szName, 0, 0, 0)); - IfFailGo(pSrcItfITI->GetTypeAttr(&psAttr)); - - if (ExplicitlyImplementsIEnumerable(pSrcItfITI, psAttr) == S_OK) - fInheritsIEnum = TRUE; - - // Generate a unique name for the event interface which will be of the form: - // <ImportingAssemblyNamespace>.<SrcItfName>_Event<PotentialSuffix> - - // Strip the namespace - IfFailGo(qbSrcItfName.ReSizeNoThrow(wcslen(bstrSrcItfName) + 2)); - ns::SplitPath((WCHAR*)bstrSrcItfName, NULL, 0, qbSrcItfName.Ptr(), (int)wcslen(bstrSrcItfName) + 1); - - // Add the namespace of the importing typelib and the event suffix - IfFailGo(qbEventItfName.ReSizeNoThrow(qbSrcItfName.Size() + wcslen(m_wzNamespace) + EVENT_ITF_SUFFIX_LENGTH + 7)); - StringCchPrintf(qbEventItfName.Ptr(), qbEventItfName.Size(), W("%s.%s%s"), m_wzNamespace, qbSrcItfName.Ptr(), EVENT_ITF_SUFFIX); - IfFailGo(GenerateUniqueTypeName(qbEventItfName)); - - // Generate a unique name for the event provider which will be of the form: - // <ImportingAssemblyNamespace>.<SrcItfName>_EventProvider<PotentialSuffix> - - // Add the namespace of the imporing typelib and the event suffix - IfFailGo(qbEventProviderName.ReSizeNoThrow(qbSrcItfName.Size() + wcslen(m_wzNamespace) + EVENT_PROVIDER_SUFFIX_LENGTH + 7)); - StringCchPrintf(qbEventProviderName.Ptr(), qbEventProviderName.Size(), W("%s.%s%s"), m_wzNamespace, qbSrcItfName.Ptr(), EVENT_PROVIDER_SUFFIX); - IfFailGo(GenerateUniqueTypeName(qbEventProviderName)); - - // Add the event provider as a reserved name. - m_ReservedNames.AddReservedName(qbEventProviderName.Ptr()); - - // Create the typedef for the event interface. - IfFailGo(m_pEmit->DefineTypeDef(qbEventItfName.Ptr(), tdPublic | tdInterface | tdAbstract, mdTypeDefNil, NULL, &m_tdTypeDef)); - - // Hide the event interface from the VB object browser (_Event) - _SetHiddenCA(m_tdTypeDef); - - // Make the interface ComVisible(false). - { - DECLARE_CUSTOM_ATTRIBUTE(sizeof(BYTE)); - BUILD_CUSTOM_ATTRIBUTE(BYTE, FALSE); - IfFailGo(GetAttrType(ATTR_COMVISIBLE, &tkAttr)); - FINISH_CUSTOM_ATTRIBUTE(); - IfFailGo(m_pEmit->DefineCustomAttribute(m_tdTypeDef, tkAttr, PTROF_CUSTOM_ATTRIBUTE(), SIZEOF_CUSTOM_ATTRIBUTE(), 0)); - } - - // Set the ComEventInterface CA on the interface. - { - CQuickBytes asmQualifiedSrcItfName; - if (!ns::MakeAssemblyQualifiedName(asmQualifiedSrcItfName, bstrSrcItfName, wzAsmName)) - IfFailGo(E_OUTOFMEMORY); - DECLARE_DYNLEN_CUSTOM_ATTRIBUTE(wcslen((WCHAR*)asmQualifiedSrcItfName.Ptr()) + 5 + wcslen(qbEventProviderName.Ptr()) + 5); - APPEND_WIDE_STRING_TO_CUSTOM_ATTRIBUTE((WCHAR*)asmQualifiedSrcItfName.Ptr()); - APPEND_WIDE_STRING_TO_CUSTOM_ATTRIBUTE(qbEventProviderName.Ptr()); - IfFailGo(GetAttrType(ATTR_COMEVENTINTERFACE, &tkAttr)); - FINISH_DYNLEN_CUSTOM_ATTRIBUTE(); - IfFailGo(m_pEmit->DefineCustomAttribute(m_tdTypeDef, tkAttr, PTROF_CUSTOM_ATTRIBUTE(), SIZEOF_CUSTOM_ATTRIBUTE(), 0)); - } - - // Add the add_XXX and remove_XXX methods to the event interface. - IfFailGo(_ConvSrcIfaceMembers(pSrcItfITI, psAttr, fInheritsIEnum)); - - // Define a typeref for the event interface. - IfFailGo(m_pEmit->DefineTypeRefByName(TokenFromRid(1, mdtModule), qbEventItfName.Ptr(), &trEventItf)); - - // Add the event info to the map. - IfFailGo(m_EventInfoMap.AddEventInfo(bstrSrcItfName, trEventItf, qbEventItfName.Ptr(), qbEventProviderName.Ptr(), SrcItfAssembly)); - - // Set the out type ref. - *ptr = trEventItf; - -ErrExit: - if (bstrSrcItfName) - ::SysFreeString(bstrSrcItfName); - if (m_szName) - ::SysFreeString(m_szName); - if (psAttr) - pSrcItfITI->ReleaseTypeAttr(psAttr); - if (pTypeTLB) - pTypeTLB->Release(); - - // Restore the initial values for the ITypeInfo name and the type def. - m_szName = szOldName; - m_tdTypeDef = tdOldTypeDef; - - return (hr); -#else - DacNotImpl(); - return E_NOTIMPL; -#endif // #ifndef DACCESS_COMPILE -} // HRESULT CImportTlb::_GetTokenForEventItf() - -//***************************************************************************** -// Creates an interface with the same name as the class and which implements -// the default interface and the default event interface. -//***************************************************************************** -HRESULT CImportTlb::_CreateClassInterface(ITypeInfo *pCoClassITI, ITypeInfo *pDefItfITI, mdTypeRef trDefItf, mdTypeRef rtDefEvItf, mdToken *ptr) -{ - HRESULT hr = S_OK; // A result. - CQuickArray<mdToken> rImpls; // Array of implemented interfaces. - int ixImpl = -1; // Index into rImpls for implemented interface. - mdTypeDef tdTypeDef; // The class interface typedef. - BSTR bstrFullName = NULL; // The name of the CoClass. - TYPEATTR *psAttrIface=0; // TYPEATTR for an interface. - CQuickArray<WCHAR> qbClassName; // The name of the class. - - IfFailGo(rImpls.ReSizeNoThrow(3)); - memset(rImpls.Ptr(), 0, 3 * sizeof(mdToken)); - if (trDefItf) - rImpls[++ixImpl] = trDefItf; - if (rtDefEvItf) - rImpls[++ixImpl] = rtDefEvItf; - - // Retrieve the TypeAttr for the interface. - if (pDefItfITI) - IfFailGo(pDefItfITI->GetTypeAttr(&psAttrIface)); - - // Retrieve the name of the CoClass (use the original name if this is an alias). - IfFailGo(GetManagedNameForTypeInfo(m_pOrigITI, m_wzNamespace, NULL, &bstrFullName)); - - // Create the typedef. - IfFailGo(m_pEmit->DefineTypeDef(bstrFullName, rdwTypeFlags[TKIND_INTERFACE], mdTypeDefNil, 0, &tdTypeDef)); - - // Set the IID to the IID of the default interface. - IfFailGo(_AddGuidCa(tdTypeDef, psAttrIface ? psAttrIface->guid : GUID_NULL)); - - // Add the CoClass CA to the interface. - _AddStringCa(ATTR_COCLASS, tdTypeDef, m_szMngName); - - // Add the implemented interfaces and event interfaces to the TypeDef. - IfFailGo(m_pEmit->SetTypeDefProps(tdTypeDef, ULONG_MAX/*Classflags*/, - ULONG_MAX, (mdToken*)rImpls.Ptr())); - - // Set the out type def. - *ptr = tdTypeDef; - -ErrExit: - if (bstrFullName) - ::SysFreeString(bstrFullName); - if (psAttrIface) - pDefItfITI->ReleaseTypeAttr(psAttrIface); - - return (hr); -} // HRESULT CImportTlb::_CreateClassInterface() - -//***************************************************************************** -// Creates an interface with the same name as the class and which implements -// the default interface and the default event interface. -//***************************************************************************** -HRESULT CImportTlb::GetManagedNameForCoClass(ITypeInfo *pITI, CQuickArray<WCHAR> &qbClassName) -{ - HRESULT hr = S_OK; // A result. - BSTR bstrFullName=0; // Fully qualified name of type. - - // Retrieve the name of the CoClass. - IfFailGo(GetManagedNameForTypeInfo(pITI, m_wzNamespace, NULL, &bstrFullName)); - - // Resize the class name to accomodate the Class and potential suffix. - IfFailGo(qbClassName.ReSizeNoThrow(wcslen(bstrFullName) + CLASS_SUFFIX_LENGTH + 6)); - - // Set the class name to the CoClass name suffixed with Class. - StringCchPrintf(qbClassName.Ptr(), qbClassName.Size(), W("%s%s"), bstrFullName, CLASS_SUFFIX); - - // Generate a unique name for the class. - IfFailGo(GenerateUniqueTypeName(qbClassName)); - -ErrExit: - if (bstrFullName) - ::SysFreeString(bstrFullName); - - return (hr); -} // HRESULT CImportTlb::GetManagedNameForCoClass() - -//***************************************************************************** -// Creates an interface with the same name as the class and which implements -// the default interface and the default event interface. -//***************************************************************************** -HRESULT CImportTlb::GenerateUniqueTypeName(CQuickArray<WCHAR> &qbTypeName) -{ - HRESULT hr = S_OK; // A result. - WCHAR *pSuffix=0; // Location for suffix. - size_t cchSuffix; - WCHAR *pName=0; // The name without the namespace. - int iSuffix=2; // Starting value for suffix. - mdToken td; // For looking up a TypeDef. - BSTR szTypeInfoName=0; // Name of a typeinfo. - ITypeInfo *pITI=0; // A typeinfo. - - // Resize the class name to accomodate the Class and potential suffix. - IfFailGo(qbTypeName.ReSizeNoThrow(wcslen(qbTypeName.Ptr()) + 6)); - - // Set the suffix pointer. - pSuffix = qbTypeName.Ptr() + wcslen(qbTypeName.Ptr()); - cchSuffix = qbTypeName.Size() - wcslen(qbTypeName.Ptr()); - - // Set the name pointer. - WCHAR* pTemp = ns::FindSep(qbTypeName.Ptr()); - if (pTemp == NULL) - pName = qbTypeName.Ptr(); - else - pName = pTemp + 1; - - // Attempt to find a class name that is not in use. - for (;;) - { - // First check to see if the type name is in use in the metadata we - // have emitted so far. - hr = m_pImport->FindTypeDefByName(qbTypeName.Ptr(), mdTypeDefNil, &td); - if (hr == CLDB_E_RECORD_NOTFOUND) - { - // It is not in use in the metadata but we still need to check the - // typelib because the type might not have been emitted yet. - USHORT cReq = 4; - USHORT cFound = cReq; - BOOL bTypeInTlb = FALSE; - CQuickArray<ITypeInfo *> qbTI; - CQuickArray<MEMBERID> qbMemId; - - // Retrieve all the instances of the name in the typelib. - do - { - // Double the number of requested names. - cReq *= 2; - - // Resize the array's to accomodate the resquested names. - IfFailGo(qbTI.ReSizeNoThrow(cReq)); - IfFailGo(qbMemId.ReSizeNoThrow(cReq)); - - // Request the names. - cFound = cReq; - IfFailGo(m_pITLB->FindName(pName, 0, qbTI.Ptr(), qbMemId.Ptr(), &cFound)); - - // Release all the ITypeInfo's. - for (int i = 0; i < cFound; i++) - qbTI[i]->Release(); - } - while (cReq == cFound); - - // Check to see if one of the instances of the name is for a type. - for (int i = 0; i < cFound; i++) - { - if (qbMemId[i] == MEMBERID_NIL) - { - bTypeInTlb = TRUE; - break; - } - } - - // If the type name exists in the typelib, but we didn't find it as a type, - // we still need to do a deeper check, due to how FindName() works. - if (!bTypeInTlb && cFound > 0) - { - int cTi; // Count of TypeInfos. - int i; // Loop control. - - //@todo: this iterates over every typeinfo every time! We could cache - // the names, and skip the types already converted. However, this should - // be pretty rare. - - // How many TypeInfos? - IfFailGo(cTi = m_pITLB->GetTypeInfoCount()); - - // Iterate over them. - for (i=0; i<cTi; ++i) - { - // Get the TypeInfo, and its name. - IfFailGo(m_pITLB->GetTypeInfo(i, &pITI)); - IfFailGo(pITI->GetDocumentation(MEMBERID_NIL, &szTypeInfoName, 0, 0, 0)); - if (wcscmp(pName, szTypeInfoName) == 0) - { - bTypeInTlb = TRUE; - break; - } - - // Release for next TypeInfo. - ::SysFreeString(szTypeInfoName); - szTypeInfoName = 0; - pITI->Release(); - pITI = 0; - } - } - - // The type name is not in the typelib and not in the metadata then we still - // need to check to see if is a reserved name. - if (!bTypeInTlb) - { - if (!m_ReservedNames.IsReservedName(qbTypeName.Ptr())) - { - // The name is not a reserved name so we can use it. - break; - } - } - } - IfFailGo(hr); - - // Append the new suffix to the class name. - StringCchPrintf(pSuffix, cchSuffix, W("_%i"), iSuffix++); - } - -ErrExit: - if (szTypeInfoName) - ::SysFreeString(szTypeInfoName); - if (pITI) - pITI->Release(); - return (hr); -} // HRESULT CImportTlb::GenerateUniqueTypeName() - -//***************************************************************************** -// Generate a unique member name based on the interface member name. -//***************************************************************************** -HRESULT CImportTlb::GenerateUniqueMemberName(// S_OK or error - CQuickArray<WCHAR> &qbMemberName, // Original name of member. - PCCOR_SIGNATURE pSig, // Signature of the member. - ULONG cSig, // Length of the signature. - LPCWSTR szPrefix, // Possible prefix for decoration. - mdToken type) // Is it a property? (Not a method?) -{ - HRESULT hr; // A result. - mdToken tkMember; // Dummy location for token. - WCHAR *pSuffix=0; // Location for suffix. - size_t cchSuffix = 0; - int iSuffix=2; // Starting value for suffix. - - // Try to find a member name that is not already in use. - for (;;) - { // See if this is (finally) a unique member or property. - switch (type) - { - case mdtProperty: - hr = FindProperty(m_tdTypeDef, qbMemberName.Ptr(), 0, 0, &tkMember); - // If name is OK as property, check that there is no method or - // property with the name. - if (hr == CLDB_E_RECORD_NOTFOUND) - hr = FindMethod(m_tdTypeDef, qbMemberName.Ptr(), 0,0, &tkMember); - if (hr == CLDB_E_RECORD_NOTFOUND) - hr = FindEvent(m_tdTypeDef, qbMemberName.Ptr(), &tkMember); - break; - case mdtMethodDef: - hr = FindMethod(m_tdTypeDef, qbMemberName.Ptr(), pSig, cSig, &tkMember); - // If name is OK as method, check that there is no property or - // event with the name. - if (hr == CLDB_E_RECORD_NOTFOUND) - hr = FindProperty(m_tdTypeDef, qbMemberName.Ptr(), 0,0, &tkMember); - if (hr == CLDB_E_RECORD_NOTFOUND) - hr = FindEvent(m_tdTypeDef, qbMemberName.Ptr(), &tkMember); - break; - case mdtEvent: - hr = FindEvent(m_tdTypeDef, qbMemberName.Ptr(), &tkMember); - // If name is OK as event, check that there is no property or - // method with the name. - if (hr == CLDB_E_RECORD_NOTFOUND) - hr = FindProperty(m_tdTypeDef, qbMemberName.Ptr(), 0,0, &tkMember); - if (hr == CLDB_E_RECORD_NOTFOUND) - hr = FindMethod(m_tdTypeDef, qbMemberName.Ptr(), 0,0, &tkMember); - break; - default: - // Unexpected type. Make noise, but let it pass. - _ASSERTE(!"Unexpected token type in GenerateUniqueMemberName"); - hr = CLDB_E_RECORD_NOTFOUND; - } - - // If name was not found, it is unique. - if (hr == CLDB_E_RECORD_NOTFOUND) - { - hr = S_OK; - goto ErrExit; - } - // Test for failure. - IfFailGo(hr); - - // Make a test decoration. - if (szPrefix) - { - size_t iLenPrefix, iLenName; - iLenPrefix = wcslen(szPrefix); - iLenName = wcslen(qbMemberName.Ptr()); - IfFailGo(qbMemberName.ReSizeNoThrow(iLenName + iLenPrefix + 2)); - // Shift by prefix length, plus '_'. Note use of overlap-safe move. - memmove(&qbMemberName[iLenPrefix+1], &qbMemberName[0], (iLenName+1)*sizeof(WCHAR)); - wcscpy_s(qbMemberName.Ptr(), iLenPrefix + 1, szPrefix); - qbMemberName[iLenPrefix] = W('_'); - szPrefix = 0; - // Try again with prefix before trying a suffix. - continue; - } - if (!pSuffix) - { - IfFailGo(qbMemberName.ReSizeNoThrow(wcslen(qbMemberName.Ptr()) + 6)); - pSuffix = qbMemberName.Ptr() + wcslen(qbMemberName.Ptr()); - cchSuffix = qbMemberName.Size() - wcslen(qbMemberName.Ptr()); - } - StringCchPrintf(pSuffix, cchSuffix, W("_%i"), iSuffix++); - } - -ErrExit: - return hr; -} // HRESULT CImportTlb::GenerateUniqueMemberName() - -//***************************************************************************** -// Convert a TYPEDESC to a COM+ signature. -// -// Conversion rules: -// integral types are converted as-is. -// strings to strings, with native type decoration. -// VT_UNKNOWN, VT_DISPATCH as ref class (ie, Object) -// VT_PTR -> VT_USERDEFINED interface as Object -// VT_USERDEFINED record as value type. -// -// With SIG_FUNC: -// PTR to valuetype depends on other flags: -// [IN] or [RETVAL] valuetype + NATIVE_TYPE_LPSTRUCT -// [OUT] or [IN, OUT] byref valuetype -// PTR to integral type: -// [IN] @todo: see atti -// [OUT] [IN, OUT] byref type -// [RETVAL] type -// PTR to object -// [IN] @todo: see atti -// [OUT] [IN, OUT] byref object -// [RETVAL] object -// -// With SIG_FIELD: -// PTR to integral type adds ELEMENT_TYPE_PTR. -// -// Conversion proceeds in three steps. -// 1) Parse the COM type info. Accumulate VT_PTR and VT_BYREF into a count -// of indirections. Follow TKIND_ALIAS to determine the ultimate aliased -// type, and for non-user-defined types, convert that ultimate type. -// Collect array sizes and udt names. Determine element type and native -// type. -// 2) Normalize to COM+ types. Determine if there is conversion loss. -// 3) Emit the COM+ signature. Recurse to handle array types. Add native -// type info if there is any. -//***************************************************************************** -#ifdef _PREFAST_ -#pragma warning(push) -#pragma warning(disable:21000) // Suppress PREFast warning about overly large function -#endif -HRESULT CImportTlb::_ConvSignature( // S_OK, S_CONVERSION_LOSS, or error. - ITypeInfo *pITI, // [IN] The typeinfo containing the TYPEDESC. - const TYPEDESC *pType, // [IN] The TYPEDESC to convert. - ULONG Flags, // [IN] Flags describing the TYPEDESC. - CQuickBytes &qbSigBuf, // [IN, OUT] A CQuickBytes containing the signature. - ULONG cbSig, // [IN] Where to start building the signature. - ULONG *pcbSig, // [OUT] Where the signature ends (ix of first byte past; where to start next). - CQuickArray<BYTE> &qbNativeTypeBuf, // [IN, OUT] A CQuickBytes containing the native type. - ULONG cbNativeType, // [IN] Where to start building the native type. - ULONG *pcbNativeType, // [OUT] Where the native type ends (ix of first byte past; where to start next). - BOOL bNewEnumMember, // [IN] A flag indicating if the member is the NewEnum member. - int iByRef) // [IN] ByRef count of caller (for recursive calls). -{ - HRESULT hr=S_OK; // A result. - TYPEDESC tdTemp; // Copy of TYPEDESC, for R/W. - VARTYPE vt; // The typelib signature element. - int bByRef=false; // If true, convert first pointer as "ELEMENT_TYPE_BYREF". - COR_SIGNATURE et=0; // The COM+ signature element. - mdToken tk=0; // Token from some COM+ signature element. - ULONG nt=NATIVE_TYPE_NONE; // Native type decoration. - ITypeInfo *pITIAlias=0; // Typeinfo of the aliased type. - TYPEATTR *psAttrAlias=0; // TYPEATTR of the aliased typeinfo. - ITypeInfo *pITIUD=0; // TypeInfo of an aliased UserDefined type. - ITypeLib *pITLBUD=0; // TypeLib of an aliased UserDefined type. - BSTR bstrNamespace=0; // Namespace name. - BSTR bstrName=0; // UserDefined name. - int bConversionLoss=false; // If true, the conversion was lossy. - BYTE *pbSig; // Byte pointer for easy pointer math. - ULONG cb; // Size of a signature element. - ULONG cElems=0; // Count of elements in an array. - int i; // Loop control. - TYPEATTR *psAttr = 0; // The TYPEATTR for the user defined type being converted. - const StdConvertibleItfInfo *pConvertionInfo = 0; // The standard convertible interface information. - CQuickArray<BYTE> qbNestedNativeType;// A native type buffer used for array sig convertion. - ULONG iNestedNativeTypeOfs=0; // A native type offset. - ULONG nested=NATIVE_TYPE_NONE; // A nested native type. - - // VT_ to ELEMENT_TYPE_ translation table. - struct VtSig - { - CorElementType et; - CorNativeType nt; - short flags; - }; - - // The VARIANT_TYPE to sig mapping table. - static const VtSig - _VtInfo[MAX_TLB_VT] = - { - // Relies on {0} initializing the entire sub-structure to 0. - {ELEMENT_TYPE_MAX, NATIVE_TYPE_NONE, 0}, // VT_EMPTY = 0 - {ELEMENT_TYPE_MAX, NATIVE_TYPE_NONE, 0}, // VT_NULL = 1 - {ELEMENT_TYPE_I2, NATIVE_TYPE_NONE, 0}, // VT_I2 = 2 - {ELEMENT_TYPE_I4, NATIVE_TYPE_NONE, 0}, // VT_I4 = 3 - {ELEMENT_TYPE_R4, NATIVE_TYPE_NONE, 0}, // VT_R4 = 4 - {ELEMENT_TYPE_R8, NATIVE_TYPE_NONE, 0}, // VT_R8 = 5 - {ELEMENT_TYPE_VALUETYPE,NATIVE_TYPE_CURRENCY, 0}, // VT_CY = 6 - {ELEMENT_TYPE_VALUETYPE,NATIVE_TYPE_NONE, 0}, // VT_DATE = 7 - {ELEMENT_TYPE_STRING, NATIVE_TYPE_BSTR, 0}, // VT_BSTR = 8 - {ELEMENT_TYPE_OBJECT, NATIVE_TYPE_IDISPATCH, 0}, // VT_DISPATCH = 9 - {ELEMENT_TYPE_I4, NATIVE_TYPE_ERROR, 0}, // VT_ERROR = 10 scode - {ELEMENT_TYPE_BOOLEAN, NATIVE_TYPE_NONE, 0}, // VT_BOOL = 11 - {ELEMENT_TYPE_OBJECT, NATIVE_TYPE_STRUCT, 0}, // VT_VARIANT = 12 - {ELEMENT_TYPE_OBJECT, NATIVE_TYPE_IUNKNOWN, 0}, // VT_UNKNOWN = 13 - {ELEMENT_TYPE_VALUETYPE,NATIVE_TYPE_NONE, 0}, // VT_DECIMAL = 14 - {ELEMENT_TYPE_MAX, NATIVE_TYPE_NONE, 0}, // = 15 - {ELEMENT_TYPE_I1, NATIVE_TYPE_NONE, 0}, // VT_I1 = 16 - {ELEMENT_TYPE_U1, NATIVE_TYPE_NONE, 0}, // VT_UI1 = 17 - {ELEMENT_TYPE_U2, NATIVE_TYPE_NONE, 0}, // VT_UI2 = 18 - {ELEMENT_TYPE_U4, NATIVE_TYPE_NONE, 0}, // VT_UI4 = 19 - {ELEMENT_TYPE_I8, NATIVE_TYPE_NONE, 0}, // VT_I8 = 20 - {ELEMENT_TYPE_U8, NATIVE_TYPE_NONE, 0}, // VT_UI8 = 21 - - // it would be nice to convert these as I and U, with NT_I4 and NT_U4, but that doesn't work. - {ELEMENT_TYPE_I4, NATIVE_TYPE_NONE, 0}, // VT_INT = 22 INT is I4 on win32 - {ELEMENT_TYPE_U4, NATIVE_TYPE_NONE, 0}, // VT_UINT = 23 UINT is UI4 on win32 - - {ELEMENT_TYPE_VOID, NATIVE_TYPE_NONE, 0}, // VT_VOID = 24 - - {ELEMENT_TYPE_I4, NATIVE_TYPE_ERROR, 0}, // VT_HRESULT = 25 - {ELEMENT_TYPE_MAX, NATIVE_TYPE_NONE, 0}, // VT_PTR = 26 - {ELEMENT_TYPE_MAX, NATIVE_TYPE_NONE, 0}, // VT_SAFEARRAY = 27 - {ELEMENT_TYPE_SZARRAY, NATIVE_TYPE_FIXEDARRAY, 0}, // VT_CARRAY = 28 - {ELEMENT_TYPE_MAX, NATIVE_TYPE_NONE, 0}, // VT_USERDEFINED = 29 - {ELEMENT_TYPE_STRING, NATIVE_TYPE_LPSTR, 0}, // VT_LPSTR = 30 - {ELEMENT_TYPE_STRING, NATIVE_TYPE_LPWSTR, 0}, // VT_LPWSTR = 31 - }; - - _ASSERTE(pType && pcbSig && pcbNativeType); - - //------------------------------------------------------------------------- - // Parse COM signature - - // Strip off leading VT_PTR and VT_BYREF - while (pType->vt == VT_PTR) - pType = pType->lptdesc, ++iByRef; - if (pType->vt & VT_BYREF) - { - tdTemp = *pType; - tdTemp.vt &= ~VT_BYREF; - ++iByRef; - pType = &tdTemp; - } - - // Determine the element type, and possibly the token and/or native type. - switch (vt=pType->vt) - { - case VT_PTR: - _ASSERTE(!"Should not have VT_PTR here"); - break; - - // These are all known types (plus GUID). - case VT_CY: - case VT_DATE: - case VT_DECIMAL: - IfFailGo(GetKnownTypeToken(vt, &tk)); - et = _VtInfo[vt].et; - nt = _VtInfo[vt].nt; - break; - - case VT_SAFEARRAY: - if (m_bSafeArrayAsSystemArray && !IsSigVarArg(Flags)) - { - IfFailGo(GetKnownTypeToken(vt, &tk)); - et = ELEMENT_TYPE_CLASS; - nt = NATIVE_TYPE_SAFEARRAY; - } - else - { - IfFailGo(GetKnownTypeToken(vt, &tk)); - et = ELEMENT_TYPE_SZARRAY; - nt = NATIVE_TYPE_SAFEARRAY; - } - break; - - case VT_USERDEFINED: - // Resolve the alias to the ultimate aliased type. - IfFailGo(_ResolveTypeDescAlias(pITI, pType, &pITIAlias, &psAttrAlias)); - - // If the aliased type was built-in, convert that built-in type. - if (psAttrAlias->typekind == TKIND_ALIAS) - { // Recurse to follow the alias chain. - _ASSERTE(psAttrAlias->tdescAlias.vt != VT_USERDEFINED); - hr = _ConvSignature(pITIAlias, &psAttrAlias->tdescAlias, Flags, qbSigBuf, cbSig, pcbSig, qbNativeTypeBuf, cbNativeType, pcbNativeType, bNewEnumMember, iByRef); - goto ErrExit; - } - - // If the type is a coclass then we need to retrieve the default interface and - // substitute it for the coclass. Look up on the resolved alias, because it is - // that class that has a default interface. - if (psAttrAlias->typekind == TKIND_COCLASS) - { - ITypeInfo *pDefaultItf = NULL; - hr = GetDefaultInterface(pITIAlias, &pDefaultItf); - if ((hr != S_OK) || !pDefaultItf) - { - hr = E_UNEXPECTED; - goto ErrExit; - } - - pITIUD = pDefaultItf; - } - else - { // USERDEFINED class/interface/record/union/enum. Retrieve the type - // info for the user defined type. Note: use the TKIND_ALIAS typeinfo - // itself for this conversion (not the aliased type) to preserve - // names, lib locations, etc. - IfFailGo(pITI->GetRefTypeInfo(pType->hreftype, &pITIUD)); - } - - // pITIUD points to the typeinfo for which we'll create a signature. - IfFailGo(pITIUD->GetDocumentation(MEMBERID_NIL, &bstrName, 0,0,0)); - IfFailGo(pITIUD->GetContainingTypeLib(&pITLBUD, 0)); - IfFailGo(pITIUD->GetTypeAttr(&psAttr)); - IfFailGo(GetNamespaceNameForTypeLib(pITLBUD, &bstrNamespace)); - - // If the "User Defined Type" is GUID in StdOle2, convert to M.R.GUID - if (SString::_wcsicmp(bstrNamespace, COM_STDOLE2) == 0 && wcscmp(bstrName, COM_GUID) == 0) - { // Classlib valuetype GUID. - et = ELEMENT_TYPE_VALUETYPE; - IfFailGo(GetKnownTypeToken(VT_SLOT_FOR_GUID, &tk)); - } - else - { // Some user defined class. Is it a value class, or a VOS class? - tk = 0; - switch (psAttrAlias->typekind) - { - case TKIND_RECORD: - case TKIND_ENUM: - case TKIND_UNION: - et = ELEMENT_TYPE_VALUETYPE; - break; - case TKIND_INTERFACE: - case TKIND_DISPATCH: - case TKIND_COCLASS: - // A pointer to a user defined type of interface/dispatch/coclass - // is a straight COM+ object (the ref is implicit), so eliminate - // one byref count for those. - // Somehow, there are typelibs written with ([out, retval] IFoo *pOut); - if (iByRef <= 0) - { - // convert to an int. - bConversionLoss = true; - tk = 0; - et = ELEMENT_TYPE_I; - nt = NATIVE_TYPE_NONE; - iByRef = 0; - break; - } - else - { - --iByRef; - - // Check for references to Stdole2.IUnknown or Stdole2.IDispatch. - if (psAttr->guid == IID_IUnknown) - { - vt = VT_UNKNOWN; - goto IsReallyUnknown; - } - else if (psAttr->guid == IID_IDispatch) - { - vt = VT_DISPATCH; - goto IsReallyUnknown; - } - - // Check to see if this user defined type is one of the standard ones - // we generate custom marshalers for. - pConvertionInfo = GetConvertionInfoFromNativeIID(psAttr->guid); - if (pConvertionInfo) - { - // Convert the UTF8 string to unicode. - int MngTypeNameStrLen = (int)(strlen(pConvertionInfo->m_strMngTypeName) + 1); - WCHAR *strFullyQualifiedMngTypeName = (WCHAR *)_alloca(MngTypeNameStrLen * sizeof(WCHAR)); - int ret = WszMultiByteToWideChar(CP_UTF8, 0, pConvertionInfo->m_strMngTypeName, MngTypeNameStrLen, strFullyQualifiedMngTypeName, MngTypeNameStrLen); - _ASSERTE(ret != 0); - if (!ret) - IfFailGo(HRESULT_FROM_GetLastError()); - - // Create a TypeRef to the marshaller. - IfFailGo(m_TRMap.DefineTypeRef(m_pEmit, m_arSystem, strFullyQualifiedMngTypeName, &tk)); - - // The type is a standard interface that we need to convert. - et = ELEMENT_TYPE_CLASS; - nt = NATIVE_TYPE_CUSTOMMARSHALER; - break; - } - } - et = ELEMENT_TYPE_CLASS; - nt = NATIVE_TYPE_INTF; - break; - default: - //case TKIND_MODULE: -- can't pass one of these as a parameter. - //case TKIND_ALIAS: -- should already be resolved. - _ASSERTE(!"Unexpected typekind for user defined type"); - et = ELEMENT_TYPE_END; - } // switch (psAttrAlias->typekind) - } - break; - - IsReallyUnknown: - case VT_UNKNOWN: - case VT_DISPATCH: - // If the NewEnum member, retrieve the custom marshaler information for IEnumVARIANT. - if (bNewEnumMember && (pConvertionInfo=GetConvertionInfoFromNativeIID(IID_IEnumVARIANT))) - { - // Convert the UTF8 string to unicode. - int MngTypeNameStrLen = (int)(strlen(pConvertionInfo->m_strMngTypeName) + 1); - WCHAR *strFullyQualifiedMngTypeName = (WCHAR *)_alloca(MngTypeNameStrLen * sizeof(WCHAR)); - int ret = WszMultiByteToWideChar(CP_UTF8, 0, pConvertionInfo->m_strMngTypeName, MngTypeNameStrLen, strFullyQualifiedMngTypeName, MngTypeNameStrLen); - _ASSERTE(ret != 0); - if (!ret) - IfFailGo(HRESULT_FROM_GetLastError()); - - // Create a TypeRef to the marshaller. - IfFailGo(m_TRMap.DefineTypeRef(m_pEmit, m_arSystem, strFullyQualifiedMngTypeName, &tk)); - - // The type is a standard interface that we need to convert. - et = ELEMENT_TYPE_CLASS; - nt = NATIVE_TYPE_CUSTOMMARSHALER; - } - else - { - et = _VtInfo[vt].et; - nt = _VtInfo[vt].nt; - } - break; - - case VT_CARRAY: - // Determine the count of elements. - for (cElems=1, i=0; i<pType->lpadesc->cDims; ++i) - cElems *= pType->lpadesc->rgbounds[i].cElements; - - // Set the native type based on weither we are dealing with a field or a method sig. - if (IsSigField(Flags)) - { - nt = NATIVE_TYPE_FIXEDARRAY; - } - else - { - nt = NATIVE_TYPE_ARRAY; - } - - // Set the element type. - et = _VtInfo[vt].et; - break; - - case VT_BOOL: - // Special case for VARIANT_BOOL: If a field of a struct or union, convert - // as ET_I2. - if (IsSigField(Flags)) - vt = VT_I2; - // Fall through to default case. - - default: - if (vt > VT_LPWSTR) - { - ReportEvent(NOTIF_CONVERTWARNING, TLBX_E_BAD_VT_TYPE, vt, m_szName, m_szMember); - IfFailGo(PostError(TLBX_E_BAD_VT_TYPE, vt, m_szName, m_szMember)); - } - _ASSERTE(vt <= VT_LPWSTR && _VtInfo[vt].et != ELEMENT_TYPE_MAX); -#ifdef _PREFAST_ -#pragma warning(push) -#pragma warning(disable:26000) // "Disable PREFast/espX warning about buffer overflow" -#endif - et = _VtInfo[vt].et; - nt = _VtInfo[vt].nt; -#ifdef _PREFAST_ -#pragma warning(pop) -#endif - break; - } // switch (vt=pType->vt) - - //------------------------------------------------------------------------- - // Normalize to COM+ types. - - // At this point the type, flags, and pointer nesting are known. Is this a legal combination? - // If not, what is the appropriate "simplifing assumption"? - - if (et == ELEMENT_TYPE_VOID) - { - if (IsSigField(Flags)) - { // A void as a field. No byref. - iByRef = 0; - } - else - { - // Param or return type. "void *" -> ET_I, "void **", "void ***",... -> ET_BYREF ET_I - if (iByRef > 1) - iByRef = 1; - else - if (iByRef == 1) - iByRef = 0; - } - tk = 0; - et = ELEMENT_TYPE_I; - nt = NATIVE_TYPE_NONE; - } - - if (et == ELEMENT_TYPE_STRING && iByRef == 0 && !IsSigField(Flags) && IsSigOut(Flags)) - { - // This is an [out] or [in, out] string parameter without indirections. - if (vt == VT_BSTR) - { - // [in, out] System.String does not make much sense. Managed strings are - // immutable and we do not have BSTR <-> StringBuilder marshaling support. - // Convert them to IntPtr. - bConversionLoss = true; - tk = 0; - et = ELEMENT_TYPE_I; - nt = NATIVE_TYPE_NONE; - } - else - { - _ASSERTE(vt == VT_LPSTR || vt == VT_LPWSTR); - - // [in, out] C-strings and wide strings have a lossless conversion to StringBuilder. - IfFailGo(GetKnownTypeToken(VT_SLOT_FOR_STRINGBUF, &tk)); - et = ELEMENT_TYPE_CLASS; - - // nt already has the right value - _ASSERTE(nt == (vt == VT_LPSTR ? NATIVE_TYPE_LPSTR : NATIVE_TYPE_LPWSTR)); - } - } - - if (iByRef) - { - if (et == ELEMENT_TYPE_VALUETYPE && iByRef >= 2) - { - bConversionLoss = true; - tk = 0; - et = ELEMENT_TYPE_I; - nt = NATIVE_TYPE_NONE; - iByRef = 0; - } - else - { - switch (Flags & SIG_TYPE_MASK) - { - case SIG_FIELD: - // If ptr to valuetype or class type, we can't handle it. - if (et == ELEMENT_TYPE_END || - et == ELEMENT_TYPE_CLASS || - et == ELEMENT_TYPE_OBJECT || - et == ELEMENT_TYPE_VALUETYPE) - { - bConversionLoss = true; - tk = 0; - et = ELEMENT_TYPE_I; - nt = NATIVE_TYPE_NONE; - iByRef = 0; - } - break; - case SIG_FUNC: - // Pointer to value type? - if (et == ELEMENT_TYPE_VALUETYPE) - { - // For [retval], eat one level of indirection; otherwise turn one into BYREF - if (IsSigOutRet(Flags)) - { // [out, retval], so reduce one level of indirection. - --iByRef; - } - else - { // Favor BYREF over NATIVE_TYPE_LPSTRUCT - if (IsSigUseByref(Flags)) - { - bByRef = true; - --iByRef; - } - if (iByRef > 0) - { - nt = NATIVE_TYPE_LPSTRUCT; - --iByRef; - } - } - } - else // Pointer to Object or base type. - { - if (IsSigRet(Flags)) - { // [retval] so consume one indirection. - _ASSERTE(iByRef > 0); - --iByRef; - } - if (iByRef > 0 && IsSigUseByref(Flags)) - { - bByRef = true; - --iByRef; - } - } - break; - case SIG_ELEM: - // This case comes up when a property type is from a [retval]. - if (IsSigRet(Flags)) - { - if (iByRef > 0) - --iByRef; - } - break; - } - } - } // if (iByRef) - - //------------------------------------------------------------------------- - // We don't want any ET_PTR, so if there are any byref counts left, bail. - if (iByRef) - { - bConversionLoss = true; - tk = 0; - et = ELEMENT_TYPE_I; - nt = NATIVE_TYPE_NONE; - iByRef = 0; - bByRef = false; - } - - //------------------------------------------------------------------------- - // Build COM+ signature. - - // Type has been analyzed, and possibly modified. Emit the COM+ signature. - _ASSERTE(et != ELEMENT_TYPE_MAX); - _ASSERTE(et != ELEMENT_TYPE_END); - - // If it is a pointer to something, emit that now. - if (bByRef || iByRef) - { - // Size the array to hold the elements. - IfFailGo(qbSigBuf.ReSizeNoThrow(cbSig + CB_MAX_ELEMENT_TYPE * (iByRef+(bByRef?1:0)))); - pbSig = reinterpret_cast<BYTE*>(qbSigBuf.Ptr()); - - // Put in any leading "BYREF" - if (bByRef) - { - pbSig = reinterpret_cast<BYTE*>(qbSigBuf.Ptr()); - cb = CorSigCompressData(ELEMENT_TYPE_BYREF, &pbSig[cbSig]); - cbSig += cb; - } - - // Put in the "PTR"s. - while (iByRef-- > 0) - { - cb = CorSigCompressData(ELEMENT_TYPE_PTR, &pbSig[cbSig]); - cbSig += cb; - } - } - - // Emit the type. - IfFailGo(qbSigBuf.ReSizeNoThrow(cbSig + CB_MAX_ELEMENT_TYPE)); - pbSig = reinterpret_cast<BYTE*>(qbSigBuf.Ptr()); - cb = CorSigCompressData(et, &pbSig[cbSig]); - cbSig += cb; - - // Add the class type, the array information, etc. - switch (et) - { - case ELEMENT_TYPE_CLASS: - case ELEMENT_TYPE_VALUETYPE: - // Size the array to hold the token. - IfFailGo(qbSigBuf.ReSizeNoThrow(cbSig + CB_MAX_ELEMENT_TYPE)); - pbSig = reinterpret_cast<BYTE*>(qbSigBuf.Ptr()); - - // If the token hasn't been resolved yet, do that now. - if (tk == 0) - { - _ASSERTE(pITIUD); - IfFailGo(_GetTokenForTypeInfo(pITIUD, TRUE, &tk)); - } - cb = CorSigCompressToken(tk, reinterpret_cast<ULONG*>(&pbSig[cbSig])); - cbSig += cb; - break; - - case ELEMENT_TYPE_SZARRAY: - // map to SZARRAY <subtype> - IfFailGo(qbSigBuf.ReSizeNoThrow(cbSig + CB_MAX_ELEMENT_TYPE)); - pbSig = reinterpret_cast<BYTE*>(qbSigBuf.Ptr()); - // Recurse on the type. - IfFailGo(_ConvSignature(pITI, &pType->lpadesc->tdescElem, SIG_ELEM, qbSigBuf, cbSig, &cbSig, qbNestedNativeType, 0, &iNestedNativeTypeOfs, bNewEnumMember)); - if (hr == S_CONVERSION_LOSS) - bConversionLoss = true; - break; - - case VT_DISPATCH: - case VT_UNKNOWN: - default: - _ASSERTE(tk == 0); - // et, nt assigned above. - break; - } // switch (et) - - // Do any native type info. - if (nt != NATIVE_TYPE_NONE) - { - if (iNestedNativeTypeOfs > 0) - CorSigUncompressData(reinterpret_cast<PCCOR_SIGNATURE>(qbNestedNativeType.Ptr()), &nested); - - if (nt == NATIVE_TYPE_FIXEDARRAY) - { - IfFailGo(qbNativeTypeBuf.ReSizeNoThrow(cbNativeType + NATIVE_TYPE_MAX_CB * 2 + DWORD_MAX_CB)); - cbNativeType += CorSigCompressData(nt, &qbNativeTypeBuf[cbNativeType]); - cbNativeType += CorSigCompressData(cElems, &qbNativeTypeBuf[cbNativeType]); - if (nested == NATIVE_TYPE_BSTR || nested == NATIVE_TYPE_LPWSTR || nested == NATIVE_TYPE_LPSTR) - { // Use the nested type. - cbNativeType += CorSigCompressData(nested, &qbNativeTypeBuf[cbNativeType]); - } - else - { // Use a default sub type. - cbNativeType += CorSigCompressData(NATIVE_TYPE_MAX, &qbNativeTypeBuf[cbNativeType]); - } - } - else if (nt == NATIVE_TYPE_ARRAY) - { - IfFailGo(qbNativeTypeBuf.ReSizeNoThrow(cbNativeType + NATIVE_TYPE_MAX_CB * 2 + DWORD_MAX_CB * 2)); - cbNativeType += CorSigCompressData(nt, &qbNativeTypeBuf[cbNativeType]); - if (nested == NATIVE_TYPE_BSTR || nested == NATIVE_TYPE_LPWSTR || nested == NATIVE_TYPE_LPSTR) - { // Use the nested type. - cbNativeType += CorSigCompressData(nested, &qbNativeTypeBuf[cbNativeType]); - } - else - { // Use a default sub type. - cbNativeType += CorSigCompressData(NATIVE_TYPE_MAX, &qbNativeTypeBuf[cbNativeType]); - } - // Use zero for param index. - cbNativeType += CorSigCompressData(0, &qbNativeTypeBuf[cbNativeType]); - // Use count from typelib for elem count. - cbNativeType += CorSigCompressData(cElems, &qbNativeTypeBuf[cbNativeType]); - } - else if (nt == NATIVE_TYPE_SAFEARRAY) - { - BOOL bPtrArray = FALSE; - CQuickArray<WCHAR> rTemp; - CQuickArray<char> rTypeName; - LPUTF8 strTypeName = ""; - TYPEDESC *pTypeDesc = &pType->lpadesc->tdescElem; - VARTYPE ArrayElemVT = pTypeDesc->vt; - - if (ArrayElemVT == VT_PTR) - { - bPtrArray = TRUE; - pTypeDesc = pType->lpadesc->tdescElem.lptdesc; - ArrayElemVT = pTypeDesc->vt; - if ((ArrayElemVT != VT_USERDEFINED) && (ArrayElemVT != VT_VOID)) - { - // We do not support deep marshalling pointers. - ArrayElemVT = VT_INT; - bConversionLoss = TRUE; - } - } - - // If we are dealing with a safe array of user defined types and if we - // are importing safe array's as System.Array then add the SafeArrayUserDefSubType. - if (ArrayElemVT == VT_USERDEFINED) - { - // Resolve the alias to the ultimate aliased type. - IfFailGo(_ResolveTypeDescAlias(pITI, pTypeDesc, &pITIAlias, &psAttrAlias)); - - // If the type is a coclass then we need to retrieve the default interface and - // substitute it for the coclass. Look up on the resolved alias, because it is - // that class that has a default interface. - if (psAttrAlias->typekind == TKIND_COCLASS) - { - ITypeInfo *pDefaultItf = NULL; - hr = GetDefaultInterface(pITIAlias, &pDefaultItf); - if ((hr != S_OK) || !pDefaultItf) - { - hr = E_UNEXPECTED; - goto ErrExit; - } - - pITIUD = pDefaultItf; - } - else - { // USERDEFINED interface/record/union/enum. Retrieve the type - // info for the user defined type. Note: use the TKIND_ALIAS typeinfo - // itself for this conversion (not the aliased type) to preserve - // names, lib locations, etc. - IfFailGo(pITI->GetRefTypeInfo(pTypeDesc->hreftype, &pITIUD)); - } - - // pITIUD points to the typeinfo for which we'll create a signature. - IfFailGo(pITIUD->GetTypeAttr(&psAttr)); - - // Get the typeref name for the type. - for(;;) - { - int cchReq; - mdToken tkDummy; - IfFailGo(_GetTokenForTypeInfo(pITIUD, TRUE, &tkDummy, rTemp.Ptr(), (int)rTemp.MaxSize(), &cchReq, TRUE)); - if (cchReq <= (int)rTemp.MaxSize()) - break; - IfFailGo(rTemp.ReSizeNoThrow(cchReq)); - } - - // Convert the type name to UTF8. - ULONG cbReq = WszWideCharToMultiByte(CP_UTF8, 0, rTemp.Ptr(), -1, 0, 0, 0, 0); - IfFailGo(rTypeName.ReSizeNoThrow(cbReq + 1)); - WszWideCharToMultiByte(CP_UTF8, 0, rTemp.Ptr(), -1, rTypeName.Ptr(), cbReq, 0, 0); - - // Determine the safe array element VT. - switch (psAttrAlias->typekind) - { - case TKIND_RECORD: - case TKIND_ENUM: - case TKIND_UNION: - if (bPtrArray) - { - ArrayElemVT = VT_INT; - bConversionLoss = TRUE; - } - else - { - ArrayElemVT = psAttrAlias->typekind == TKIND_ENUM ? VT_I4 : VT_RECORD; - strTypeName = rTypeName.Ptr(); - } - break; - - case TKIND_INTERFACE: - case TKIND_DISPATCH: - case TKIND_COCLASS: - if (!bPtrArray) - { - ArrayElemVT = VT_INT; - bConversionLoss = TRUE; - } - else - { - if (IsIDispatchDerived(pITIUD, psAttr) == S_FALSE) - ArrayElemVT = VT_UNKNOWN; - else - ArrayElemVT = VT_DISPATCH; - strTypeName = rTypeName.Ptr(); - } - break; - } - - // If we are not converting the SAFEARRAY to a System.Array, then - // we don't need to encode the name of the user defined type. - if (!m_bSafeArrayAsSystemArray) - strTypeName = ""; - } - - // Make sure the native type buffer is large enough. - ULONG TypeNameStringLen = (ULONG)strlen(strTypeName); - IfFailGo(qbNativeTypeBuf.ReSizeNoThrow(cbNativeType + NATIVE_TYPE_MAX_CB * 2 + DWORD_MAX_CB + TypeNameStringLen + STRING_OVERHEAD_MAX_CB)); - - // Add the native type to the native type info. - cbNativeType += CorSigCompressData(nt, &qbNativeTypeBuf[cbNativeType]); - - // Add the VARTYPE of the array. - cbNativeType += CorSigCompressData(ArrayElemVT, &qbNativeTypeBuf[cbNativeType]); - - // Add the type name to the native type info. - BYTE *pNativeType = (BYTE*)CPackedLen::PutLength(&qbNativeTypeBuf[cbNativeType], TypeNameStringLen); - cbNativeType += (ULONG)(pNativeType - &qbNativeTypeBuf[cbNativeType]); - memcpy(&qbNativeTypeBuf[cbNativeType], strTypeName, TypeNameStringLen); - cbNativeType += TypeNameStringLen; - } - else if (nt == NATIVE_TYPE_CUSTOMMARSHALER) - { - // Calculate the length of each string and then the total length of the native type info. - ULONG MarshalerTypeNameStringLen = (ULONG)strlen(pConvertionInfo->m_strCustomMarshalerTypeName); - ULONG CookieStringLen = (ULONG)strlen(pConvertionInfo->m_strCookie); - ULONG TotalNativeTypeLen = MarshalerTypeNameStringLen + CookieStringLen; - BYTE *pNativeType = 0; - - // Make sure the native type buffer is large enough. - IfFailGo(qbNativeTypeBuf.ReSizeNoThrow(cbNativeType + NATIVE_TYPE_MAX_CB + TotalNativeTypeLen + STRING_OVERHEAD_MAX_CB * 4)); - - // Add the native type to the native type info. - cbNativeType += CorSigCompressData(nt, &qbNativeTypeBuf[cbNativeType]); - - // Add an empty string for the typelib guid. - pNativeType = (BYTE*)CPackedLen::PutLength(&qbNativeTypeBuf[cbNativeType], 0); - cbNativeType += (ULONG)(pNativeType - &qbNativeTypeBuf[cbNativeType]); - - // Add an empty string for the unmanaged type name. - pNativeType = (BYTE*)CPackedLen::PutLength(&qbNativeTypeBuf[cbNativeType], 0); - cbNativeType += (ULONG)(pNativeType - &qbNativeTypeBuf[cbNativeType]); - - // Add the name of the custom marshaler to the native type info. - pNativeType = (BYTE*)CPackedLen::PutLength(&qbNativeTypeBuf[cbNativeType], MarshalerTypeNameStringLen); - cbNativeType += (ULONG)(pNativeType - &qbNativeTypeBuf[cbNativeType]); - memcpy(&qbNativeTypeBuf[cbNativeType], pConvertionInfo->m_strCustomMarshalerTypeName, MarshalerTypeNameStringLen); - cbNativeType += MarshalerTypeNameStringLen; - - // Add the cookie to the native type info. - pNativeType = (BYTE*)CPackedLen::PutLength(&qbNativeTypeBuf[cbNativeType], CookieStringLen); - cbNativeType += (ULONG)(pNativeType - &qbNativeTypeBuf[cbNativeType]); - memcpy(&qbNativeTypeBuf[cbNativeType], pConvertionInfo->m_strCookie, CookieStringLen); - cbNativeType += CookieStringLen; - } - else - { - IfFailGo(qbNativeTypeBuf.ReSizeNoThrow(cbNativeType + NATIVE_TYPE_MAX_CB + 1)); - cbNativeType += CorSigCompressData(nt, &qbNativeTypeBuf[cbNativeType]); - } - } - - // Return the size of the native type to the caller. - *pcbNativeType = cbNativeType; - - // Return size to caller. - *pcbSig = cbSig; - - // If there was a conversion loss, change the return code. - if (bConversionLoss) - hr = S_CONVERSION_LOSS; - -ErrExit: - if (bstrNamespace) - ::SysFreeString(bstrNamespace); - if (bstrName) - ::SysFreeString(bstrName); - if(psAttrAlias) - pITIAlias->ReleaseTypeAttr(psAttrAlias); - if (pITIAlias) - pITIAlias->Release(); - if (psAttr) - pITIUD->ReleaseTypeAttr(psAttr); - if (pITIUD) - pITIUD->Release(); - if (pITLBUD) - pITLBUD->Release(); - - return hr; -} // HRESULT CImportTlb::_ConvSignature() -#ifdef _PREFAST_ -#pragma warning(pop) -#endif - -//***************************************************************************** -// Build a sorted list of functions to convert. (Sort by vtable offset.) -//***************************************************************************** -HRESULT CImportTlb::BuildMemberList( - ITypeInfo *pITI, // TypeInfo with functions. - int iStart, // First function to take. - int iEnd, // Last function to take. - BOOL bInheritsIEnum) // Inherits from IEnumerable. -{ - HRESULT hr; // A result. - int bNeedSort = false; // If true, need to sort the array. - int ix = 0; // Loop counter. - int oVftPrev = -1; // To see if oVft is increasing. - TYPEATTR *psAttr = 0; // TypeAttr for pITI. - FUNCDESC *psFunc; // A FUNCDESC. - LPWSTR pszName; // Working pointer for name. - BSTR bstrName=0; // Name from typelib. - ITypeInfo2 *pITI2=0; // To get custom attributes. - VARIANT vt; // Variant type. - BOOL bFunctionToGetter; // Did a given getter come from a managed function? - - ::VariantInit(&vt); - - IfFailGo(pITI->GetTypeAttr(&psAttr)); - pITI->QueryInterface(IID_ITypeInfo2, reinterpret_cast<void**>(&pITI2)); - - // Get the vars. - IfFailGo(m_MemberList.ReSizeNoThrow(psAttr->cVars + iEnd - iStart)); - memset(m_MemberList.Ptr(), 0, m_MemberList.Size()*sizeof(MemberInfo)); - for (ix=0; ix<psAttr->cVars; ++ix) - { - IfFailGo(pITI->GetVarDesc(ix, &(m_MemberList[ix].m_psVar))); - m_MemberList[ix].m_iMember = ix; - } - m_cMemberProps = psAttr->cVars; - - // Get the funcs. - for (; iStart<iEnd; ++iStart, ++ix) - { - IfFailGo(TryGetFuncDesc(pITI, iStart, &(m_MemberList[ix].m_psFunc))); - psFunc = m_MemberList[ix].m_psFunc; - if (psFunc->oVft < oVftPrev) - bNeedSort = true; - oVftPrev = psFunc->oVft; - m_MemberList[ix].m_iMember = iStart; - } - - if (bNeedSort) - { - class Sorter : public CQuickSort<MemberInfo> - { - typedef CImportTlb::MemberInfo MemberInfo; - public: - Sorter(MemberInfo *p, int n) : CQuickSort<MemberInfo>(p,n) {} - virtual int Compare(MemberInfo *p1, MemberInfo *p2) - { - if (p1->m_psFunc->oVft < p2->m_psFunc->oVft) - return -1; - if (p1->m_psFunc->oVft == p2->m_psFunc->oVft) - return 0; - return 1; - } - }; - Sorter sorter(m_MemberList.Ptr()+m_cMemberProps, (int)m_MemberList.Size()-m_cMemberProps); - sorter.Sort(); - // Check for duplicates. - oVftPrev = -1; - for (ix=m_cMemberProps; ix<(int)m_MemberList.Size(); ++ix) - { - if (m_MemberList[ix].m_psFunc->oVft == oVftPrev) - { - hr = TLBX_E_BAD_VTABLE; - break; - } - oVftPrev = m_MemberList[ix].m_psFunc->oVft; - } - } - - // Build the list of unique names. - m_pMemberNames = new (nothrow) CWCHARPool; - IfNullGo(m_pMemberNames); - - // Property names. No possibility of collisions. - for (ix=0; ix<m_cMemberProps; ++ix) - { - IfFailGo(pITI->GetDocumentation(m_MemberList[ix].m_psVar->memid, &bstrName, 0,0,0)); - IfNullGo(pszName = m_pMemberNames->Alloc((ULONG)wcslen(bstrName)+PROP_DECORATION_LEN+1)); - wcscpy_s(pszName, wcslen(bstrName)+PROP_DECORATION_LEN+1, PROP_DECORATION_GET); - wcscat_s(pszName, wcslen(bstrName)+PROP_DECORATION_LEN+1, bstrName); - m_MemberList[ix].m_pName = pszName; - if ((m_MemberList[ix].m_psVar->wVarFlags & VARFLAG_FREADONLY) == 0) - { - IfNullGo(pszName = m_pMemberNames->Alloc((ULONG)wcslen(bstrName)+PROP_DECORATION_LEN+1)); - wcscpy_s(pszName, wcslen(bstrName)+PROP_DECORATION_LEN+1, PROP_DECORATION_SET); - wcscat_s(pszName, wcslen(bstrName)+PROP_DECORATION_LEN+1, bstrName); - m_MemberList[ix].m_pName2 = pszName; - } - ::SysFreeString(bstrName); - bstrName = 0; - } - - // Function names. Because of get_/set_ decoration, collisions are possible. - for (ix=m_cMemberProps; ix<(int)m_MemberList.Size(); ++ix) - { - int bNewEnumMember = FALSE; - - // Build a name based on invkind. - psFunc = m_MemberList[ix].m_psFunc; - - // Unless we are doing the [out, retval] transformation for disp only interfaces, - // we need to clear the [retval] flag. - if (!m_bTransformDispRetVals) - { - if (psFunc->funckind == FUNC_DISPATCH) - { // If [RETVAL] is set, clear it. - for (int i=0; i<psFunc->cParams; ++i) - if ((psFunc->lprgelemdescParam[i].paramdesc.wParamFlags & PARAMFLAG_FRETVAL) != 0) - psFunc->lprgelemdescParam[i].paramdesc.wParamFlags &= ~PARAMFLAG_FRETVAL; - } - } - - BOOL bExplicitManagedName = FALSE; - if ( (!bNewEnumMember) && (!bInheritsIEnum) && (FuncIsNewEnum(pITI, psFunc, m_MemberList[ix].m_iMember) == S_OK) ) - { - // The member is the new enum member so set its name to GetEnumerator. - IfNullGo(bstrName = SysAllocString(GET_ENUMERATOR_MEMBER_NAME)); - bNewEnumMember = TRUE; - - // To prevent additional methods from implementing the NewEnum method, we mark the interface - bInheritsIEnum = TRUE; - } - else - { - // If the managed name custom value is set for this member, then use it. - if (pITI2) - { - hr = pITI2->GetFuncCustData(m_MemberList[ix].m_iMember, GUID_ManagedName, &vt); - if (hr == S_OK && vt.vt == VT_BSTR) - { - IfNullGo(bstrName = SysAllocString(vt.bstrVal)); - bExplicitManagedName = TRUE; - } - ::VariantClear(&vt); - } - - if (!bstrName) - IfFailGo(pITI->GetDocumentation(psFunc->memid, &bstrName, 0,0,0)); - } - - // If this is a property getter, see if it was originally a function. - bFunctionToGetter = FALSE; - if (psFunc->invkind == INVOKE_PROPERTYGET && pITI2) - { - hr = pITI2->GetFuncCustData(m_MemberList[ix].m_iMember, GUID_Function2Getter, &vt); - if (hr == S_OK && vt.vt == VT_I4 && vt.lVal == 1) - bFunctionToGetter = TRUE; - ::VariantClear(&vt); - } - - - // Check for the propget and propset custom attributes if this not already a property. - if ( (psFunc->invkind & (INVOKE_PROPERTYGET | INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF)) == 0 ) - { - INVOKEKIND ikind; - if (S_OK == _CheckForPropertyCustomAttributes(pITI, m_MemberList[ix].m_iMember, &ikind)) - psFunc->invkind = ikind; - } - - - // If this is a property accessor, but not the 'new enum member', and not - // originally from a managed function (that was exported as a getter), - // decorate the name appropriately. If the managed name was set explicitly by - // the Guid_ManagedName attribute, then don't try an decorate it. - ULONG nChars = 0; - if (!bExplicitManagedName && (psFunc->invkind & (INVOKE_PROPERTYGET | INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF) && !bNewEnumMember && !bFunctionToGetter)) - { - nChars = (ULONG)wcslen(bstrName)+PROP_DECORATION_LEN+1; - IfNullGo(pszName = m_pMemberNames->Alloc(nChars)); - - USHORT msSemantics=0; // Property's methodsemantics. - FUNCDESC *psF; // FUNCDESC of Get, Put, or PutRef. - TYPEDESC *pProperty; // TYPEDESC of property type. - BOOL bPropRetval; // Is the property type a [retval]? - IfFailGo(_GetFunctionPropertyInfo(psFunc, &msSemantics, &psF, &pProperty, &bPropRetval, FALSE, bstrName)); - - m_MemberList[ix].m_msSemantics = msSemantics; - switch(msSemantics) - { - case msGetter: - wcscpy_s(pszName, nChars, PROP_DECORATION_GET); - break; - case msSetter: - wcscpy_s(pszName, nChars, PROP_DECORATION_SET); - break; - case msOther: - wcscpy_s(pszName, nChars, PROP_DECORATION_LET); - break; - default: - _ASSERTE(msSemantics == 0); - *pszName = 0; - break; - } - wcscat_s(pszName, nChars, bstrName); - } - else - { - nChars = (ULONG)wcslen(bstrName)+1; - IfNullGo(pszName = m_pMemberNames->Alloc(nChars)); - wcscpy_s(pszName, nChars, bstrName); - } - - // Check for name collision, restore original name if collision occurs. - for (int index=0; index<ix; index++) - { - if ( (m_MemberList[index].m_pName) && (wcscmp(pszName, m_MemberList[index].m_pName) == 0) ) - { - wcscpy_s(pszName, nChars, bstrName); - m_MemberList[ix].m_msSemantics = 0; - } - } - - // Save the unique name. - m_MemberList[ix].m_pName = pszName; - ::SysFreeString(bstrName); - bstrName = 0; - } - -ErrExit: - if (pITI2) - pITI2->Release(); - if (psAttr) - pITI->ReleaseTypeAttr(psAttr); - if (bstrName) - ::SysFreeString(bstrName); - ::VariantClear(&vt); - return hr; -} // HRESULT CImportTlb::BuildMemberList() - -//***************************************************************************** -// Free the list built in BuildMemberList(). -//***************************************************************************** -HRESULT CImportTlb::FreeMemberList( - ITypeInfo *pITI) // TypeInfo with functions. -{ - int ix; // Loop control. - for (ix=0; ix<m_cMemberProps; ++ix) - pITI->ReleaseVarDesc(m_MemberList[ix].m_psVar); - m_cMemberProps = 0; - for (; ix<(int)m_MemberList.Size(); ++ix) - pITI->ReleaseFuncDesc(m_MemberList[ix].m_psFunc); - m_MemberList.Shrink(0); - if (m_pMemberNames) - { - delete m_pMemberNames; - m_pMemberNames = 0; - } - return S_OK; -} // HRESULT CImportTlb::FreeMemberList() - -//***************************************************************************** -// Set a GUID CustomAttribute on an object. -//***************************************************************************** -HRESULT CImportTlb::_AddGuidCa( // S_OK or error. - mdToken tkObj, // Object to be attributed. - REFGUID guid) // The GUID. -{ - HRESULT hr; // A result. - mdMemberRef mr; // MemberRef for GUID CA. - WCHAR wzGuid[40]; // Buffer for Guid, Unicode. - CHAR szGuid[40]; // Buffer for Guid, Ansi. - DECLARE_CUSTOM_ATTRIBUTE(40); - - // If GUID_NULL, don't store it. - if (guid == GUID_NULL) - return S_OK; - - // Get the GUID as a string. - // ----+----1----+----2----+----3----+----4 - // {12345678-1234-1234-1234-123456789012} - GuidToLPWSTR(guid, wzGuid, lengthof(wzGuid)); - _ASSERTE(wzGuid[37] == W('}')); - wzGuid[37] = W('\0'); - WszWideCharToMultiByte(CP_UTF8, 0, wzGuid+1,-1, szGuid,sizeof(szGuid), 0,0); - - // Put it in the Custom Attribute. - APPEND_STRING_TO_CUSTOM_ATTRIBUTE(szGuid); - - // Store the attribute - IfFailGo(GetAttrType(ATTR_GUID, &mr)); - FINISH_CUSTOM_ATTRIBUTE(); - IfFailGo(m_pEmit->DefineCustomAttribute(tkObj, mr, PTROF_CUSTOM_ATTRIBUTE(), SIZEOF_CUSTOM_ATTRIBUTE(), 0)); - -ErrExit: - return hr; -} // HRESULT CImportTlb::_AddGuidCa() - -//***************************************************************************** -// Add a default member as a custom attribute. -//***************************************************************************** -HRESULT CImportTlb::_AddDefaultMemberCa(// S_OK or error. - mdToken tkObj, // TypeDef with default member. - LPCWSTR wzName) // Name of the default member. -{ - // Only set once per typedef. - if (tkObj == m_tdHasDefault) - return S_OK; - m_tdHasDefault = tkObj; - - return _AddStringCa(ATTR_DEFAULTMEMBER, tkObj, wzName); -} // HRESULT CImportTlb::_AddDefaultMemberCa() - -//***************************************************************************** -// Add a string custom attribute of the given type to the token. -//***************************************************************************** -HRESULT CImportTlb::_AddStringCa( // S_OK or error. - int attr, // The type of the CA. - mdToken tk, // Token to add the CA to. - LPCWSTR wzString) // String to put in the CA. -{ - HRESULT hr = S_OK; // A result. - mdMemberRef mr; // MemberRef for DefaultMember CA. - BYTE *pca; // Pointer to custom attribute. - BYTE *ca; // Pointer to custom attribute. - int wzLen; // Length of wide string. - int len; // Length of the string. - CQuickArray<BYTE> buf; - - if (wzString == NULL) - { - hr = E_INVALIDARG; - goto ErrExit; - } - - // Prolog, up to 4 bytes length, string, epilog - wzLen = (int)wcslen(wzString); - len = WszWideCharToMultiByte(CP_UTF8,0, wzString, wzLen, 0,0, 0,0); - IfFailGo(buf.ReSizeNoThrow(2 + 4 + len + 2)); - ca = pca = buf.Ptr(); - - // Add prolog. - *reinterpret_cast<UNALIGNED USHORT*>(pca) = 1; - pca += sizeof(USHORT); - - // Add length. - pca = reinterpret_cast<BYTE*>(CPackedLen::PutLength(pca, len)); - - // Add string. - WszWideCharToMultiByte(CP_UTF8,0, wzString, wzLen, reinterpret_cast<char*>(pca), len, 0, 0); - pca += len; - - // Add epilog. - *reinterpret_cast<UNALIGNED USHORT*>(pca) = 0; - pca += sizeof(USHORT); - - // Store the attribute - IfFailGo(GetAttrType(attr, &mr)); - IfFailGo(m_pEmit->DefineCustomAttribute(tk, mr, ca, (ULONG)(pca-ca), 0)); - -ErrExit: - return hr; -} // HRESULT CImportTlb::_AddStringCa() - -//***************************************************************************** -// Add a referenced typelib to the list of referenced typelibs. Check if -// it is "this" typelib first. -//***************************************************************************** -HRESULT CImportTlb::_AddTlbRef( // S_OK or error. - ITypeLib *pITLB, // The referenced typelib. - mdAssemblyRef *par, // The AssemblyRef in this module. - BSTR *pwzNamespace, // The namespace contained in the resolved assembly. - BSTR *pwzAsmName, // The name of the resolved assembly. - CImpTlbDefItfToClassItfMap **ppDefItfToClassItfMap) // The default interface to class interface map. -{ - HRESULT hr = S_OK; // A result. - IUnknown *pIUnk=0; // IUnknown for external assembly. - mdAssemblyRef ar=0; // Assembly ref in the module containing the typeref. - ITypeLib2 *pITLB2=0; // To get custom attributes. - VARIANT vt; // Variant type. - Assembly* ResolvedAssembly=0; // The resolved assembly. - CImpTlbDefItfToClassItfMap *pDefItfToClassItfMap; // Temp def itf to class itf map. - - // Validate the arguments. - _ASSERTE(pITLB && par && pwzNamespace && pwzAsmName); - - // Initialize the out parameters to NULL. - *par = mdTokenNil; - *pwzNamespace = NULL; - *pwzAsmName = NULL; - if (ppDefItfToClassItfMap) - *ppDefItfToClassItfMap = NULL; - - ::VariantInit(&vt); - - // If not the importing typelib, add it to the list. - if (pITLB == m_pITLB) - { // Not an external assembly. - //*par = mdAssemblyRefNil; - *par = TokenFromRid(1, mdtModule); - IfNullGo(*pwzNamespace = SysAllocStringLen(m_wzNamespace, SysStringLen(m_wzNamespace))); - *pwzAsmName = NULL; - if (ppDefItfToClassItfMap) - *ppDefItfToClassItfMap = &m_DefItfToClassItfMap; - return S_OK; - } - - // If already resolved, just return assembly ref. - if (m_LibRefs.Find(pITLB, par, pwzNamespace, pwzAsmName, NULL, ppDefItfToClassItfMap)) - return S_OK; - - // See if the typelib was exported, in which case it already has assembly ref information. - if (pITLB->QueryInterface(IID_ITypeLib2, reinterpret_cast<void**>(&pITLB2)) == S_OK) - { - hr = pITLB2->GetCustData(GUID_ExportedFromComPlus, &vt); - if (vt.vt == VT_BSTR) - { - // Use the CA data to get a reference. - //CQuickArray<BYTE> rBuf; - //int iLen; - // The buffer should have been converted with CP_ACP, and should convert back directly. - //IfFailGo(rBuf.ReSizeNoThrow(iLen=::SysStringLen(vt.bstrVal))); - //if (iLen=WszWideCharToMultiByte(CP_ACP,0, vt.bstrVal,iLen, (char*)rBuf.Ptr(),iLen, 0,0)) - { - // Define the assembly ref for the exported assembly. - //ar = DefineAssemblyRefForExportedAssembly(rBuf.Ptr(),(DWORD)rBuf.Size(), m_pEmit); - ar = DefineAssemblyRefForExportedAssembly(vt.bstrVal, m_pEmit); - - // Retrieve the namespace from the typelib. - IfFailGo(GetNamespaceNameForTypeLib(pITLB, pwzNamespace)); - - // Set the assembly name. - IfNullGo(*pwzAsmName = SysAllocStringLen(vt.bstrVal, SysStringLen(vt.bstrVal))); - } - } - } - - // If it wasn't directly converted to a reference, callback to the resolver. - if (IsNilToken(ar)) - { - // Get the assembly for that typelib. - if (FAILED(m_Notify->ResolveRef(pITLB, &pIUnk))) - IfFailGo(TLBX_I_RESOLVEREFFAILED); - - // If a NULL assembly was returned, then stop converting the type but - // continue the import. - if (pIUnk == NULL) - IfFailGo(TLBX_E_INVALID_TYPEINFO); - - // Create an assembly ref in local assembly for referenced assembly. - ar = DefineAssemblyRefForImportedTypeLib(m_pAssembly, m_pModule, m_pEmit, pIUnk, pwzNamespace, pwzAsmName, &ResolvedAssembly); - } - - // Make sure the ref was resolved before adding to cache. - if (IsNilToken(ar)) - IfFailGo(TLBX_I_RESOLVEREFFAILED); - - // Add the TLB to the list of references. - IfFailGo(m_LibRefs.Add(pITLB, this, ar, *pwzNamespace, *pwzAsmName, ResolvedAssembly, &pDefItfToClassItfMap)); - - // Set the output parameters. - *par = ar; - if (ppDefItfToClassItfMap) - *ppDefItfToClassItfMap = pDefItfToClassItfMap; - -ErrExit: - if (FAILED(hr)) - { - if (*pwzNamespace) - { - SysFreeString(*pwzNamespace); - *pwzNamespace = NULL; - } - if (*pwzAsmName) - { - SysFreeString(*pwzAsmName); - *pwzAsmName = NULL; - } - } - if (pIUnk) - pIUnk->Release(); - if (pITLB2) - pITLB2->Release(); - VariantClear(&vt); - - return hr; -} // HRESULT CImportTlb::_AddTlbRef() - -//***************************************************************************** -// Error reporting helper. -//***************************************************************************** -HRESULT CImportTlb::ReportEvent( // Returns the original HR. - int ev, // The event kind. - int hrRpt, // HR. - ...) // Variable args. -{ - HRESULT hr; // A result. - va_list marker; // User text. - BSTR bstrBuf=0; // BSTR for bufferrr. - BSTR bstrMsg=0; // BSTR for message. - const int iSize = 1024; // Message size; - - // We need a BSTR anyway for the call to ReportEvent, so just allocate a - // big one for the buffer. - IfNullGo(bstrBuf = ::SysAllocStringLen(0, iSize)); - - // Format the message. - va_start(marker, hrRpt); - hr = FormatRuntimeErrorVa(bstrBuf, iSize, hrRpt, marker); - va_end(marker); - - // Display it. - IfNullGo(bstrMsg = ::SysAllocString(bstrBuf)); - m_Notify->ReportEvent(static_cast<ImporterEventKind>(ev), hrRpt, bstrMsg); - -ErrExit: - // Clean up. - if (bstrBuf) - ::SysFreeString(bstrBuf); - if (bstrMsg) - ::SysFreeString(bstrMsg); - return hrRpt; -} // HRESULT CImportTlb::ReportEvent() - -//***************************************************************************** -// Helper function to perform the shared functions of creating a TypeRef. -//***************************************************************************** -HRESULT CImpTlbTypeRef::DefineTypeRef( // S_OK or error. - IMetaDataEmit *pEmit, // Emit interface. - mdAssemblyRef ar, // The system assemblyref. - const LPCWSTR szURL, // URL of the TypeDef, wide chars. - mdTypeRef *ptr) // Put mdTypeRef here -{ - HRESULT hr = S_OK; // A result. - LPCWSTR szLookup; // The name to look up. - mdToken tkNester; // Token of enclosing class. - - // If the name contains a '+', this is a nested type. The first part becomes - // the resolution scope for the part after the '+'. - szLookup = wcsrchr(szURL, NESTED_SEPARATOR_WCHAR); - if (szLookup) - { - CQuickArray<WCHAR> qbName; - IfFailGo(qbName.ReSizeNoThrow(szLookup - szURL + 1)); - wcsncpy_s(qbName.Ptr(), (szLookup - szURL + 1), szURL, szLookup - szURL); - IfFailGo(DefineTypeRef(pEmit, ar, qbName.Ptr(), &tkNester)); - ar = tkNester; - ++szLookup; - } - else - szLookup = szURL; - - // Look for the item in the map. - CImpTlbTypeRef::TokenOfTypeRefHashKey sSearch, *pMapped; - - sSearch.tkResolutionScope = ar; - sSearch.szName = szLookup; - pMapped = m_Map.Find(&sSearch); - - if (pMapped) - { - *ptr = pMapped->tr; - goto ErrExit; - } - - // Wasn't found, create a new one and add to the map. - hr = pEmit->DefineTypeRefByName(ar, szLookup, ptr); - if (SUCCEEDED(hr)) - { - sSearch.tr = *ptr; - pMapped = m_Map.Add(&sSearch); - IfNullGo(pMapped); - } - -ErrExit: - return (hr); -} // HRESULT CImpTlbTypeRef::DefineTypeRef() - -//***************************************************************************** -// Free the held typelibs in the list of imported typelibs. -//***************************************************************************** -CImpTlbLibRef::~CImpTlbLibRef() -{ - for (ULONG i = 0; i < Size(); i++) - { - SysFreeString(operator[](i).szNameSpace); - delete operator[](i).pDefItfToClassItfMap; - } -} // CImpTlbLibRef::~CImpTlbLibRef() - -//***************************************************************************** -// Add a new typelib reference to the list. -//***************************************************************************** -HRESULT CImpTlbLibRef::Add( - ITypeLib *pITLB, - CImportTlb *pImporter, - mdAssemblyRef ar, - BSTR wzNamespace, - BSTR wzAsmName, - Assembly* assm, - CImpTlbDefItfToClassItfMap **ppMap) -{ - HRESULT hr = S_OK; // A result. - TLIBATTR *pAttr=0; // A typelib attribute. - ULONG i; // Index. - CTlbRef *pTlbRef=0; // A pointer to the TlbRef struct. - CImpTlbDefItfToClassItfMap *pDefItfToClassItfMap = NULL; // ptr to the default interface to class interface map. - - // Validate the arguments. - _ASSERTE(wzNamespace); - _ASSERTE(wzAsmName); - - IfFailGo(pITLB->GetLibAttr(&pAttr)); - -#if defined(_DEBUG) - for (i=0; i<Size(); ++i) - { - if (operator[](i).guid == pAttr->guid) - { - _ASSERTE(!"External TypeLib already referenced"); - goto ErrExit; - } - } -#else - i = (ULONG)Size(); -#endif - - // Allocate and initialize the default interface to class interface map. - pDefItfToClassItfMap = new (nothrow) CImpTlbDefItfToClassItfMap(); - IfNullGo(pDefItfToClassItfMap); - IfFailGo(pDefItfToClassItfMap->Init(pITLB, wzNamespace)); - - // Attemp to resize the array. - IfFailGo(ReSizeNoThrow(i+1)); - pTlbRef = &operator[](i); - pTlbRef->guid = pAttr->guid; - pTlbRef->ar = ar; - IfNullGo(pTlbRef->szNameSpace = SysAllocString(wzNamespace)); - IfNullGo(pTlbRef->szAsmName = SysAllocString(wzAsmName)); - pTlbRef->pDefItfToClassItfMap = pDefItfToClassItfMap; - pTlbRef->Asm = assm; - -ErrExit: - if (pAttr) - pITLB->ReleaseTLibAttr(pAttr); - if (FAILED(hr)) - { - if (pTlbRef && pTlbRef->szNameSpace) - SysFreeString(pTlbRef->szNameSpace); - if (pTlbRef && pTlbRef->szAsmName) - SysFreeString(pTlbRef->szAsmName); - delete pDefItfToClassItfMap; - } - else - { - *ppMap = pDefItfToClassItfMap; - } - - return hr; -} // void CImpTlbLibRef::Add() - -//***************************************************************************** -// Find an existing typelib reference. -//***************************************************************************** -int CImpTlbLibRef::Find( - ITypeLib *pITLB, - mdAssemblyRef *par, - BSTR *pwzNamespace, - BSTR *pwzAsmName, - Assembly** assm, - CImpTlbDefItfToClassItfMap **ppDefItfToClassItfMap) -{ - HRESULT hr; // A result. - TLIBATTR *pAttr=0; // A typelib attribute. - int rslt = FALSE; // Return result. - ULONG i; // Loop control. - - _ASSERTE(pwzNamespace); - _ASSERTE(pwzAsmName); - - // Initalize the out parameters to NULL. - *pwzNamespace = NULL; - *pwzAsmName = NULL; - - if (assm) - *assm = NULL; - - IfFailGo(pITLB->GetLibAttr(&pAttr)); - - for (i=0; i<Size(); ++i) - { - if (operator[](i).guid == pAttr->guid) - { - *par = operator[](i).ar; - IfNullGo(*pwzNamespace = SysAllocString(operator[](i).szNameSpace)); - IfNullGo(*pwzAsmName = SysAllocString(operator[](i).szAsmName)); - if (ppDefItfToClassItfMap) - *ppDefItfToClassItfMap = operator[](i).pDefItfToClassItfMap; - if (assm) - *assm = operator[](i).Asm; - rslt = TRUE; - goto ErrExit; - } - } - -ErrExit: - if (FAILED(hr)) - { - if (*pwzNamespace) - SysFreeString(*pwzNamespace); - if (*pwzAsmName) - SysFreeString(*pwzAsmName); - } - if (pAttr) - pITLB->ReleaseTLibAttr(pAttr); - return rslt; -} // void CImpTlbLibRef::Find() - -//***************************************************************************** -// unpack variant to an ELEMENT_TYPE_* plus a blob value -// If VT_BOOL, it is a two-byte value. -//***************************************************************************** -HRESULT _UnpackVariantToConstantBlob(VARIANT *pvar, BYTE *pcvType, void **pvValue, __int64 *pd) -{ - HRESULT hr = NOERROR; - - switch (pvar->vt) - { - case VT_BOOL: - *pcvType = ELEMENT_TYPE_BOOLEAN; - *((VARIANT_BOOL **)pvValue) = &(pvar->boolVal); - break; - case VT_I1: - *pcvType = ELEMENT_TYPE_I1; - *((CHAR **)pvValue) = &(pvar->cVal); - break; - case VT_UI1: - *pcvType = ELEMENT_TYPE_U1; - *((BYTE **)pvValue) = &(pvar->bVal); - break; - case VT_I2: - *pcvType = ELEMENT_TYPE_I2; - *((SHORT **)pvValue) = &(pvar->iVal); - break; - case VT_UI2: - *pcvType = ELEMENT_TYPE_U2; - *((USHORT **)pvValue) = &(pvar->uiVal); - break; - case VT_I4: - case VT_INT: - *pcvType = ELEMENT_TYPE_I4; - *((LONG **)pvValue) = &(pvar->lVal); - break; - case VT_UI4: - case VT_UINT: - *pcvType = ELEMENT_TYPE_U4; - *((ULONG **)pvValue) = &(pvar->ulVal); - break; - case VT_R4: - *pcvType = ELEMENT_TYPE_R4; - *((float **)pvValue) = &(pvar->fltVal); - break; - case VT_I8: - *pcvType = ELEMENT_TYPE_I8; - *((LONGLONG **)pvValue) = &(pvar->cyVal.int64); - break; - case VT_R8: - *pcvType = ELEMENT_TYPE_R8; - *((double **)pvValue) = &(pvar->dblVal); - break; - case VT_BSTR: - *pcvType = ELEMENT_TYPE_STRING; - *((BSTR *)pvValue) = pvar->bstrVal; - break; - - case VT_DATE: - *pcvType = ELEMENT_TYPE_I8; - *pd = _DoubleDateToTicks(pvar->date); - *((LONGLONG **)pvValue) = pd; - break; - case VT_UNKNOWN: - case VT_DISPATCH: - *pcvType = ELEMENT_TYPE_CLASS; - _ASSERTE(pvar->punkVal == NULL); - *((IUnknown ***)pvValue) = &(pvar->punkVal); - break; - default: - _ASSERTE(!"Not a valid type to specify default value!"); - IfFailGo( META_E_BAD_INPUT_PARAMETER ); - break; - } -ErrExit: - return hr; -} // HRESULT _UnpackVariantToConstantBlob() - -//***************************************************************************** -// Stolen from classlib. -//***************************************************************************** -INT64 _DoubleDateToTicks(const double d) -{ - const INT64 MillisPerSecond = 1000; - const INT64 MillisPerDay = MillisPerSecond * 60 * 60 * 24; - const INT64 TicksPerMillisecond = 10000; - const INT64 TicksPerSecond = TicksPerMillisecond * 1000; - const INT64 TicksPerMinute = TicksPerSecond * 60; - const INT64 TicksPerHour = TicksPerMinute * 60; - const INT64 TicksPerDay = TicksPerHour * 24; - const int DaysPer4Years = 365 * 4 + 1; - const int DaysPer100Years = DaysPer4Years * 25 - 1; - const int DaysPer400Years = DaysPer100Years * 4 + 1; - const int DaysTo1899 = DaysPer400Years * 4 + DaysPer100Years * 3 - 367; - const INT64 DoubleDateOffset = DaysTo1899 * TicksPerDay; - const int DaysTo10000 = DaysPer400Years * 25 - 366; - const INT64 MaxMillis = DaysTo10000 * MillisPerDay; - - INT64 millis = (INT64)(d * MillisPerDay + (d >= 0? 0.5: -0.5)); - if (millis < 0) millis -= (millis % MillisPerDay) * 2; - millis += DoubleDateOffset / TicksPerMillisecond; - if (millis < 0 || millis >= MaxMillis) { - return 0; - } - return millis * TicksPerMillisecond; -} // INT64 _DoubleDateToTicks() - - -//***************************************************************************** -// Wrapper for GetFuncDesc to catch errors. -//***************************************************************************** -static HRESULT TryGetFuncDesc( // S_OK or error. - ITypeInfo *pITI, // ITypeInfo with function. - int i, // Function index. - FUNCDESC **ppFunc) // Put FUNCDESC here. -{ - HRESULT hr; // A return code. - __try - { - hr = pITI->GetFuncDesc(i, ppFunc); - } - __except(1) - { - hr = PostError(TLBX_E_TLB_EXCEPTION, _exception_code()); - } - - return hr; -} // static HRESULT TryGetFuncDesc() - -//***************************************************************************** -// Implementation of a hashed ResolutionScope+Name to TypeRef map. -//***************************************************************************** -void CImpTlbTypeRef::CTokenOfTypeRefHash::Clear() -{ -#if defined(_DEBUG) - // printf("Name to TypeRef cache: %d buckets, %d used, %d collisions\n", Buckets(), Count(), Collisions()); -#endif - CClosedHash<class TokenOfTypeRefHashKey>::Clear(); -} // void CImpTlbTypeRef::CTokenOfTypeRefHash::Clear() - -unsigned int CImpTlbTypeRef::CTokenOfTypeRefHash::Hash(const TokenOfTypeRefHashKey *pData) -{ - // Starting value for hash. - ULONG hash = 5381; - - // Hash in the resolution scope token. - const BYTE *pbData = reinterpret_cast<const BYTE *>(&pData->tkResolutionScope); - int iSize = 4; - while (--iSize >= 0) - { - hash = ((hash << 5) + hash) ^ *pbData; - ++pbData; - } - - // Hash in the typeref name. - LPCWSTR szStr = pData->szName; - int c; - while ((c = *szStr) != 0) - { - hash = ((hash << 5) + hash) ^ c; - ++szStr; - } - - return hash; -} // unsigned int CImpTlbTypeRef::CTokenOfTypeRefHash::Hash() - -unsigned int CImpTlbTypeRef::CTokenOfTypeRefHash::Compare(const TokenOfTypeRefHashKey *p1, TokenOfTypeRefHashKey *p2) -{ - // Resolution scopes are fast to compare. - if (p1->tkResolutionScope < p2->tkResolutionScope) - return -1; - if (p1->tkResolutionScope > p2->tkResolutionScope) - return 1; - // But if they are the same, compare the names. - return wcscmp(p1->szName, p2->szName); -} // unsigned int CImpTlbTypeRef::CTokenOfTypeRefHash::Compare() - -CImpTlbTypeRef::CTokenOfTypeRefHash::ELEMENTSTATUS CImpTlbTypeRef::CTokenOfTypeRefHash::Status(TokenOfTypeRefHashKey *p) -{ - if (p->tkResolutionScope == static_cast<mdToken>(FREE)) - return (FREE); - if (p->tkResolutionScope == static_cast<mdToken>(DELETED)) - return (DELETED); - return (USED); -} // CImpTlbTypeRef::CTokenOfTypeRefHash::ELEMENTSTATUS CImpTlbTypeRef::CTokenOfTypeRefHash::Status() - -void CImpTlbTypeRef::CTokenOfTypeRefHash::SetStatus(TokenOfTypeRefHashKey *p, ELEMENTSTATUS s) -{ - p->tkResolutionScope = static_cast<mdToken>(s); -} // void CImpTlbTypeRef::CTokenOfTypeRefHash::SetStatus() - -void *CImpTlbTypeRef::CTokenOfTypeRefHash::GetKey(TokenOfTypeRefHashKey *p) -{ - return p; -} // void *CImpTlbTypeRef::CTokenOfTypeRefHash::GetKey() - -CImpTlbTypeRef::TokenOfTypeRefHashKey* CImpTlbTypeRef::CTokenOfTypeRefHash::Add(const TokenOfTypeRefHashKey *pData) -{ - LPWSTR pName; - const void *pvData = pData; - TokenOfTypeRefHashKey *pNew = Super::Add(const_cast<void*>(pvData)); - if (pNew == 0) - return 0; - pNew->szName = pName = m_Names.Alloc((ULONG)wcslen(pData->szName)+1); - if (pNew->szName == 0) - return 0; - wcscpy_s(pName, wcslen(pData->szName)+1, pData->szName); - pNew->tkResolutionScope = pData->tkResolutionScope; - pNew->tr = pData->tr; - - return pNew; -} // TokenOfTypeRefHashKey* CImpTlbTypeRef::CTokenOfTypeRefHash::Add() - -//***************************************************************************** -// Implementation of a hashed ITypeInfo * source interface to event information -// map. -//***************************************************************************** -HRESULT CImpTlbEventInfoMap::AddEventInfo(LPCWSTR szSrcItfName, mdTypeRef trEventItf, LPCWSTR szEventItfName, LPCWSTR szEventProviderName, Assembly* SrcItfAssembly) -{ - ImpTlbEventInfo sNew; - sNew.szSrcItfName = szSrcItfName; - sNew.trEventItf = trEventItf; - sNew.szEventItfName = szEventItfName; - sNew.szEventProviderName = szEventProviderName; - sNew.SrcItfAssembly = SrcItfAssembly; - return Add(&sNew) != NULL ? S_OK : E_OUTOFMEMORY; -} // BOOL CImpTlbEventInfoMap::AddEventInfo() - -ImpTlbEventInfo *CImpTlbEventInfoMap::FindEventInfo(LPCWSTR szSrcItfName) -{ - ImpTlbEventInfo sSearch, *pMapped; - sSearch.szSrcItfName = szSrcItfName; - pMapped = Find(&sSearch); - return pMapped; -} // ImpTlbEventInfo *CImpTlbEventInfoMap::FindEventInfo() - -HRESULT CImpTlbEventInfoMap::GetEventInfoList(CQuickArray<ImpTlbEventInfo*> &qbEvInfoList) -{ - HRESULT hr = S_OK; - int cCurrEvInfo = 0; - - // Resise the event info list. - IfFailGo(qbEvInfoList.ReSizeNoThrow(Count())); - - // Retrieve the first event info. - ImpTlbEventInfo *pEvInfo = GetFirst(); - - // Add all the event info's to the list. - while (pEvInfo) - { - qbEvInfoList[cCurrEvInfo++] = pEvInfo; - pEvInfo = GetNext(pEvInfo); - } - -ErrExit: - return hr; -} // HRESULT CImpTlbEventInfoMap::GetEventInfoList() - -unsigned int CImpTlbEventInfoMap::Hash(const ImpTlbEventInfo *pData) -{ - // Starting value for hash. - ULONG hash = 5381; - - // Hash in the source interface name. - LPCWSTR szStr = pData->szSrcItfName; - int c; - while ((c = *szStr) != 0) - { - hash = ((hash << 5) + hash) ^ c; - ++szStr; - } - - return hash; -} // unsigned int CImpTlbEventInfoMap::Hash() - -unsigned int CImpTlbEventInfoMap::Compare(const ImpTlbEventInfo *p1, ImpTlbEventInfo *p2) -{ - // Compare the source interface names. - return wcscmp(p1->szSrcItfName, p2->szSrcItfName); -} // unsigned int CImpTlbEventInfoMap::Compare() - -CImpTlbEventInfoMap::ELEMENTSTATUS CImpTlbEventInfoMap::Status(ImpTlbEventInfo *p) -{ - if (p->szSrcItfName == reinterpret_cast<LPCWSTR>(FREE)) - return (FREE); - if (p->szSrcItfName == reinterpret_cast<LPCWSTR>(DELETED)) - return (DELETED); - return (USED); -} // CImpTlbEventInfoMap::ELEMENTSTATUS CImpTlbEventInfoMap::Status() - -void CImpTlbEventInfoMap::SetStatus(ImpTlbEventInfo *p, ELEMENTSTATUS s) -{ - p->szSrcItfName = reinterpret_cast<LPCWSTR>(s); -} // void CImpTlbEventInfoMap::SetStatus() - -void *CImpTlbEventInfoMap::GetKey(ImpTlbEventInfo *p) -{ - return p; -} // void *CImpTlbEventInfoMap::GetKey() - -ImpTlbEventInfo* CImpTlbEventInfoMap::Add(const ImpTlbEventInfo *pData) -{ - // Add the new entry to the map. - const void *pvData = pData; - ImpTlbEventInfo *pNew = Super::Add(const_cast<void*>(pvData)); - if (pNew == 0) - return 0; - - // Copy the source interface name. - pNew->szSrcItfName = m_Names.Alloc((ULONG)wcslen(pData->szSrcItfName)+1); - if (pNew->szSrcItfName == 0) - return 0; - wcscpy_s((LPWSTR)pNew->szSrcItfName, wcslen(pData->szSrcItfName)+1, pData->szSrcItfName); - - // Copy the event interface type def. - pNew->trEventItf = pData->trEventItf; - - // Copy the event interface name. - pNew->szEventItfName = m_Names.Alloc((ULONG)wcslen(pData->szEventItfName)+1); - if (pNew->szEventItfName == 0) - return 0; - wcscpy_s((LPWSTR)pNew->szEventItfName, wcslen(pData->szEventItfName)+1, pData->szEventItfName); - - // Copy the event provider name. - pNew->szEventProviderName = m_Names.Alloc((ULONG)wcslen(pData->szEventProviderName)+1); - if (pNew->szEventProviderName == 0) - return 0; - wcscpy_s((LPWSTR)pNew->szEventProviderName, wcslen(pData->szEventProviderName)+1, pData->szEventProviderName); - - // Copy the Source Interface Assembly pointer - pNew->SrcItfAssembly = pData->SrcItfAssembly; - - // Return the new entry. - return pNew; -} // ImpTlbEventInfo* CImpTlbEventInfoMap::Add() - -CImpTlbDefItfToClassItfMap::CImpTlbDefItfToClassItfMap() -: CClosedHash<class ImpTlbClassItfInfo>(101) -, m_bstrNameSpace(NULL) -{ -} - -CImpTlbDefItfToClassItfMap::~CImpTlbDefItfToClassItfMap() -{ - Clear(); - if (m_bstrNameSpace) - { - ::SysFreeString(m_bstrNameSpace); - m_bstrNameSpace = NULL; - } -} - -HRESULT CImpTlbDefItfToClassItfMap::Init(ITypeLib *pTlb, BSTR bstrNameSpace) -{ - HRESULT hr; // A result. - int cTi; // Count of TypeInfos. - int i; // Loop control. - TYPEATTR *psAttr=0; // TYPEATTR for the ITypeInfo. - TYPEATTR *psDefItfAttr=0; // TYPEATTR for the default interface. - ITypeInfo *pITI=0; // The ITypeInfo. - ITypeInfo *pDefItfITI=0; // The ITypeInfo for the default interface. - - // Save the namespace. - IfNullGo(m_bstrNameSpace = SysAllocString(bstrNameSpace)); - - // How many TypeInfos? - IfFailGo(cTi = pTlb->GetTypeInfoCount()); - - // Iterate over them. - for (i = 0; i < cTi; ++i) - { - // Get the TypeInfo. - hr = pTlb->GetTypeInfo(i, &pITI); - if (SUCCEEDED(hr)) - { - // Retrieve the attributes of the type info. - IfFailGo(pITI->GetTypeAttr(&psAttr)); - - // If we are dealing with a CoClass, then set up the default interface to - // class interface mapping. - if (psAttr->typekind == TKIND_COCLASS) - IfFailGo(AddCoClassInterfaces(pITI, psAttr)); - - // Release for next TypeInfo. - if (psAttr) - { - pITI->ReleaseTypeAttr(psAttr); - psAttr = 0; - } - if (pITI) - { - pITI->Release(); - pITI = 0; - } - } - } - -ErrExit: - if (psAttr) - pITI->ReleaseTypeAttr(psAttr); - if (pITI) - pITI->Release(); - - return (hr); -} - -HRESULT CImpTlbDefItfToClassItfMap::AddCoClassInterfaces(ITypeInfo *pCoClassITI, TYPEATTR *pCoClassTypeAttr) -{ - HRESULT hr; // A result - HREFTYPE href; // HREFTYPE of an implemented interface. - INT ImplFlags; // ImplType flags. - int NumInterfaces; // The number of interfaces on the coclass. - int i; // A counter. - ITypeInfo *pItfITI=0; // The ITypeInfo for the current interface. - ITypeInfo *pBaseItfITI=0; // The ITypeInfo for the base interface. - TYPEATTR *psItfAttr=0; // TYPEATTR for the interface. - BSTR bstrClassItfName=0; // The name of the class interface. - - // Retrieve the name of the CoClass. - IfFailGo(GetManagedNameForTypeInfo(pCoClassITI, m_bstrNameSpace, NULL, &bstrClassItfName)); - - // Retrieve the default interface for the CoClass. - IfFailGo(CImportTlb::GetDefaultInterface(pCoClassITI, &pItfITI)); - - // If there is a default interface, then add it to the map. - if (hr == S_OK) - { - // Retrieve the attributes of the default interface type info. - IfFailGo(pItfITI->GetTypeAttr(&psItfAttr)); - - // If there already is a CoClass that implements this - // interface then we do not want to do the mapping. - ImpTlbClassItfInfo sSearch, *pMapped; - sSearch.ItfIID = psItfAttr->guid; - pMapped = Find(&sSearch); - if (pMapped) - { - // There already is a CoClass that implements the interface so - // we set the class itf name to NULL to indicate not to do the def - // itf to class itf convertion for this interface. - pMapped->szClassItfName = NULL; - } - else - { - // Unless the default interface is IUnknown or IDispatch, add the - // def itf to class itf entry to the map. - if (psItfAttr->guid != IID_IUnknown && psItfAttr->guid != IID_IDispatch) - { - ImpTlbClassItfInfo sNew; - sNew.ItfIID = psItfAttr->guid; - sNew.szClassItfName = bstrClassItfName; - IfNullGo(Add(&sNew)); - } - } - - // Release for next interface. - pItfITI->ReleaseTypeAttr(psItfAttr); - psItfAttr = 0; - pItfITI->Release(); - pItfITI = 0; - } - - // Retrieve the number of interfaces the coclass has - NumInterfaces = pCoClassTypeAttr->cImplTypes; - - // Go through all the interfaces and add them to the map. - for (i=0; i < NumInterfaces; i++) - { - // Get the impl flags. - IfFailGo(pCoClassITI->GetImplTypeFlags(i, &ImplFlags)); - - // If this is an implemented interface. - if (!(ImplFlags & IMPLTYPEFLAG_FSOURCE)) - { - IfFailGo(pCoClassITI->GetRefTypeOfImplType(i, &href)); - IfFailGo(pCoClassITI->GetRefTypeInfo(href, &pItfITI)); - - do - { - // Retrieve the attributes of the interface type info. - IfFailGo(pItfITI->GetTypeAttr(&psItfAttr)); - - // If there already is a CoClass that implements this - // interface then we do not want to do the mapping. - ImpTlbClassItfInfo sSearch, *pMapped; - sSearch.ItfIID = psItfAttr->guid; - pMapped = Find(&sSearch); - if (pMapped) - { - // There already is a CoClass that implements the interface. If that - // CoClass is not the current one, then we we set the class itf name - // to NULL to indicate not to do the def itf to class itf convertion - // for this interface. - if (pMapped->szClassItfName && wcscmp(pMapped->szClassItfName, bstrClassItfName) != 0) - pMapped->szClassItfName = NULL; - } - else - { - // Add an entry with a NULL name to prevent future substitutions. - ImpTlbClassItfInfo sNew; - sNew.ItfIID = psItfAttr->guid; - sNew.szClassItfName = NULL; - IfNullGo(Add(&sNew)); - } - - // If there is a base interface, then handle it also. - if (psItfAttr->cImplTypes == 1) - { - IfFailGo(pItfITI->GetRefTypeOfImplType(0, &href)); - IfFailGo(pItfITI->GetRefTypeInfo(href, &pBaseItfITI)); - } - - // Release for next interface. - if (psItfAttr) - { - pItfITI->ReleaseTypeAttr(psItfAttr); - psItfAttr = 0; - } - if (pItfITI) - { - pItfITI->Release(); - pItfITI = 0; - } - - // Set the current interface to the base interface. - pItfITI = pBaseItfITI; - pBaseItfITI = 0; - } - while(pItfITI); - } - } - -ErrExit: - if (psItfAttr) - pItfITI->ReleaseTypeAttr(psItfAttr); - if (pItfITI) - pItfITI->Release(); - if (bstrClassItfName) - ::SysFreeString(bstrClassItfName); - - return hr; -} - -LPCWSTR CImpTlbDefItfToClassItfMap::GetClassItfName(IID &rItfIID) -{ - ImpTlbClassItfInfo sSearch, *pMapped; - sSearch.ItfIID = rItfIID; - pMapped = Find(&sSearch); - return pMapped ? pMapped->szClassItfName : NULL; -} - -unsigned int CImpTlbDefItfToClassItfMap::Hash(const ImpTlbClassItfInfo *pData) -{ - // Starting value for hash. - ULONG hash = 5381; - - // Hash in the IID. - const BYTE *pbData = reinterpret_cast<const BYTE *>(&pData->ItfIID); - int iSize = sizeof(IID); - while (--iSize >= 0) - { - hash = ((hash << 5) + hash) ^ *pbData; - ++pbData; - } - - return hash; -} // unsigned int CImpTlbDefItfToClassItfMap::Hash() - -unsigned int CImpTlbDefItfToClassItfMap::Compare(const ImpTlbClassItfInfo *p1, ImpTlbClassItfInfo *p2) -{ - // Compare the IID's. - return memcmp(&p1->ItfIID, &p2->ItfIID, sizeof(IID)); -} // unsigned int CImpTlbEventInfoMap::Compare() - -CImpTlbDefItfToClassItfMap::ELEMENTSTATUS CImpTlbDefItfToClassItfMap::Status(ImpTlbClassItfInfo *p) -{ - if (IsEqualGUID(p->ItfIID, FREE_STATUS_GUID)) - { - return (FREE); - } - else if (IsEqualGUID(p->ItfIID, DELETED_STATUS_GUID)) - { - return (DELETED); - } - return (USED); -} // CImpTlbDefItfToClassItfMap::ELEMENTSTATUS CImpTlbEventInfoMap::Status() - -void CImpTlbDefItfToClassItfMap::SetStatus(ImpTlbClassItfInfo *p, ELEMENTSTATUS s) -{ - if (s == FREE) - { - p->ItfIID = FREE_STATUS_GUID; - } - else if (s == DELETED) - { - p->ItfIID = DELETED_STATUS_GUID; - } - else - { - _ASSERTE(!"Invalid status!"); - } -} // void CImpTlbDefItfToClassItfMap::SetStatus() - -void *CImpTlbDefItfToClassItfMap::GetKey(ImpTlbClassItfInfo *p) -{ - return p; -} // void *CImpTlbDefItfToClassItfMap::GetKey() - -ImpTlbClassItfInfo* CImpTlbDefItfToClassItfMap::Add(const ImpTlbClassItfInfo *pData) -{ - // Add the new entry to the map. - const void *pvData = pData; - ImpTlbClassItfInfo *pNew = Super::Add(const_cast<void*>(pvData)); - if (pNew == 0) - return 0; - - // Copy the IID. - pNew->ItfIID = pData->ItfIID; - - // Copy the class interface name. - if (pData->szClassItfName) - { - pNew->szClassItfName = m_Names.Alloc((ULONG)wcslen(pData->szClassItfName)+1); - if (pNew->szClassItfName == 0) - return 0; - wcscpy_s((LPWSTR)pNew->szClassItfName, wcslen(pData->szClassItfName)+1, pData->szClassItfName); - } - else - { - pNew->szClassItfName = NULL; - } - - // Return the new entry. - return pNew; -} // ImpTlbEventInfo* CImpTlbEventInfoMap::Add() - -// EOF ======================================================================= diff --git a/src/md/enc/liteweightstgdbrw.cpp b/src/md/enc/liteweightstgdbrw.cpp index 12779f59c0..9bd923c931 100644 --- a/src/md/enc/liteweightstgdbrw.cpp +++ b/src/md/enc/liteweightstgdbrw.cpp @@ -339,12 +339,7 @@ HRESULT CLiteWeightStgdbRW::OpenForRead( // If we're taking ownership of this memory..... if (IsOfTakeOwnership(dwFlags)) { -#ifdef FEATURE_METADATA_STANDALONE_WINRT_RO - // Shared memory uses ole32.dll - we cannot depend on it in the standalone WinRT Read-Only DLL - IfFailGo(E_INVALIDARG); -#else dmOpenFlags = (DBPROPMODE)(dmOpenFlags | DBPROP_TMODEF_SHAREDMEM); -#endif //!FEATURE_METADATA_STANDALONE_WINRT_RO } #ifdef FEATURE_METADATA_LOAD_TRUSTED_IMAGES if (IsOfTrustedImage(dwFlags)) @@ -1251,28 +1246,5 @@ BOOL CLiteWeightStgdbRW::IsValidFileNameLength( const WCHAR * wszFileName) { -#ifdef FEATURE_CORECLR return TRUE; -#else - static const WCHAR const_wszLongPathPrefix[] = W("\\\\?\\"); - - if (wszFileName == NULL) - { - return TRUE; - } - size_t cchFileName = wcslen(wszFileName); - if (cchFileName < _MAX_PATH) - { - return TRUE; - } - if (SString::_wcsnicmp(wszFileName, const_wszLongPathPrefix, _countof(const_wszLongPathPrefix) - 1) != 0) - { // Path does not have long path prefix \\?\ (as required by CreateFile API) - return FALSE; - } - if (cchFileName < 32767) - { // Limit for the long path length as defined in CreateFile API - return TRUE; - } - return FALSE; -#endif } // CLiteWeightStgdbRW::IsValidFileNameLength diff --git a/src/md/enc/metamodelenc.cpp b/src/md/enc/metamodelenc.cpp index 4d972827ca..7460d580dc 100644 --- a/src/md/enc/metamodelenc.cpp +++ b/src/md/enc/metamodelenc.cpp @@ -263,18 +263,6 @@ CMiniMdRW::ApplyDelta( return E_INVALIDARG; } -#ifndef FEATURE_CORECLR - // Verify that the delta is based on the base. - IfFailGo(mdDelta.getEncBaseIdOfModule(pModDelta, &GuidDelta)); - IfFailGo(getEncBaseIdOfModule(pModBase,&GuidBase)); - if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_MD_DeltaCheck) && - CLRConfig::GetConfigValue(CLRConfig::INTERNAL_MD_UseMinimalDeltas) && - (GuidDelta != GuidBase)) - { - _ASSERTE(!"The Delta MetaData is based on a different generation than the current MetaData."); - return E_INVALIDARG; - } -#endif //!FEATURE_CORECLR // Let the other md prepare for sparse records. IfFailGo(mdDelta.StartENCMap()); @@ -390,19 +378,6 @@ ErrExit: HRESULT hrReturn = hr; IfFailRet(mdDelta.EndENCMap()); -#ifndef FEATURE_CORECLR - if (SUCCEEDED(hrReturn) && - CLRConfig::GetConfigValue(CLRConfig::INTERNAL_MD_DeltaCheck) && - CLRConfig::GetConfigValue(CLRConfig::INTERNAL_MD_UseMinimalDeltas)) - { - GUID GuidNewBase; - - // We'll use the delta's 'delta guid' for our new base guid - IfFailRet(mdDelta.getEncIdOfModule(pModDelta, &GuidNewBase)); - - IfFailRet(PutGuid(TBL_Module, ModuleRec::COL_EncBaseId, pModBase, GuidNewBase)); - } -#endif //!FEATURE_CORECLR return hrReturn; } // CMiniMdRW::ApplyDelta diff --git a/src/md/enc/metamodelrw.cpp b/src/md/enc/metamodelrw.cpp index f9002b6fa9..6a3bc327ef 100644 --- a/src/md/enc/metamodelrw.cpp +++ b/src/md/enc/metamodelrw.cpp @@ -4317,11 +4317,6 @@ CMiniMdRW::SaveHotPoolsToStream( UINT32 *pnPoolDirSize, UINT32 *pnHeapsSavedSize) { -// @todo: Triton workaround: FEATURE_METADATA_STANDALNE_WINRT_RO is supposed to disable FEATURE_PREJIT - remove this #if once we figure out how to get that working in the CoreClr build. -#ifdef FEATURE_METADATA_STANDALONE_WINRT_RO - _ASSERTE(!"SaveHotPoolsToStream: This method not supported in RoMetadata.dll"); - return E_NOTIMPL; -#else // FEATURE_METADATA_STANDALONE_WINRT_RO HRESULT hr = S_OK; UINT32 rgHeapSavedSize[MDPoolCount] = { 0, 0, 0, 0 }; @@ -4393,7 +4388,6 @@ CMiniMdRW::SaveHotPoolsToStream( } return S_OK; -#endif //FEATURE_METADATA_STANDALONE_WINRT_RO } // CMiniMdRW::SaveHotPoolsToStream // write hot data of specific blob @@ -4406,11 +4400,6 @@ CMiniMdRW::SaveHotPoolToStream( MetaData::HotHeapWriter *pHotHeapWriter, UINT32 *pnSavedSize) { -// @todo: Triton workaround: FEATURE_METADATA_STANDALNE_WINRT_RO is supposed to disable FEATURE_PREJIT - remove this #if once we figure out how to get that working in the CoreClr build. -#ifdef FEATURE_METADATA_STANDALONE_WINRT_RO - _ASSERTE(!"SaveHotPoolToStream: This method not supported in RoMetadata.dll"); - return E_NOTIMPL; -#else //FEATURE_METADATA_STANDALONE_WINRT_RO _ASSERTE(pProfileData != NULL); @@ -4435,7 +4424,6 @@ CMiniMdRW::SaveHotPoolToStream( } return S_OK; -#endif // FEATURE_METADATA_STANDALONE_WINRT_RO } // CMiniMdRW::SaveHotPoolToStream #endif //FEATURE_PREJIT @@ -8228,19 +8216,6 @@ CMiniMdRW::ResetENCLog() // Get the module record. IfFailGo(GetModuleRecord(1, &pMod)); -#ifndef FEATURE_CORECLR - if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_MD_UseMinimalDeltas)) - { // Update the ENC Guids - GUID encid; - // Copy EncId as BaseId. - ULONG uVal = GetCol(TBL_Module, ModuleRec::COL_EncId, pMod); - IfFailGo(PutCol(TBL_Module, ModuleRec::COL_EncBaseId, pMod, uVal)); - - // Allocate a new GUID for EncId. - IfFailGo(CoCreateGuid(&encid)); - IfFailGo(PutGuid(TBL_Module, ModuleRec::COL_EncId, pMod, encid)); - } -#endif //!FEATURE_CORECLR // Reset the pool deltas m_StringHeap.StartNewEnCSession(); diff --git a/src/md/enc/rwutil.cpp b/src/md/enc/rwutil.cpp index 874d972716..a00eddb3f1 100644 --- a/src/md/enc/rwutil.cpp +++ b/src/md/enc/rwutil.cpp @@ -952,149 +952,6 @@ ErrExit: - -//********************************************************************************************************* -// -// Merge Token manager's constructor -// -//********************************************************************************************************* -MergeTokenManager::MergeTokenManager(MDTOKENMAP *pTkMapList, IUnknown *pHandler) -{ - m_cRef = 1; - m_pTkMapList = pTkMapList; - m_pDefaultHostRemap = NULL; - if (pHandler) - pHandler->QueryInterface(IID_IMapToken, (void **) &m_pDefaultHostRemap); -} // TokenManager::TokenManager() - - - -//********************************************************************************************************* -// -// Merge Token manager's destructor -// -//********************************************************************************************************* -MergeTokenManager::~MergeTokenManager() -{ - if (m_pDefaultHostRemap) - m_pDefaultHostRemap->Release(); -} // TokenManager::~TokenManager() - - - - -ULONG MergeTokenManager::AddRef() -{ - return InterlockedIncrement(&m_cRef); -} // TokenManager::AddRef() - - - -ULONG MergeTokenManager::Release() -{ - ULONG cRef = InterlockedDecrement(&m_cRef); - if (!cRef) - delete this; - return (cRef); -} // TokenManager::Release() - - -HRESULT MergeTokenManager::QueryInterface(REFIID riid, void **ppUnk) -{ - if (ppUnk == NULL) - return E_INVALIDARG; - - if (IsEqualIID(riid, IID_IMapToken)) - { - //*ppUnk = (IUnknown *) (IMapToken *) this; - // it should return the accurate type requested, - // if IUnknown is returned, it will finally converted to IMapToken* - *ppUnk = (IMapToken *) this; - } - else if (IsEqualIID(riid, IID_IUnknown)) - { - // add query handling for IUnknown - // this upcasting (converting a derived-class - // reference or pointer to a base-class) is safe - *ppUnk = (IUnknown *) this; - } - else - { - *ppUnk = NULL; - return (E_NOINTERFACE); - } - - AddRef(); - return (S_OK); -} // TokenManager::QueryInterface - - - -//********************************************************************************************************* -// -// Token manager keep tracks a list of tokenmaps. Each tokenmap corresponding -// to an imported scope. Note that with this, we do have problem in how to -// tell linker regarding the token movement when the token is added by Define -// rather than merge. This should be fixed with new merge implementation. -// The tkImp is the old tokens in the emit scope, tkEmit is the new token in the -// emit scope. We need to find the token from an import scope that is resolved -// to the tkImp. We then need to tell linker about this token movement. -// If we don't find any import scope which generates the tkImp token, that is -// this tkImp is generated by calling DefinXXX directly on the final merged scope. -// Then we use the default host remap to send the notification. -// -//********************************************************************************************************* -HRESULT MergeTokenManager::Map(mdToken tkImp, mdToken tkEmit) -{ - HRESULT hr = NOERROR; - MDTOKENMAP *pTkMapList = m_pTkMapList; - bool fFoundInImport = false; - int iPosition; - TOKENREC *pRec; - - _ASSERTE(m_pTkMapList); - while ( pTkMapList ) - { - // FindWithToToken will return the first match with the To token. - // pTkMapList is sorted with To token. It might contain several From tokens - // that map to the To token due to ref to def optimiation. Make sure that - // all notification is sent to all of these From tokens. - // - if ( pTkMapList->FindWithToToken(tkImp, &iPosition) ) - { - // make sure that we don't walk over the last entry - while (iPosition < pTkMapList->Count()) - { - pRec = pTkMapList->Get(iPosition); - if (pRec->m_tkTo != tkImp) - { - // we are done! - break; - } - - // more matching record... - fFoundInImport = true; - if (pTkMapList->m_pMap) - hr = pTkMapList->m_pMap->Map(pRec->m_tkFrom, tkEmit); - _ASSERTE(SUCCEEDED(hr)); - IfFailGo( hr ); - iPosition++; - } - } - pTkMapList = pTkMapList->m_pNextMap; - } - - if (fFoundInImport == false && m_pDefaultHostRemap) - { - // use the default remap to send the notification - IfFailGo( m_pDefaultHostRemap->Map(tkImp, tkEmit) ); - } -ErrExit: - return hr; -} - - - //********************************************************************************************************* // // CMapToken's constructor diff --git a/src/md/enc/stgio.cpp b/src/md/enc/stgio.cpp index 27d5ff2c5d..9dea3cb689 100644 --- a/src/md/enc/stgio.cpp +++ b/src/md/enc/stgio.cpp @@ -42,17 +42,10 @@ #include "pedecoder.inl" //********** Types. *********************************************************** -#if !defined(FEATURE_METADATA_STANDALONE_WINRT_RO) #define SMALL_ALLOC_MAP_SIZE (64 * 1024) // 64 kb is the minimum size of virtual // memory you can allocate, so anything // less is a waste of VM resources. -#else //FEATURE_METADATA_STANDALONE_WINRT_RO -// RoMetadata.dll is required to call CreateFileMapping on all WinMD files (even small ones) to use -// Code Intergrity checks on Win8 - see code:#EnableCodeIntegrity -#define SMALL_ALLOC_MAP_SIZE 0 - -#endif //FEATURE_METADATA_STANDALONE_WINRT_RO #define MIN_WRITE_CACHE_BYTES (16 * 1024) // 16 kb for a write back cache @@ -154,7 +147,6 @@ HRESULT StgIO::Open( // Return code. m_pData = (void *) pbBuff; m_cbData = cbBuff; -#ifndef FEATURE_METADATA_STANDALONE_WINRT_RO // All access to data will be by memory provided. if ((fFlags & DBPROP_TMODEF_SHAREDMEM) == DBPROP_TMODEF_SHAREDMEM) { @@ -163,7 +155,6 @@ HRESULT StgIO::Open( // Return code. m_iType = STGIO_SHAREDMEM; } else -#endif //!FEATURE_METADATA_STANDALONE_WINRT_RO { m_iType = STGIO_MEM; } @@ -359,7 +350,6 @@ void StgIO::Close() { switch (m_iType) { -#ifndef FEATURE_METADATA_STANDALONE_WINRT_RO // Free any allocated memory. case STGIO_SHAREDMEM: if (m_pBaseData != NULL) @@ -368,7 +358,6 @@ void StgIO::Close() m_pBaseData = NULL; break; } -#endif //!FEATURE_METADATA_STANDALONE_WINRT_RO case STGIO_MEM: case STGIO_HFILEMEM: @@ -538,9 +527,7 @@ HRESULT StgIO::Read( // Return code. // Simply copy the data from our data. case STGIO_MEM: -#ifndef FEATURE_METADATA_STANDALONE_WINRT_RO case STGIO_SHAREDMEM: -#endif case STGIO_HFILEMEM: { _ASSERTE(m_pData && m_cbData); @@ -686,9 +673,7 @@ HRESULT StgIO::Seek( // New offset. break; case STGIO_MEM: -#ifndef FEATURE_METADATA_STANDALONE_WINRT_RO case STGIO_SHAREDMEM: -#endif case STGIO_HFILEMEM: case STGIO_HMODULE: { @@ -770,9 +755,7 @@ HRESULT StgIO::MapFileToMem( // Return code. if (IsBackingStore() || IsMemoryMapped() || (m_iType == STGIO_MEM) || -#ifndef FEATURE_METADATA_STANDALONE_WINRT_RO (m_iType == STGIO_SHAREDMEM) || -#endif (m_iType == STGIO_HFILEMEM)) { ptr = m_pData; @@ -854,24 +837,13 @@ HRESULT StgIO::MapFileToMem( // Return code. _ASSERTE(m_hMapping == 0); DWORD dwProtectionFlags = PAGE_READONLY; -#ifdef FEATURE_METADATA_STANDALONE_WINRT_RO - //#EnableCodeIntegrity - // RoMetadata.dll is required to always map (WinMD) files with SEC_IMAGE to enable Code Integrity checkes on Win8 - // Note: MidlRtMd.dll cannot do the same, because it runs on pre-Win8 OS versions where SEC_IMAGE-mapping will likely - // refuse WinMD files (they are Win8+ only in PE headers) - dwProtectionFlags |= SEC_IMAGE; -#endif if ((m_hMapping = WszCreateFileMapping(m_hFile, pAttributes, dwProtectionFlags, 0, 0, nullptr)) == 0) { return (MapFileError(GetLastError())); } -#ifdef FEATURE_METADATA_STANDALONE_WINRT_RO - m_mtMappedType = MTYPE_IMAGE; -#else // FEATURE_METADATA_STANDALONE_WINRT_RO m_mtMappedType = MTYPE_FLAT; -#endif // FEATURE_METADATA_STANDALONE_WINRT_RO // Check to see if the memory already exists, in which case we have // no guarantees it is the right piece of data. if (GetLastError() == ERROR_ALREADY_EXISTS) @@ -958,7 +930,6 @@ ErrExit: HRESULT StgIO::ReleaseMappingObject() // Return code. { // Check type first. -#ifndef FEATURE_METADATA_STANDALONE_WINRT_RO if (m_iType != STGIO_SHAREDMEM) { _ASSERTE(FALSE); @@ -982,7 +953,6 @@ HRESULT StgIO::ReleaseMappingObject() // Return code. VERIFY(CloseHandle(m_hMapping)); m_hMapping = 0; } -#endif //!FEATURE_METADATA_STANDALONE_WINRT_RO return S_OK; } @@ -998,7 +968,6 @@ HRESULT StgIO::SetBaseRange( // Return code. void *pbStart, // Start of file data. ULONG cbSize) // How big is the range. { -#ifndef FEATURE_METADATA_STANDALONE_WINRT_RO if (m_iType == STGIO_SHAREDMEM) { // The base range must be inside of the current range. @@ -1006,7 +975,6 @@ HRESULT StgIO::SetBaseRange( // Return code. _ASSERTE(((LONG_PTR) pbStart >= (LONG_PTR) m_pBaseData)); _ASSERTE(((LONG_PTR) pbStart + cbSize <= (LONG_PTR) m_pBaseData + m_cbData)); } -#endif //!FEATURE_METADATA_STANDALONE_WINRT_RO // Save the base range per user request. m_pData = pbStart; @@ -1117,9 +1085,7 @@ HRESULT StgIO::GetPtrForMem( // Return code. // Memory version or memory mapped file work the same way. else if (IsMemoryMapped() || (m_iType == STGIO_MEM) || -#ifndef FEATURE_METADATA_STANDALONE_WINRT_RO (m_iType == STGIO_SHAREDMEM) || -#endif (m_iType == STGIO_HFILEMEM)) { if (!(cbStart <= m_cbData)) @@ -1245,9 +1211,7 @@ HRESULT StgIO::WriteToDisk( // Return code. // We cannot write to fixed read/only memory or LoadLibrary module. case STGIO_HMODULE: case STGIO_MEM: -#ifndef FEATURE_METADATA_STANDALONE_WINRT_RO case STGIO_SHAREDMEM: -#endif _ASSERTE(0); hr = BadError(E_UNEXPECTED); break; @@ -1384,9 +1348,7 @@ int StgIO::IsAlignedPtr(ULONG_PTR Value, int iAlignment) void *ptrStart = NULL; if ((m_iType == STGIO_STREAM) || -#ifndef FEATURE_METADATA_STANDALONE_WINRT_RO (m_iType == STGIO_SHAREDMEM) || -#endif (m_iType == STGIO_MEM)) { return ((Value - (ULONG_PTR) m_pData) % iAlignment == 0); diff --git a/src/md/enc/stgtiggerstorage.cpp b/src/md/enc/stgtiggerstorage.cpp index 436b3d72e3..2c8420d02d 100644 --- a/src/md/enc/stgtiggerstorage.cpp +++ b/src/md/enc/stgtiggerstorage.cpp @@ -138,9 +138,6 @@ TiggerStorage::GetDefaultVersion( if (g_pDefaultVersion == NULL) { -#ifdef FEATURE_METADATA_STANDALONE_WINRT - g_pDefaultVersion = ""; -#else //!FEATURE_METADATA_STANDALONE_WINRT #ifndef DACCESS_COMPILE HRESULT hr; @@ -170,7 +167,6 @@ TiggerStorage::GetDefaultVersion( #else DacNotImpl(); #endif //DACCESS_COMPILE -#endif //!FEATURE_METADATA_STANDALONE_WINRT } *ppVersion = g_pDefaultVersion; diff --git a/src/md/enc/wks/CMakeLists.txt b/src/md/enc/wks/CMakeLists.txt index df7664187d..2c0a2b1af5 100644 --- a/src/md/enc/wks/CMakeLists.txt +++ b/src/md/enc/wks/CMakeLists.txt @@ -1,4 +1,6 @@ include(../../md_wks.cmake) +add_definitions(-DFEATURE_METADATA_EMIT_ALL) + add_precompiled_header(stdafx.h ../stdafx.cpp MDRUNTIMERW_SOURCES) add_library_clr(mdruntimerw_wks ${MDRUNTIMERW_SOURCES}) diff --git a/src/md/hotdata/hotdataformat.h b/src/md/hotdata/hotdataformat.h index 0823010611..3431d18deb 100644 --- a/src/md/hotdata/hotdataformat.h +++ b/src/md/hotdata/hotdataformat.h @@ -35,7 +35,7 @@ namespace MetaData // #HotMetaData // To help with startup time, we create a section of metadata that is only that meta-data that was touched // durring IBC profiling. Given an offset into a pool this checks if we have any hot data associated with -// it. If we do we return a poitner to it, otherwse we return NULL. +// it. If we do we return a pointer to it, otherwse we return NULL. #include <pshpack1.h> diff --git a/src/md/inc/assemblymdinternaldisp.h b/src/md/inc/assemblymdinternaldisp.h index 91b7d2cc29..8e8017ee9b 100644 --- a/src/md/inc/assemblymdinternaldisp.h +++ b/src/md/inc/assemblymdinternaldisp.h @@ -14,710 +14,5 @@ #include "../runtime/mdinternalro.h" -#ifdef FEATURE_FUSION - -#include "fusionpriv.h" - -struct CORCOMPILE_VERSION_INFO; -struct CORCOMPILE_DEPENDENCY; - -//***************************************************************************** -// This class can support the IMetaDataAssemblyImport and some funcationalities -// of IMetaDataImport on the internal import interface (IMDInternalImport). -//***************************************************************************** -class AssemblyMDInternalImport : - public IMetaDataAssemblyImport, - public IMetaDataImport2, -#ifdef FEATURE_PREJIT - public IGetIMDInternalImport, -#endif //FEATURE_PREJIT - public ISNAssemblySignature -#ifdef FEATURE_PREJIT - , public INativeImageInstallInfo -#endif // FEATURE_PREJIT -{ -public: - AssemblyMDInternalImport(IMDInternalImport *pMDInternalImport); - ~AssemblyMDInternalImport(); - - // *** IUnknown methods *** - STDMETHODIMP QueryInterface(REFIID riid, void** ppUnk); - STDMETHODIMP_(ULONG) AddRef(void); - STDMETHODIMP_(ULONG) Release(void); - - // *** IMetaDataAssemblyImport methods *** - STDMETHODIMP GetAssemblyProps ( // S_OK or error. - mdAssembly mda, // [IN] The Assembly for which to get the properties. - const void **ppbPublicKey, // [OUT] Pointer to the public key. - ULONG *pcbPublicKey, // [OUT] Count of bytes in the public key. - ULONG *pulHashAlgId, // [OUT] Hash Algorithm. - __out_ecount (cchName) LPWSTR szName, // [OUT] Buffer to fill with name. - ULONG cchName, // [IN] Size of buffer in wide chars. - ULONG *pchName, // [OUT] Actual # of wide chars in name. - ASSEMBLYMETADATA *pMetaData, // [OUT] Assembly MetaData. - DWORD *pdwAssemblyFlags); // [OUT] Flags. - - STDMETHODIMP GetAssemblyRefProps ( // S_OK or error. - mdAssemblyRef mdar, // [IN] The AssemblyRef for which to get the properties. - const void **ppbPublicKeyOrToken, // [OUT] Pointer to the public key or token. - ULONG *pcbPublicKeyOrToken, // [OUT] Count of bytes in the public key or token. - __out_ecount (cchName) LPWSTR szName, // [OUT] Buffer to fill with name. - ULONG cchName, // [IN] Size of buffer in wide chars. - ULONG *pchName, // [OUT] Actual # of wide chars in name. - ASSEMBLYMETADATA *pMetaData, // [OUT] Assembly MetaData. - const void **ppbHashValue, // [OUT] Hash blob. - ULONG *pcbHashValue, // [OUT] Count of bytes in the hash blob. - DWORD *pdwAssemblyRefFlags); // [OUT] Flags. - - STDMETHODIMP GetFileProps ( // S_OK or error. - mdFile mdf, // [IN] The File for which to get the properties. - __out_ecount (cchName) LPWSTR szName, // [OUT] Buffer to fill with name. - ULONG cchName, // [IN] Size of buffer in wide chars. - ULONG *pchName, // [OUT] Actual # of wide chars in name. - const void **ppbHashValue, // [OUT] Pointer to the Hash Value Blob. - ULONG *pcbHashValue, // [OUT] Count of bytes in the Hash Value Blob. - DWORD *pdwFileFlags); // [OUT] Flags. - - STDMETHODIMP GetExportedTypeProps ( // S_OK or error. - mdExportedType mdct, // [IN] The ExportedType for which to get the properties. - __out_ecount (cchName) LPWSTR szName, // [OUT] Buffer to fill with name. - ULONG cchName, // [IN] Size of buffer in wide chars. - ULONG *pchName, // [OUT] Actual # of wide chars in name. - mdToken *ptkImplementation, // [OUT] mdFile or mdAssemblyRef or mdExportedType. - mdTypeDef *ptkTypeDef, // [OUT] TypeDef token within the file. - DWORD *pdwExportedTypeFlags); // [OUT] Flags. - - STDMETHODIMP GetManifestResourceProps ( // S_OK or error. - mdManifestResource mdmr, // [IN] The ManifestResource for which to get the properties. - __out_ecount (cchName) LPWSTR szName, // [OUT] Buffer to fill with name. - ULONG cchName, // [IN] Size of buffer in wide chars. - ULONG *pchName, // [OUT] Actual # of wide chars in name. - mdToken *ptkImplementation, // [OUT] mdFile or mdAssemblyRef that provides the ManifestResource. - DWORD *pdwOffset, // [OUT] Offset to the beginning of the resource within the file. - DWORD *pdwResourceFlags); // [OUT] Flags. - - STDMETHODIMP EnumAssemblyRefs ( // S_OK or error - HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. - mdAssemblyRef rAssemblyRefs[], // [OUT] Put AssemblyRefs here. - ULONG cMax, // [IN] Max AssemblyRefs to put. - ULONG *pcTokens); // [OUT] Put # put here. - - STDMETHODIMP EnumFiles ( // S_OK or error - HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. - mdFile rFiles[], // [OUT] Put Files here. - ULONG cMax, // [IN] Max Files to put. - ULONG *pcTokens); // [OUT] Put # put here. - - STDMETHODIMP EnumExportedTypes ( // S_OK or error - HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. - mdExportedType rExportedTypes[], // [OUT] Put ExportedTypes here. - ULONG cMax, // [IN] Max ExportedTypes to put. - ULONG *pcTokens); // [OUT] Put # put here. - - STDMETHODIMP EnumManifestResources ( // S_OK or error - HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. - mdManifestResource rManifestResources[], // [OUT] Put ManifestResources here. - ULONG cMax, // [IN] Max Resources to put. - ULONG *pcTokens); // [OUT] Put # put here. - - STDMETHODIMP GetAssemblyFromScope ( // S_OK or error - mdAssembly *ptkAssembly); // [OUT] Put token here. - - STDMETHODIMP FindExportedTypeByName ( // S_OK or error - LPCWSTR szName, // [IN] Name of the ExportedType. - mdToken mdtExportedType, // [IN] ExportedType for the enclosing class. - mdExportedType *ptkExportedType); // [OUT] Put the ExportedType token here. - - STDMETHODIMP FindManifestResourceByName ( // S_OK or error - LPCWSTR szName, // [IN] Name of the ManifestResource. - mdManifestResource *ptkManifestResource); // [OUT] Put the ManifestResource token here. - - STDMETHOD_(void, CloseEnum)( - HCORENUM hEnum); // Enum to be closed. - - STDMETHODIMP FindAssembliesByName ( // S_OK or error - LPCWSTR szAppBase, // [IN] optional - can be NULL - LPCWSTR szPrivateBin, // [IN] optional - can be NULL - LPCWSTR szAssemblyName, // [IN] required - this is the assembly you are requesting - IUnknown *ppIUnk[], // [OUT] put IMetaDataAssemblyImport pointers here - ULONG cMax, // [IN] The max number to put - ULONG *pcAssemblies); // [OUT] The number of assemblies returned. - - // *** IMetaDataImport methods *** - STDMETHOD(CountEnum)(HCORENUM hEnum, ULONG *pulCount); - STDMETHOD(ResetEnum)(HCORENUM hEnum, ULONG ulPos); - STDMETHOD(EnumTypeDefs)(HCORENUM *phEnum, mdTypeDef rTypeDefs[], - ULONG cMax, ULONG *pcTypeDefs); - STDMETHOD(EnumInterfaceImpls)(HCORENUM *phEnum, mdTypeDef td, - mdInterfaceImpl rImpls[], ULONG cMax, - ULONG* pcImpls); - STDMETHOD(EnumTypeRefs)(HCORENUM *phEnum, mdTypeRef rTypeRefs[], - ULONG cMax, ULONG* pcTypeRefs); - - STDMETHOD(FindTypeDefByName)( // S_OK or error. - LPCWSTR szTypeDef, // [IN] Name of the Type. - mdToken tkEnclosingClass, // [IN] TypeDef/TypeRef for Enclosing class. - mdTypeDef *ptd); // [OUT] Put the TypeDef token here. - - STDMETHOD(GetScopeProps)( - __out_ecount_part_opt(cchName, *pchName) - LPWSTR wszName, // [OUT] Put the name here. - ULONG cchName, // [IN] Size of name buffer in wide chars. - ULONG * pchName, // [OUT] Put size of name (wide chars) here. - GUID * pMvid); // [OUT, OPTIONAL] Put MVID here. - - STDMETHOD(GetModuleFromScope)( // S_OK. - mdModule *pmd); // [OUT] Put mdModule token here. - - STDMETHOD(GetTypeDefProps)( - mdTypeDef td, // [IN] TypeDef token for inquiry. - __out_ecount_part_opt(cchTypeDef, *pchTypeDef) - LPWSTR wszTypeDef, // [OUT] Put name here. - ULONG cchTypeDef, // [IN] size of name buffer in wide chars. - ULONG * pchTypeDef, // [OUT] put size of name (wide chars) here. - DWORD * pdwTypeDefFlags, // [OUT] Put flags here. - mdToken * ptkExtends); // [OUT] Put base class TypeDef/TypeRef here. - - STDMETHOD(GetInterfaceImplProps)( // S_OK or error. - mdInterfaceImpl iiImpl, // [IN] InterfaceImpl token. - mdTypeDef *pClass, // [OUT] Put implementing class token here. - mdToken *ptkIface); // [OUT] Put implemented interface token here. - - STDMETHOD(GetTypeRefProps)( - mdTypeRef tr, // [IN] TypeRef token. - mdToken * ptkResolutionScope, // [OUT] Resolution scope, ModuleRef or AssemblyRef. - __out_ecount_part_opt(cchName, *pchName) - LPWSTR wszName, // [OUT] Name of the TypeRef. - ULONG cchName, // [IN] Size of buffer. - ULONG * pchName); // [OUT] Size of Name. - - STDMETHOD(ResolveTypeRef)(mdTypeRef tr, REFIID riid, IUnknown **ppIScope, mdTypeDef *ptd); - - STDMETHOD(EnumMembers)( // S_OK, S_FALSE, or error. - HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. - mdTypeDef cl, // [IN] TypeDef to scope the enumeration. - mdToken rMembers[], // [OUT] Put MemberDefs here. - ULONG cMax, // [IN] Max MemberDefs to put. - ULONG *pcTokens); // [OUT] Put # put here. - - STDMETHOD(EnumMembersWithName)( // S_OK, S_FALSE, or error. - HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. - mdTypeDef cl, // [IN] TypeDef to scope the enumeration. - LPCWSTR szName, // [IN] Limit results to those with this name. - mdToken rMembers[], // [OUT] Put MemberDefs here. - ULONG cMax, // [IN] Max MemberDefs to put. - ULONG *pcTokens); // [OUT] Put # put here. - - STDMETHOD(EnumMethods)( // S_OK, S_FALSE, or error. - HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. - mdTypeDef cl, // [IN] TypeDef to scope the enumeration. - mdMethodDef rMethods[], // [OUT] Put MethodDefs here. - ULONG cMax, // [IN] Max MethodDefs to put. - ULONG *pcTokens); // [OUT] Put # put here. - - STDMETHOD(EnumMethodsWithName)( // S_OK, S_FALSE, or error. - HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. - mdTypeDef cl, // [IN] TypeDef to scope the enumeration. - LPCWSTR szName, // [IN] Limit results to those with this name. - mdMethodDef rMethods[], // [OU] Put MethodDefs here. - ULONG cMax, // [IN] Max MethodDefs to put. - ULONG *pcTokens); // [OUT] Put # put here. - - STDMETHOD(EnumFields)( // S_OK, S_FALSE, or error. - HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. - mdTypeDef cl, // [IN] TypeDef to scope the enumeration. - mdFieldDef rFields[], // [OUT] Put FieldDefs here. - ULONG cMax, // [IN] Max FieldDefs to put. - ULONG *pcTokens); // [OUT] Put # put here. - - STDMETHOD(EnumFieldsWithName)( // S_OK, S_FALSE, or error. - HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. - mdTypeDef cl, // [IN] TypeDef to scope the enumeration. - LPCWSTR szName, // [IN] Limit results to those with this name. - mdFieldDef rFields[], // [OUT] Put MemberDefs here. - ULONG cMax, // [IN] Max MemberDefs to put. - ULONG *pcTokens); // [OUT] Put # put here. - - - STDMETHOD(EnumParams)( // S_OK, S_FALSE, or error. - HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. - mdMethodDef mb, // [IN] MethodDef to scope the enumeration. - mdParamDef rParams[], // [OUT] Put ParamDefs here. - ULONG cMax, // [IN] Max ParamDefs to put. - ULONG *pcTokens); // [OUT] Put # put here. - - STDMETHOD(EnumMemberRefs)( // S_OK, S_FALSE, or error. - HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. - mdToken tkParent, // [IN] Parent token to scope the enumeration. - mdMemberRef rMemberRefs[], // [OUT] Put MemberRefs here. - ULONG cMax, // [IN] Max MemberRefs to put. - ULONG *pcTokens); // [OUT] Put # put here. - - STDMETHOD(EnumMethodImpls)( // S_OK, S_FALSE, or error - HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. - mdTypeDef td, // [IN] TypeDef to scope the enumeration. - mdToken rMethodBody[], // [OUT] Put Method Body tokens here. - mdToken rMethodDecl[], // [OUT] Put Method Declaration tokens here. - ULONG cMax, // [IN] Max tokens to put. - ULONG *pcTokens); // [OUT] Put # put here. - - STDMETHOD(EnumPermissionSets)( // S_OK, S_FALSE, or error. - HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. - mdToken tk, // [IN] if !NIL, token to scope the enumeration. - DWORD dwActions, // [IN] if !0, return only these actions. - mdPermission rPermission[], // [OUT] Put Permissions here. - ULONG cMax, // [IN] Max Permissions to put. - ULONG *pcTokens); // [OUT] Put # put here. - - STDMETHOD(FindMember)( - mdTypeDef td, // [IN] given typedef - LPCWSTR szName, // [IN] member name - PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of COM+ signature - ULONG cbSigBlob, // [IN] count of bytes in the signature blob - mdToken *pmb); // [OUT] matching memberdef - - STDMETHOD(FindMethod)( - mdTypeDef td, // [IN] given typedef - LPCWSTR szName, // [IN] member name - PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of COM+ signature - ULONG cbSigBlob, // [IN] count of bytes in the signature blob - mdMethodDef *pmb); // [OUT] matching memberdef - - STDMETHOD(FindField)( - mdTypeDef td, // [IN] given typedef - LPCWSTR szName, // [IN] member name - PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of COM+ signature - ULONG cbSigBlob, // [IN] count of bytes in the signature blob - mdFieldDef *pmb); // [OUT] matching memberdef - - STDMETHOD(FindMemberRef)( - mdTypeRef td, // [IN] given typeRef - LPCWSTR szName, // [IN] member name - PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of COM+ signature - ULONG cbSigBlob, // [IN] count of bytes in the signature blob - mdMemberRef *pmr); // [OUT] matching memberref - - STDMETHOD (GetMethodProps)( - mdMethodDef mb, // The method for which to get props. - mdTypeDef * pClass, // Put method's class here. - __out_ecount_part_opt(cchMethod, *pchMethod) - LPWSTR wszMethod, // Put method's name here. - ULONG cchMethod, // Size of szMethod buffer in wide chars. - ULONG * pchMethod, // Put actual size here. - DWORD * pdwAttr, // Put flags here. - PCCOR_SIGNATURE * ppvSigBlob, // [OUT] point to the blob value of meta data - ULONG * pcbSigBlob, // [OUT] actual size of signature blob - ULONG * pulCodeRVA, // [OUT] codeRVA - DWORD * pdwImplFlags); // [OUT] Impl. Flags - - STDMETHOD(GetMemberRefProps)( - mdMemberRef mr, // [IN] given memberref - mdToken * ptk, // [OUT] Put classref or classdef here. - __out_ecount_part_opt(cchMember, *pchMember) - LPWSTR wszMember, // [OUT] buffer to fill for member's name - ULONG cchMember, // [IN] the count of char of szMember - ULONG * pchMember, // [OUT] actual count of char in member name - PCCOR_SIGNATURE * ppvSigBlob, // [OUT] point to meta data blob value - ULONG * pbSig); // [OUT] actual size of signature blob - - STDMETHOD(EnumProperties)( // S_OK, S_FALSE, or error. - HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. - mdTypeDef td, // [IN] TypeDef to scope the enumeration. - mdProperty rProperties[], // [OUT] Put Properties here. - ULONG cMax, // [IN] Max properties to put. - ULONG *pcProperties); // [OUT] Put # put here. - - STDMETHOD(EnumEvents)( // S_OK, S_FALSE, or error. - HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. - mdTypeDef td, // [IN] TypeDef to scope the enumeration. - mdEvent rEvents[], // [OUT] Put events here. - ULONG cMax, // [IN] Max events to put. - ULONG *pcEvents); // [OUT] Put # put here. - - STDMETHOD(GetEventProps)( // S_OK, S_FALSE, or error. - mdEvent ev, // [IN] event token - mdTypeDef *pClass, // [OUT] typedef containing the event declarion. - LPCWSTR szEvent, // [OUT] Event name - ULONG cchEvent, // [IN] the count of wchar of szEvent - ULONG *pchEvent, // [OUT] actual count of wchar for event's name - DWORD *pdwEventFlags, // [OUT] Event flags. - mdToken *ptkEventType, // [OUT] EventType class - mdMethodDef *pmdAddOn, // [OUT] AddOn method of the event - mdMethodDef *pmdRemoveOn, // [OUT] RemoveOn method of the event - mdMethodDef *pmdFire, // [OUT] Fire method of the event - mdMethodDef rmdOtherMethod[], // [OUT] other method of the event - ULONG cMax, // [IN] size of rmdOtherMethod - ULONG *pcOtherMethod); // [OUT] total number of other method of this event - - STDMETHOD(EnumMethodSemantics)( // S_OK, S_FALSE, or error. - HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. - mdMethodDef mb, // [IN] MethodDef to scope the enumeration. - mdToken rEventProp[], // [OUT] Put Event/Property here. - ULONG cMax, // [IN] Max properties to put. - ULONG *pcEventProp); // [OUT] Put # put here. - - STDMETHOD(GetMethodSemantics)( // S_OK, S_FALSE, or error. - mdMethodDef mb, // [IN] method token - mdToken tkEventProp, // [IN] event/property token. - DWORD *pdwSemanticsFlags); // [OUT] the role flags for the method/propevent pair - - STDMETHOD(GetClassLayout) ( - mdTypeDef td, // [IN] give typedef - DWORD *pdwPackSize, // [OUT] 1, 2, 4, 8, or 16 - COR_FIELD_OFFSET rFieldOffset[], // [OUT] field offset array - ULONG cMax, // [IN] size of the array - ULONG *pcFieldOffset, // [OUT] needed array size - ULONG *pulClassSize); // [OUT] the size of the class - - STDMETHOD(GetFieldMarshal) ( - mdToken tk, // [IN] given a field's memberdef - PCCOR_SIGNATURE *ppvNativeType, // [OUT] native type of this field - ULONG *pcbNativeType); // [OUT] the count of bytes of *ppvNativeType - - STDMETHOD(GetRVA)( // S_OK or error. - mdToken tk, // Member for which to set offset - ULONG *pulCodeRVA, // The offset - DWORD *pdwImplFlags); // the implementation flags - - STDMETHOD(GetPermissionSetProps) ( - mdPermission pm, // [IN] the permission token. - DWORD *pdwAction, // [OUT] CorDeclSecurity. - void const **ppvPermission, // [OUT] permission blob. - ULONG *pcbPermission); // [OUT] count of bytes of pvPermission. - - STDMETHOD(GetSigFromToken)( // S_OK or error. - mdSignature mdSig, // [IN] Signature token. - PCCOR_SIGNATURE *ppvSig, // [OUT] return pointer to token. - ULONG *pcbSig); // [OUT] return size of signature. - - STDMETHOD(GetModuleRefProps)( - mdModuleRef mur, // [IN] moduleref token. - __out_ecount_part_opt(cchName, *pchName) - LPWSTR wszName, // [OUT] buffer to fill with the moduleref name. - ULONG cchName, // [IN] size of szName in wide characters. - ULONG * pchName); // [OUT] actual count of characters in the name. - - STDMETHOD(EnumModuleRefs)( // S_OK or error. - HCORENUM *phEnum, // [IN|OUT] pointer to the enum. - mdModuleRef rModuleRefs[], // [OUT] put modulerefs here. - ULONG cmax, // [IN] max memberrefs to put. - ULONG *pcModuleRefs); // [OUT] put # put here. - - STDMETHOD(GetTypeSpecFromToken)( // S_OK or error. - mdTypeSpec typespec, // [IN] TypeSpec token. - PCCOR_SIGNATURE *ppvSig, // [OUT] return pointer to TypeSpec signature - ULONG *pcbSig); // [OUT] return size of signature. - - STDMETHOD(GetNameFromToken)( // <TODO>Not Recommended! May be removed!</TODO> - mdToken tk, // [IN] Token to get name from. Must have a name. - MDUTF8CSTR *pszUtf8NamePtr); // [OUT] Return pointer to UTF8 name in heap. - - STDMETHOD(EnumUnresolvedMethods)( // S_OK, S_FALSE, or error. - HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. - mdToken rMethods[], // [OUT] Put MemberDefs here. - ULONG cMax, // [IN] Max MemberDefs to put. - ULONG *pcTokens); // [OUT] Put # put here. - - STDMETHOD(GetUserString)( - mdString stk, // [IN] String token. - __out_ecount_part_opt(cchString, *pchString) - LPWSTR wszString, // [OUT] Copy of string. - ULONG cchString, // [IN] Max chars of room in szString. - ULONG * pchString); // [OUT] How many chars in actual string. - - STDMETHOD(GetPinvokeMap)( - mdToken tk, // [IN] FieldDef or MethodDef. - DWORD * pdwMappingFlags, // [OUT] Flags used for mapping. - __out_ecount_part_opt(cchImportName, *pchImportName) - LPWSTR wszImportName, // [OUT] Import name. - ULONG cchImportName, // [IN] Size of the name buffer. - ULONG * pchImportName, // [OUT] Actual number of characters stored. - mdModuleRef * pmrImportDLL); // [OUT] ModuleRef token for the target DLL. - - STDMETHOD(EnumSignatures)( // S_OK or error. - HCORENUM *phEnum, // [IN|OUT] pointer to the enum. - mdSignature rSignatures[], // [OUT] put signatures here. - ULONG cmax, // [IN] max signatures to put. - ULONG *pcSignatures); // [OUT] put # put here. - - STDMETHOD(EnumTypeSpecs)( // S_OK or error. - HCORENUM *phEnum, // [IN|OUT] pointer to the enum. - mdTypeSpec rTypeSpecs[], // [OUT] put TypeSpecs here. - ULONG cmax, // [IN] max TypeSpecs to put. - ULONG *pcTypeSpecs); // [OUT] put # put here. - - STDMETHOD(EnumUserStrings)( // S_OK or error. - HCORENUM *phEnum, // [IN/OUT] pointer to the enum. - mdString rStrings[], // [OUT] put Strings here. - ULONG cmax, // [IN] max Strings to put. - ULONG *pcStrings); // [OUT] put # put here. - - STDMETHOD(GetParamForMethodIndex)( // S_OK or error. - mdMethodDef md, // [IN] Method token. - ULONG ulParamSeq, // [IN] Parameter sequence. - mdParamDef *ppd); // [IN] Put Param token here. - - STDMETHOD(EnumCustomAttributes)( // S_OK or error. - HCORENUM *phEnum, // [IN, OUT] COR enumerator. - mdToken tk, // [IN] Token to scope the enumeration, 0 for all. - mdToken tkType, // [IN] Type of interest, 0 for all. - mdCustomAttribute rCustomAttributes[], // [OUT] Put custom attribute tokens here. - ULONG cMax, // [IN] Size of rCustomAttributes. - ULONG *pcCustomAttributes); // [OUT, OPTIONAL] Put count of token values here. - - STDMETHOD(GetCustomAttributeProps)( // S_OK or error. - mdCustomAttribute cv, // [IN] CustomAttribute token. - mdToken *ptkObj, // [OUT, OPTIONAL] Put object token here. - mdToken *ptkType, // [OUT, OPTIONAL] Put AttrType token here. - void const **ppBlob, // [OUT, OPTIONAL] Put pointer to data here. - ULONG *pcbSize); // [OUT, OPTIONAL] Put size of date here. - - STDMETHOD(FindTypeRef)( - mdToken tkResolutionScope, // [IN] ModuleRef, AssemblyRef or TypeRef. - LPCWSTR szName, // [IN] TypeRef Name. - mdTypeRef *ptr); // [OUT] matching TypeRef. - - STDMETHOD(GetMemberProps)( - mdToken mb, // The member for which to get props. - mdTypeDef * pClass, // Put member's class here. - __out_ecount_part_opt(cchMember, *pchMember) - LPWSTR wszMember, // Put member's name here. - ULONG cchMember, // Size of szMember buffer in wide chars. - ULONG * pchMember, // Put actual size here - DWORD * pdwAttr, // Put flags here. - PCCOR_SIGNATURE * ppvSigBlob, // [OUT] point to the blob value of meta data - ULONG * pcbSigBlob, // [OUT] actual size of signature blob - ULONG * pulCodeRVA, // [OUT] codeRVA - DWORD * pdwImplFlags, // [OUT] Impl. Flags - DWORD * pdwCPlusTypeFlag, // [OUT] flag for value type. selected ELEMENT_TYPE_* - UVCP_CONSTANT * ppValue, // [OUT] constant value - ULONG * pcchValue); // [OUT] size of constant string in chars, 0 for non-strings. - - STDMETHOD(GetFieldProps)( - mdFieldDef mb, // The field for which to get props. - mdTypeDef * pClass, // Put field's class here. - __out_ecount_part_opt(cchField, *pchField) - LPWSTR szField, // Put field's name here. - ULONG cchField, // Size of szField buffer in wide chars. - ULONG * pchField, // Put actual size here. - DWORD * pdwAttr, // Put flags here. - PCCOR_SIGNATURE * ppvSigBlob, // [OUT] point to the blob value of meta data. - ULONG * pcbSigBlob, // [OUT] actual size of signature blob. - DWORD * pdwCPlusTypeFlag, // [OUT] flag for value type. selected ELEMENT_TYPE_*. - UVCP_CONSTANT * ppValue, // [OUT] constant value. - ULONG * pcchValue); // [OUT] size of constant string in chars, 0 for non-strings. - - STDMETHOD(GetPropertyProps)( // S_OK, S_FALSE, or error. - mdProperty prop, // [IN] property token - mdTypeDef *pClass, // [OUT] typedef containing the property declarion. - LPCWSTR szProperty, // [OUT] Property name - ULONG cchProperty, // [IN] the count of wchar of szProperty - ULONG *pchProperty, // [OUT] actual count of wchar for property name - DWORD *pdwPropFlags, // [OUT] property flags. - PCCOR_SIGNATURE *ppvSig, // [OUT] property type. pointing to meta data internal blob - ULONG *pbSig, // [OUT] count of bytes in *ppvSig - DWORD *pdwCPlusTypeFlag, // [OUT] flag for value type. selected ELEMENT_TYPE_* - UVCP_CONSTANT *ppDefaultValue, // [OUT] constant value - ULONG *pcchDefaultValue, // [OUT] size of constant string in chars, 0 for non-strings. - mdMethodDef *pmdSetter, // [OUT] setter method of the property - mdMethodDef *pmdGetter, // [OUT] getter method of the property - mdMethodDef rmdOtherMethod[], // [OUT] other method of the property - ULONG cMax, // [IN] size of rmdOtherMethod - ULONG *pcOtherMethod); // [OUT] total number of other method of this property - - STDMETHOD(GetParamProps)( - mdParamDef tk, // [IN]The Parameter. - mdMethodDef * pmd, // [OUT] Parent Method token. - ULONG * pulSequence, // [OUT] Parameter sequence. - __out_ecount_part_opt(cchName, *pchName) - LPWSTR wszName, // [OUT] Put name here. - ULONG cchName, // [OUT] Size of name buffer. - ULONG * pchName, // [OUT] Put actual size of name here. - DWORD * pdwAttr, // [OUT] Put flags here. - DWORD * pdwCPlusTypeFlag, // [OUT] Flag for value type. selected ELEMENT_TYPE_*. - UVCP_CONSTANT * ppValue, // [OUT] Constant value. - ULONG * pcchValue); // [OUT] size of constant string in chars, 0 for non-strings. - - STDMETHOD(GetCustomAttributeByName)( // S_OK or error. - mdToken tkObj, // [IN] Object with Custom Attribute. - LPCWSTR szName, // [IN] Name of desired Custom Attribute. - const void **ppData, // [OUT] Put pointer to data here. - ULONG *pcbData); // [OUT] Put size of data here. - - STDMETHOD_(BOOL, IsValidToken)( // True or False. - mdToken tk); // [IN] Given token. - - STDMETHOD(GetNestedClassProps)( // S_OK or error. - mdTypeDef tdNestedClass, // [IN] NestedClass token. - mdTypeDef *ptdEnclosingClass); // [OUT] EnclosingClass token. - - STDMETHOD(GetNativeCallConvFromSig)( // S_OK or error. - void const *pvSig, // [IN] Pointer to signature. - ULONG cbSig, // [IN] Count of signature bytes. - ULONG *pCallConv); // [OUT] Put calling conv here (see CorPinvokemap). - - STDMETHOD(IsGlobal)( // S_OK or error. - mdToken pd, // [IN] Type, Field, or Method token. - int *pbGlobal); // [OUT] Put 1 if global, 0 otherwise. - -//***************************************************************************** -// IMetaDataImport2 methods -//***************************************************************************** - STDMETHOD(GetMethodSpecProps)( - mdMethodSpec mi, // [IN] The method instantiation - mdToken *tkParent, // [OUT] MethodDef or MemberRef - PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to the blob value of meta data - ULONG *pcbSigBlob); // [OUT] actual size of signature blob - - STDMETHOD(GetGenericParamProps)( - mdGenericParam gp, // [IN] GenericParam - ULONG * pulParamSeq, // [OUT] Index of the type parameter - DWORD * pdwParamFlags, // [OUT] Flags, for future use (e.g. variance) - mdToken * ptOwner, // [OUT] Owner (TypeDef or MethodDef) - DWORD * pdwReserved, // [OUT] For future use (e.g. non-type parameters) - __out_ecount_part_opt(cchName, *pchName) - LPWSTR wszName, // [OUT] Put name here - ULONG cchName, // [IN] Size of buffer - ULONG * pchName); // [OUT] Put size of name (wide chars) here. - - STDMETHOD(GetGenericParamConstraintProps)( // S_OK or error. - mdGenericParamConstraint gpc, // [IN] GenericParamConstraint - mdGenericParam *ptGenericParam, // [OUT] GenericParam that is constrained - mdToken *ptkConstraintType); // [OUT] TypeDef/Ref/Spec constraint - - STDMETHOD(EnumGenericParams)( // S_OK or error. - HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. - mdToken tk, // [IN] TypeDef or MethodDef whose generic parameters are requested - mdGenericParam rGenericParams[], // [OUT] Put GenericParams here. - ULONG cMax, // [IN] Max GenericParams to put. - ULONG *pcGenericParams); // [OUT] Put # put here. - - STDMETHOD(EnumGenericParamConstraints)( // S_OK or error. - HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. - mdGenericParam tk, // [IN] GenericParam whose constraints are requested - mdGenericParamConstraint rGenericParamConstraints[], // [OUT] Put GenericParamConstraints here. - ULONG cMax, // [IN] Max GenericParamConstraints to put. - ULONG *pcGenericParamConstraints); // [OUT] Put # put here. - - STDMETHOD(EnumMethodSpecs)( - HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. - mdToken tk, // [IN] MethodDef or MemberRef whose MethodSpecs are requested - mdMethodSpec rMethodSpecs[], // [OUT] Put MethodSpecs here. - ULONG cMax, // [IN] Max tokens to put. - ULONG *pcMethodSpecs); // [OUT] Put actual count here. - - STDMETHOD(GetPEKind)( // S_OK or error. - DWORD* pdwPEKind, // [OUT] The kind of PE (0 - not a PE) - DWORD* pdwMachine); // [OUT] Machine as defined in NT header - - STDMETHOD(GetVersionString)( - __out_ecount_part_opt(ccBufSize, *pccBufSize) - LPWSTR pwzBuf, // Put version string here. - DWORD ccBufSize, // [in] Size of the buffer, in wide chars. - DWORD * pccBufSize); // [out] Size of the version string, wide chars, including terminating nul. - - - // *** ISNAssemblySignature methods *** - - STDMETHOD(GetSNAssemblySignature)( // S_OK or error. - BYTE *pbSig, // [IN, OUT] Buffer to write signature - DWORD *pcbSig); // [IN, OUT] Size of buffer, bytes written - - -#ifdef FEATURE_PREJIT - // *** IGetIMDInternalImport methods *** - - STDMETHOD(GetIMDInternalImport) ( - IMDInternalImport ** ppIMDInternalImport); - - // *** INativeImageInstallInfo *** - - STDMETHOD (GetSignature) ( - CORCOMPILE_NGEN_SIGNATURE * pNgenSign - ); - - STDMETHOD (GetVersionInfo) ( - CORCOMPILE_VERSION_INFO * pVersionInfo - ); - - - STDMETHOD (GetILSignature) ( - CORCOMPILE_ASSEMBLY_SIGNATURE * pILSign - ); - - STDMETHOD (GetConfigMask) ( - DWORD * pConfigMask - ); - - STDMETHOD (EnumDependencies) ( - HCORENUM * phEnum, - INativeImageDependency *rDeps[], - ULONG cMax, - DWORD * pdwCount - ); - - STDMETHOD (GetDependency) ( - const CORCOMPILE_NGEN_SIGNATURE *pcngenSign, - CORCOMPILE_DEPENDENCY *pDep - ); - - -#endif // FEATURE_PREJIT - - //------------ setters for privates ----------- - void SetHandle(HCORMODULE hHandle) - { - RuntimeAddRefHandle(hHandle); - m_pHandle = hHandle; - } - - void SetPEKind(DWORD dwPEKind) - { - m_dwPEKind = dwPEKind; - } - - void SetMachine(DWORD dwMachine) - { - m_dwMachine = dwMachine; - } - - void SetVersionString(const char* szVersionString) - { - m_szVersionString = szVersionString; - } - - void SetBase(LPVOID base) - { - m_pBase = base; - } - -#ifdef FEATURE_PREJIT - void SetZapVersionInfo(CORCOMPILE_VERSION_INFO * info, CORCOMPILE_DEPENDENCY * pDeps, COUNT_T cDeps) - { - m_pZapVersionInfo = info; - m_pZapDependencies = pDeps; - m_cZapDependencies = cDeps; - } -#endif // FEATURE_PREJIT - -private: - LONG m_cRef; - HCORMODULE m_pHandle; // Handle to a cached PE image - LPVOID m_pBase; // File mapping (if runtime is not inited) -#ifdef FEATURE_PREJIT - struct CORCOMPILE_VERSION_INFO * m_pZapVersionInfo; // Zap image information - struct CORCOMPILE_DEPENDENCY * m_pZapDependencies; // Zap Dependancies directory - COUNT_T m_cZapDependencies; -#endif // FEATURE_PREJIT - IMDInternalImport * m_pMDInternalImport; - DWORD m_dwPEKind; - DWORD m_dwMachine; - const char * m_szVersionString; -#ifdef _DEBUG - IMetaDataAssemblyImport * m_pDebugMDImport; -#endif //_DEBUG -}; - -#endif // FEATURE_FUSION #endif // __AssemblyMDInternalDispenser__h__ diff --git a/src/md/inc/imptlb.h b/src/md/inc/imptlb.h deleted file mode 100644 index ba2981a415..0000000000 --- a/src/md/inc/imptlb.h +++ /dev/null @@ -1,777 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. -//***************************************************************************** -// File: imptlb.h -// - -// -// TypeLib importer. -//***************************************************************************** -#ifndef __imptlb_h__ -#define __imptlb_h__ - -#ifndef FEATURE_COMINTEROP -#error FEATURE_COMINTEROP is required for this file -#endif // FEATURE_COMINTEROP -#ifndef FEATURE_COMINTEROP_TLB_SUPPORT -#error FEATURE_COMINTEROP_TLB_SUPPORT is required for this file -#endif // FEATURE_COMINTEROP_TLB_SUPPORT - -//#define TLB_STATS - -#define MAX_TLB_VT VT_LPWSTR + 1 -#define MAX_INIT_SIG 3 -#define MAX_COM_GUID_SIG 6 -#define MAX_COM_ADDLISTENER_SIG 8 -#define MAX_COM_REMOVELISTENER_SIG 8 -#define CB_MAX_ELEMENT_TYPE 4 - -// Forward declarations. -struct ITypeLibImporterNotifySink; -class Assembly; -class Module; -class CImportTlb; - -//***************************************************************************** -// Class to perform memory management. Memory is not moved as the heap is -// expanded, and all of the allocations are cleaned up in the destructor. -//***************************************************************************** -class CWCHARPool : public StgPool -{ -public: - CWCHARPool() : StgPool() - { - HRESULT hr = InitNew(); - _ASSERTE(hr == S_OK); - } - - // Allocate some bytes from the pool. - WCHAR * Alloc(ULONG nChars) - { - BYTE *pRslt; - // Convert from characters to bytes. - nChars *= sizeof(WCHAR); - if (nChars > GetCbSegAvailable()) - if (!Grow(nChars)) - return 0; - pRslt = GetNextLocation(); - SegAllocate(nChars); - return (WCHAR*)pRslt; - } -}; // class CDescPool : public StgPool - - -//***************************************************************************** -// This helper method is used to track an url to typeref token. This makes -// defining new typerefs faster. -//***************************************************************************** -class CImpTlbTypeRef -{ -public: - CImpTlbTypeRef() { } - ~CImpTlbTypeRef() { m_Map.Clear(); } - - //***************************************************************************** - // Look for an existing typeref in the map and return if found. If not found, - // then create a new one and add it to the map for later. - //***************************************************************************** - HRESULT DefineTypeRef( // S_OK or error. - IMetaDataEmit *pEmit, // Emit interface. - mdAssemblyRef ar, // Containing assembly. - const LPCWSTR szURL, // URL of the TypeDef, wide chars. - mdTypeRef *ptr); // Put mdTypeRef here - - class TokenOfTypeRefHashKey - { - public: - mdToken tkResolutionScope; // TypeRef's resolution scope. - LPCWSTR szName; // TypeRef's name. - mdTypeRef tr; // The TypeRef's token. - }; - -private: - - class CTokenOfTypeRefHash : public CClosedHash<class TokenOfTypeRefHashKey> - { - public: - typedef CClosedHash<class TokenOfTypeRefHashKey> Super; - typedef TokenOfTypeRefHashKey T; - - CTokenOfTypeRefHash() : CClosedHash<class TokenOfTypeRefHashKey>(101) {} - ~CTokenOfTypeRefHash() { Clear(); } - - virtual void Clear(); - - unsigned int Hash(const void *pData) {return Hash((const T*)pData);} - unsigned int Hash(const T *pData); - - unsigned int Compare(const void *p1, BYTE *p2) {return Compare((const T*)p1, (T*)p2);} - unsigned int Compare(const T *p1, T *p2); - - ELEMENTSTATUS Status(BYTE *p) {return Status((T*)p);} - ELEMENTSTATUS Status(T *p); - - void SetStatus(BYTE *p, ELEMENTSTATUS s) {SetStatus((T*)p, s);} - void SetStatus(T *p, ELEMENTSTATUS s); - - void* GetKey(BYTE *p) {return GetKey((T*)p);} - void *GetKey(T *p); - - T* Add(const T *pData); - - CWCHARPool m_Names; // Heap of names. - }; - - CTokenOfTypeRefHash m_Map; // Map of namespace to token. -}; - - -//***************************************************************************** -// This helper class is used to track source interface ITypeInfo*'s to event -// information. -//***************************************************************************** -class ImpTlbEventInfo -{ -public: - LPCWSTR szSrcItfName; // The source interface name (the key). - mdTypeRef trEventItf; // The event interface typedef. - LPCWSTR szEventItfName; // The event interface name. - LPCWSTR szEventProviderName; // The event provider name. - Assembly* SrcItfAssembly; // The assembly where source interface resides. -}; - -class CImpTlbEventInfoMap : protected CClosedHash<class ImpTlbEventInfo> -{ -public: - typedef CClosedHash<class ImpTlbEventInfo> Super; - typedef ImpTlbEventInfo T; - - CImpTlbEventInfoMap() : CClosedHash<class ImpTlbEventInfo>(101) {} - ~CImpTlbEventInfoMap() { Clear(); } - - HRESULT AddEventInfo(LPCWSTR szSrcItfName, mdTypeRef trEventItf, LPCWSTR szEventItfName, LPCWSTR szEventProviderName, Assembly* SrcItfAssembly); - ImpTlbEventInfo *FindEventInfo(LPCWSTR szSrcItfName); - - HRESULT GetEventInfoList(CQuickArray<ImpTlbEventInfo*> &qbEvInfoList); - -private: - unsigned int Hash(const void *pData) {return Hash((const T*)pData);} - unsigned int Hash(const T *pData); - - unsigned int Compare(const void *p1, BYTE *p2) {return Compare((const T*)p1, (T*)p2);} - unsigned int Compare(const T *p1, T *p2); - - ELEMENTSTATUS Status(BYTE *p) {return Status((T*)p);} - ELEMENTSTATUS Status(T *p); - - void SetStatus(BYTE *p, ELEMENTSTATUS s) {SetStatus((T*)p, s);} - void SetStatus(T *p, ELEMENTSTATUS s); - - void* GetKey(BYTE *p) {return GetKey((T*)p);} - void *GetKey(T *p); - - T* Add(const T *pData); - - CWCHARPool m_Names; // Heap of names. -}; - - -#if defined(_UNICODE) || defined(UNICODE) -#define _tHashString(szStr) HashString(szStr) -#else -#define _tHashString(szStr) HashStringA(szStr) -#endif - - - -//***************************************************************************** -// This helper template is used by the TStringMap to track an item by its -// character name. -//***************************************************************************** -template <class T> class TStringMapItem : HASHENTRY -{ -public: - TStringMapItem() : - m_szString(0) - { - LIMITED_METHOD_CONTRACT; - } - ~TStringMapItem() - { - LIMITED_METHOD_CONTRACT; - delete [] m_szString; - } - - HRESULT SetString(LPCTSTR szValue) - { - WRAPPER_NO_CONTRACT; - int iLen = (int)(::_tcslen(szValue) + 1); - if ((m_szString = new TCHAR[iLen]) == 0) - return (OutOfMemory()); - ::_tcscpy_s((TCHAR*)m_szString, iLen, szValue); - return (S_OK); - } - -public: - LPTSTR m_szString; // Key data. - T m_value; // Value for this key. -}; - - -//***************************************************************************** -// IMPORTANT: This data structure is deprecated, please do not add any new uses. -// The hashtable implementation that should be used instead is code:SHash. -// If code:SHash does not work for you, talk to mailto:clrdeag. -//***************************************************************************** -// This template provides a map from string to item, determined by the template -// type passed in. -//***************************************************************************** -template <class T, int iBuckets=17, class TAllocator=CNewData, int iMaxSize=4096> -class TStringMap : - protected CHashTableAndData<TAllocator> -{ - typedef CHashTableAndData<TAllocator> Super; - -public: - typedef TStringMapItem<T> TItemType; - typedef TStringMapItem<long> TOffsetType; - -#ifndef DACCESS_COMPILE - - TStringMap() : - CHashTableAndData<TAllocator>(iBuckets) - { - LIMITED_METHOD_CONTRACT; - } - -//***************************************************************************** -// This is the second part of construction where we do all of the work that -// can fail. We also take the array of structs here because the calling class -// presumably needs to allocate it in its NewInit. -//***************************************************************************** - HRESULT NewInit() // Return status. - { - WRAPPER_NO_CONTRACT; - return (CHashTableAndData<TAllocator>::NewInit( - CNewData::GrowSize(0)/sizeof(TItemType), - sizeof(TItemType), - iMaxSize)); - } - -//***************************************************************************** -// For each item still allocated, invoke its dtor so it frees up anything it -// holds onto. -//***************************************************************************** - void Clear() - { - WRAPPER_NO_CONTRACT; - HASHFIND sSrch; - TItemType *p = (TItemType *) FindFirstEntry(&sSrch); - - while (p != 0) - { - // Call dtor on the item, since m_value is contained the scalar - // dtor will get called. - p->~TStringMapItem<T>(); - p = (TItemType *) FindNextEntry(&sSrch); - } - CHashTableAndData<TAllocator>::Clear(); - } - -#endif // #ifndef DACCESS_COMPILE - -//***************************************************************************** -// Retrieve an item by name. -//***************************************************************************** - T *GetItem( // Null or object. - LPCTSTR szKey) // What to do the lookup on. - { - WRAPPER_NO_CONTRACT; - TItemType sInfo; - TItemType *ptr; // Working pointer. - - // Create a key. - sInfo.m_szString = (LPTSTR) szKey; - - // Look it up in the hash table. - ptr = (TItemType *) Super::Find( _tHashString(szKey), (SIZE_T) &sInfo); - - // Don't let dtor free our string. - sInfo.m_szString = 0; - - // If pointer found, return to caller. To handle T's that have - // an operator &(), find raw address without going through &m_value. - if (ptr) - return ((T *) ((BYTE *) ptr + offsetof(TOffsetType, m_value))); - else - return (0); - } - -//***************************************************************************** -// Initialize an iterator and return the first item. -//***************************************************************************** - TItemType *FindFirstEntry( - HASHFIND *psSrch) - { - WRAPPER_NO_CONTRACT; - TItemType *ptr = (TItemType *) Super::FindFirstEntry(psSrch); - - return (ptr); - } - -//***************************************************************************** -// Return the next item, via an iterator. -//***************************************************************************** - TItemType *FindNextEntry( - HASHFIND *psSrch) - { - WRAPPER_NO_CONTRACT; - TItemType *ptr = (TItemType *) Super::FindNextEntry(psSrch); - - return (ptr); - } - -#ifndef DACCESS_COMPILE - -//***************************************************************************** -// Add an item to the list. -//***************************************************************************** - HRESULT AddItem( // S_OK, or S_FALSE. - LPCTSTR szKey, // The key value for the item. - T &item) // Thing to add. - { - WRAPPER_NO_CONTRACT; - TItemType *ptr; // Working pointer. - - // Allocate an entry in the hash table. - if ((ptr = (TItemType *) this->Add( _tHashString(szKey))) == 0) - return (OutOfMemory()); - - // Fill the record. - if (ptr->SetString(szKey) < 0) - { - DelItem(ptr); - return (OutOfMemory()); - } - - // Call the placement new operator on the item so it can init itself. - // To handle T's that have an operator &(), find raw address without - // going through &m_value. - T *p = new ((void *) ((BYTE *) ptr + offsetof(TOffsetType, m_value))) T; - *p = item; - return (S_OK); - } - -//***************************************************************************** -// Delete an item. -//***************************************************************************** - void DelItem( - LPCTSTR szKey) // What to delete. - { - WRAPPER_NO_CONTRACT; - TItemType sInfo; - TItemType *ptr; // Working pointer. - - // Create a key. - sInfo.m_szString = (LPTSTR) szKey; - - // Look it up in the hash table. - ptr = (TItemType *) this->Find( _tHashString(szKey), (BYTE *) &sInfo); - - // Don't let dtor free our string. - sInfo.m_szString = 0; - - // If found, delete. - if (ptr) - DelItem(ptr); - } - -#endif // #ifndef DACCESS_COMPILE - -//***************************************************************************** -// Compare the keys for two collections. -//***************************************************************************** - BOOL Cmp( // 0 or != 0. - SIZE_T data, // Raw key data on lookup. - const HASHENTRY *pElement) // The element to compare data against. - { - LIMITED_METHOD_DAC_CONTRACT; - TItemType *p = (TItemType *) (size_t) pElement; - return (::_tcscmp(((TItemType *) data)->m_szString, p->m_szString)); - } - -private: - void DelItem( - TItemType *pItem) // Entry to delete. - { - WRAPPER_NO_CONTRACT; - // Need to destruct this item. - pItem->~TStringMapItem<T>(); - CHashTableAndData<TAllocator>::Delete( HashString(pItem->m_szString), (HASHENTRY *)(void *)pItem); - } -}; - -class CImpTlbReservedNames -{ -public: - CImpTlbReservedNames() {} - ~CImpTlbReservedNames() {/*m_StringMap.Clear();*/} - -#ifndef DACCESS_COMPILE - HRESULT Init() {return m_StringMap.NewInit();} - - void AddReservedName(LPCWSTR szName) {BOOL flag = TRUE; m_StringMap.AddItem(szName, flag);} -#endif - BOOL IsReservedName(LPCWSTR szName) {return m_StringMap.GetItem(szName) != 0;} - -private: - TStringMap<BOOL> m_StringMap; -}; - - -//***************************************************************************** -// Helper class to keep track of the mappings from default interfaces to -// class interfaces. -//***************************************************************************** -class ImpTlbClassItfInfo -{ -public: - IID ItfIID; // The IID of the interface. - LPCWSTR szClassItfName; // The class interface name. -}; - -class CImpTlbDefItfToClassItfMap : protected CClosedHash<class ImpTlbClassItfInfo> -{ -public: - typedef CClosedHash<class ImpTlbClassItfInfo> Super; - typedef ImpTlbClassItfInfo T; - - CImpTlbDefItfToClassItfMap(); - ~CImpTlbDefItfToClassItfMap(); - - HRESULT Init(ITypeLib *pTlb, BSTR bstrNameSpace); - - LPCWSTR GetClassItfName(IID &rItfIID); - -private: - HRESULT AddCoClassInterfaces(ITypeInfo *pCoClassITI, TYPEATTR *pCoClassTypeAttr); - - unsigned int Hash(const void *pData) {return Hash((const T*)pData);} - unsigned int Hash(const T *pData); - - unsigned int Compare(const void *p1, BYTE *p2) {return Compare((const T*)p1, (T*)p2);} - unsigned int Compare(const T *p1, T *p2); - - ELEMENTSTATUS Status(BYTE *p) {return Status((T*)p);} - ELEMENTSTATUS Status(T *p); - - void SetStatus(BYTE *p, ELEMENTSTATUS s) {SetStatus((T*)p, s);} - void SetStatus(T *p, ELEMENTSTATUS s); - - void* GetKey(BYTE *p) {return GetKey((T*)p);} - void *GetKey(T *p); - - T* Add(const T *pData); - - CWCHARPool m_Names; // Heap of names. - BSTR m_bstrNameSpace; // Namespace of the typelib. -}; - - -//***************************************************************************** -// Helper class to keep track of imported typelibs. Typically, a typelib -// imports only 2 or 3 other typelibs, so a simple array is used. -//***************************************************************************** -struct CTlbRef -{ - GUID guid; // GUID of referenced typelib. - mdAssemblyRef ar; // AssemblyRef for the module containing reference. - BSTR szNameSpace; // The namespace of the types contained in the assembly. - BSTR szAsmName; // The assembly name. - Assembly* Asm; // The assembly. - CImpTlbDefItfToClassItfMap *pDefItfToClassItfMap; // The default interface to class interface map. - - ~CTlbRef() - { - SysFreeString(szNameSpace); - SysFreeString(szAsmName); - delete pDefItfToClassItfMap; - } -}; - -class CImpTlbLibRef : public CQuickArray<CTlbRef> -{ - typedef CQuickArray<CTlbRef> base; -public: - CImpTlbLibRef() {base::Shrink(0);} - ~CImpTlbLibRef(); - - HRESULT Add(ITypeLib *pITLB, CImportTlb *pImporter, mdAssemblyRef ar, BSTR wzNamespace, BSTR wzAsmName, Assembly* assm, CImpTlbDefItfToClassItfMap **ppMap); - int Find(ITypeLib *pITLB, mdAssemblyRef *par, BSTR *pwzNamespace, BSTR *pwzAsmName, Assembly** assm, CImpTlbDefItfToClassItfMap **ppDefItfToClassItfMap); -}; - - -class CImportTlb -{ -public: - static CImportTlb* CreateImporter(LPCWSTR szLibrary, ITypeLib *pitlb, BOOL bGenerateTCEAdapters, BOOL bUnsafeInterfaces, BOOL bSafeArrayAsSystemArray, BOOL bTransformDispRetVals, BOOL bPreventClassMembers, BOOL bSerializableValueClasses); - - CImportTlb(); - CImportTlb(LPCWSTR szLibrary, ITypeLib *pitlb, BOOL bGenerateTCEAdapters, BOOL bUnsafeInterfaces, BOOL bSafeArrayAsSystemArray, BOOL bTransformDispRetVals, BOOL bPreventClassMembers, BOOL bSerializableValueClasses); - ~CImportTlb(); - - HRESULT Import(); - HRESULT SetNamespace(WCHAR const *pNamespace); - WCHAR *GetNamespace() {return m_wzNamespace;} - HRESULT SetNotification(ITypeLibImporterNotifySink *pINotify); - HRESULT SetMetaData(IUnknown *pIUnk); - void SetAssembly(Assembly *pAssembly) {m_pAssembly = pAssembly;} - void SetModule(Module *pModule) {m_pModule = pModule;} - HRESULT GetNamespaceOfRefTlb(ITypeLib *pITLB, BSTR *pwzNamespace, CImpTlbDefItfToClassItfMap **ppDefItfToClassItfMap); - HRESULT GetEventInfoList(CQuickArray<ImpTlbEventInfo*> &qbEvInfoList) {return m_EventInfoMap.GetEventInfoList(qbEvInfoList);} - - static HRESULT GetDefaultInterface(ITypeInfo *pCoClassTI, ITypeInfo **pDefaultItfTI); - -protected: - - struct MemberInfo - { - union - { - FUNCDESC *m_psFunc; // Pointer to FuncDesc. - VARDESC *m_psVar; // Pointer to VarDesc. - }; - LPWSTR m_pName; // Function/Prop's name, possibly decorated. - int m_iMember; // The index of the member in the ITypeInfo. - union - { - LPWSTR m_pName2; // Prop's second name, if any. - mdToken m_mdFunc; // Function's token & semantics, if not property. - USHORT m_msSemantics; // Semantics only. - }; - void SetFuncInfo(mdMethodDef mdFunc, USHORT msSemantics) {m_mdFunc = RidFromToken(mdFunc) | (msSemantics<<24);} - void GetFuncInfo(mdMethodDef &mdFunc, USHORT &msSemantics) {mdFunc = m_mdFunc&0xffffff | mdtMethodDef; msSemantics = m_mdFunc>>24;} - }; - - - HRESULT ConvertTypeLib(); - HRESULT ConvertTypeInfo(); - - HRESULT ExplicitlyImplementsIEnumerable(ITypeInfo *pITI, TYPEATTR *psAttr, BOOL fLookupPartner = TRUE); - - HRESULT _NewLibraryObject(); - HRESULT ConvCoclass(ITypeInfo *pITI, TYPEATTR *psAttr); - HRESULT ConvEnum(ITypeInfo *pITI, TYPEATTR *psAttr); - HRESULT ConvRecord(ITypeInfo *pITI, TYPEATTR *psAttr, BOOL bUnion); - HRESULT ConvIface(ITypeInfo *pITI, TYPEATTR *psAttr, BOOL bVtblGaps=true); - HRESULT ConvDispatch(ITypeInfo *pITI, TYPEATTR *psAttr, BOOL bVtblGaps=true); - HRESULT ConvModule(ITypeInfo *pITI, TYPEATTR *psAttr); - - HRESULT IsIUnknownDerived(ITypeInfo *pITI, TYPEATTR *psAttr); - HRESULT IsIDispatchDerived(ITypeInfo *pITI, TYPEATTR *psAttr); - HRESULT HasNewEnumMember(ITypeInfo *pItfTI); - HRESULT FuncIsNewEnum(ITypeInfo *pITI, FUNCDESC *pFuncDesc, DWORD index); - HRESULT PropertyIsNewEnum(ITypeInfo *pITI, VARDESC *pVarDesc, DWORD index); - - HRESULT HasObjectFields(ITypeInfo *pITI, TYPEATTR *psAttr); - HRESULT IsObjectType(ITypeInfo *pITI, const TYPEDESC *pType); - HRESULT CompareSigsIgnoringRetType(PCCOR_SIGNATURE pbSig1, ULONG cbSig1, PCCOR_SIGNATURE pbSig2, ULONG cbSig2); - - HRESULT FindMethod(mdTypeDef td, LPCWSTR szName, PCCOR_SIGNATURE pbSig, ULONG cbSig, mdMethodDef *pmb); - HRESULT FindProperty(mdTypeDef td, LPCWSTR szName, PCCOR_SIGNATURE pSig, ULONG cbSig, mdProperty *pPr); - HRESULT FindEvent(mdTypeDef td, LPCWSTR szName, mdProperty *pEv); - - HRESULT ReportEvent(int ev, int hr, ...); - - HRESULT _DefineSysRefs(); - HRESULT _GetNamespaceName(ITypeLib *pITLB, BSTR *pwzNamespace); - HRESULT _GetTokenForTypeInfo(ITypeInfo *pITI, BOOL bConvDefItfToClassItf, mdToken *pToken, __out_ecount (chTypeRef) __out_opt LPWSTR pszTypeRef=0, int chTypeRef=0, int *pchTypeRef=0, BOOL bAsmQualifiedName = FALSE); - - HRESULT _FindFirstUserMethod(ITypeInfo *pITI, TYPEATTR *psAttr, int *pIx); - HRESULT _ResolveTypeDescAliasTypeKind(ITypeInfo *pITIAlias, TYPEDESC *ptdesc, TYPEKIND *ptkind); - HRESULT _ResolveTypeDescAlias(ITypeInfo *pITIAlias, const TYPEDESC *ptdesc, ITypeInfo **ppTIResolved, TYPEATTR **ppsAttrResolved, GUID *pGuid=0); - - HRESULT _SetHiddenCA(mdTypeDef token); - HRESULT _ForceIEnumerableCVExists(ITypeInfo* pITI, BOOL* CVExists); - HRESULT _SetDispIDCA(ITypeInfo* pITI, int iMember, long lDispId, mdToken func, BOOL fAlwaysAdd, long* lDispSet, BOOL bFunc); - HRESULT _GetDispIDCA(ITypeInfo* pITI, int iMember, long* lDispSet, BOOL bFunc); - HRESULT _CheckForPropertyCustomAttributes(ITypeInfo* pITI, int index, INVOKEKIND* ikind); - - HRESULT _ConvIfaceMembers(ITypeInfo *pITI, TYPEATTR *psAttr, BOOL bVtblGaps, BOOL bAddDispIds, BOOL bInheritsIEnum); - HRESULT _ConvSrcIfaceMembers(ITypeInfo *pITI, TYPEATTR* psAttr, BOOL fInheritsIEnum); - HRESULT _ConvDispatchMembers(ITypeInfo *pITI, TYPEATTR *psAttr, BOOL fInheritsIEnum); - HRESULT _GetFunctionPropertyInfo(FUNCDESC *psFunc, USHORT *pSemantics, FUNCDESC **ppSig, TYPEDESC **ppProperty, BOOL *pbRetval, BOOL fUseLastParam, BSTR strName); - HRESULT _ConvFunction(ITypeInfo *pITI, MemberInfo *pMember, int bVtblGapFuncs, BOOL bAddDispIds, BOOL bDelegateInvokeMeth, BOOL* bAllowIEnum); - HRESULT _GenerateEvent(ITypeInfo *pITI, MemberInfo *pMember, BOOL fInheritsIEnum); - HRESULT _GenerateEventDelegate(ITypeInfo *pITI, MemberInfo *pMember, mdTypeDef *ptd, BOOL fInheritsIEnum); - HRESULT _AddSrcItfMembersToClass(mdTypeRef trSrcItf); - - HRESULT _ConvPropertiesForFunctions(ITypeInfo *pITI, TYPEATTR *psAttr); - enum ParamOpts{ParamNormal=0, ParamOptional, ParamVarArg}; - HRESULT _ConvParam(ITypeInfo *pITI, mdMethodDef mbFunc, int iSequence, const ELEMDESC *pdesc, ParamOpts paramOpts, const WCHAR *pszName, BYTE *pbNative, ULONG cbNative); - HRESULT _ConvConstant(ITypeInfo *pITI, VARDESC *psVar, BOOL bEnumMember=false); - HRESULT _ConvField(ITypeInfo *pITI, VARDESC *psVar, mdFieldDef *pmdField, BOOL bUnion); - HRESULT _ConvProperty(ITypeInfo *pITI, MemberInfo *pMember); - HRESULT _ConvNewEnumProperty(ITypeInfo *pITI, VARDESC *psVar, MemberInfo *pMember); - - HRESULT _HandleAliasInfo(ITypeInfo *pITI, TYPEDESC *pTypeDesc, mdToken tk); - - HRESULT _AddTlbRef(ITypeLib *pITLB, mdAssemblyRef *par, BSTR *pwzNamespace, BSTR *pwzAsmName, CImpTlbDefItfToClassItfMap **ppDefItfToClassItfMap); - - HRESULT _AddGuidCa(mdToken tkObj, REFGUID guid); - HRESULT _AddDefaultMemberCa(mdToken tkObj, LPCWSTR szName); - - HRESULT _AddStringCa(int attr, mdToken tk, LPCWSTR wzString); - - HRESULT GetKnownTypeToken(VARTYPE vt, mdTypeRef *ptr); - - HRESULT _GetTokenForEventItf(ITypeInfo *pSrcItfITI, mdTypeRef *ptr); - HRESULT _CreateClassInterface(ITypeInfo *pCoClassITI, ITypeInfo *pDefItfITI, mdTypeRef trDefItf, mdTypeRef rtDefEvItf, mdToken *ptr); - - HRESULT GetManagedNameForCoClass(ITypeInfo *pITI, CQuickArray<WCHAR> &qbClassName); - HRESULT GenerateUniqueTypeName(CQuickArray<WCHAR> &qbTypeName); - HRESULT GenerateUniqueMemberName(CQuickArray<WCHAR> &qbMemberName, PCCOR_SIGNATURE pSig, ULONG SigSize, LPCWSTR szPrefix, mdToken type); - HRESULT _IsAlias(ITypeInfo *pITI, TYPEDESC *pTypeDesc); - - HRESULT GetDefMemberName(ITypeInfo *pITI, BOOL bItfQualified, CQuickArray<WCHAR> &qbDefMemberName); - - enum SigFlags { - // These match the typelib values - SIG_IN = 0x0001, // Input param. - SIG_OUT = 0x0002, // Output param. - SIG_RET = 0x0008, // Retval. Currently unused. - SIG_OPT = 0x0010, // Optional param. Currently unused. - SIG_FLAGS_MASK = 0x001b, // Mask of flags from TypeLib PARAMFLAGs - - SIG_FUNC = 0x0100, // Convert signature for function. - SIG_FIELD = 0x0200, // Convert signature for field. - SIG_ELEM = 0x0300, // Convert signature for sub element (eg, array of X). - SIG_TYPE_MASK = 0x0300, - - SIG_USE_BYREF = 0x1000, // If set convert one ptr as E_T_BYREF. - SIG_VARARG = 0x4000, // If set, this is a paramarray type. Use szArray, not System.Array. - - SIG_FLAGS_NONE = 0 // '0' of this enum type. - }; - - #define IsSigIn(flags) ((flags & SIG_IN) == SIG_IN) - #define IsSigOut(flags) ((flags & SIG_OUT) == SIG_OUT) - #define IsSigRet(flags) ((flags & SIG_RET) == SIG_RET) - #define IsSigOpt(flags) ((flags & SIG_OPT) == SIG_OPT) - #define IsSigOutRet(flags) ((flags & (SIG_OUT|SIG_RET)) == (SIG_OUT|SIG_RET)) - - #define IsSigFunc(flags) ((flags & SIG_TYPE_MASK) == SIG_FUNC) - #define IsSigField(flags) ((flags & SIG_TYPE_MASK) == SIG_FIELD) - #define IsSigElem(flags) ((flags & SIG_TYPE_MASK) == SIG_ELEM) - - #define IsSigUseByref(flags) ((flags & SIG_USE_BYREF) == SIG_USE_BYREF) - #define IsSigVarArg(flags) ((flags & SIG_VARARG) == SIG_VARARG) - - HRESULT _ConvSignature(ITypeInfo *pITI, const TYPEDESC *pType, ULONG Flags, CQuickBytes &qbSigBuf, ULONG cbSig, ULONG *pcbSig, CQuickArray<BYTE> &qbNativeTypeBuf, ULONG cbNativeType, ULONG *pcbNativeType, BOOL bNewEnumMember, int iByRef=0); - - // For handling out-of-order vtables. - CQuickArray<MemberInfo> m_MemberList; - CWCHARPool *m_pMemberNames; - int m_cMemberProps; // Count of props in memberlist. - HRESULT BuildMemberList(ITypeInfo *pITI, int iStart, int iEnd, BOOL bInheritsIEnum); - HRESULT FreeMemberList(ITypeInfo *pITI); - - // List of predefined token types for custom attributes. -#define INTEROP_ATTRIBUTES() \ - INTEROP_ATTRIBUTE(DISPID) \ - INTEROP_ATTRIBUTE(CLASSINTERFACE) \ - INTEROP_ATTRIBUTE(INTERFACETYPE) \ - INTEROP_ATTRIBUTE(TYPELIBTYPE) \ - INTEROP_ATTRIBUTE(TYPELIBVAR) \ - INTEROP_ATTRIBUTE(TYPELIBFUNC) \ - INTEROP_ATTRIBUTE(COMSOURCEINTERFACES) \ - INTEROP_ATTRIBUTE(COMCONVERSIONLOSS) \ - INTEROP_ATTRIBUTE(GUID) \ - INTEROP_ATTRIBUTE(DEFAULTMEMBER) \ - INTEROP_ATTRIBUTE(COMALIASNAME) \ - INTEROP_ATTRIBUTE(PARAMARRAY) \ - INTEROP_ATTRIBUTE(LCIDCONVERSION) \ - INTEROP_ATTRIBUTE(DECIMALVALUE) \ - INTEROP_ATTRIBUTE(DATETIMEVALUE) \ - INTEROP_ATTRIBUTE(IUNKNOWNVALUE) \ - INTEROP_ATTRIBUTE(IDISPATCHVALUE) \ - INTEROP_ATTRIBUTE(COMVISIBLE) \ - INTEROP_ATTRIBUTE(SERIALIZABLE) \ - INTEROP_ATTRIBUTE_SPECIAL(COMEVENTINTERFACE) \ - INTEROP_ATTRIBUTE_SPECIAL(COCLASS) \ - -#define INTEROP_ATTRIBUTE(x) ATTR_##x, -#define INTEROP_ATTRIBUTE_SPECIAL(x) ATTR_##x, - enum {INTEROP_ATTRIBUTES() - // Last value gives array size. - ATTR_COUNT}; -#undef INTEROP_ATTRIBUTE -#undef INTEROP_ATTRIBUTE_SPECIAL - - mdToken m_tkAttr[ATTR_COUNT]; - HRESULT GetAttrType(int attr, mdToken *ptk); - - // look up table for known type - mdTypeRef m_tkKnownTypes[MAX_TLB_VT]; - - LPCWSTR m_szLibrary; // Name of typelib being imported. - BOOL m_bGenerateTCEAdapters; // A flag indicating if the TCE adapters are being generated or not. - BOOL m_bUnsafeInterfaces; // A flag indicating whether runtime security checks should be disabled on an interface - BOOL m_bSafeArrayAsSystemArray; // A flag indicating whether to import SAFEARRAY's as System.Array's. - BOOL m_bTransformDispRetVals; // A flag indicating if we should do [out,retval] transformation on disp only itfs. - BOOL m_bPreventClassMembers; // A flag indicating if we should add members to CoClasses. - BOOL m_bSerializableValueClasses; // A flag indicating if we should mark value classes as serializable. - mdMemberRef m_tkSuppressCheckAttr; // Cached ctor for security check custom attribute - ITypeLib *m_pITLB; // Typelib being imported. - IMetaDataEmit2 *m_pEmit; // Emit API Interface pointer. - IMetaDataImport2 *m_pImport; // Import API Interface pointer. - - BSTR m_wzNamespace; // Namespace of the created TypeDefs. - mdTypeRef m_trObject; // Token of System.Object. - mdTypeRef m_trValueType; // Token of System.ValueType. - mdTypeRef m_trEnum; // Token of System.Enum. - mdAssemblyRef m_arSystem; // AssemblyRef for classlib. - - ITypeInfo *m_pITI; // "Current" ITypeInfo being converted. - ITypeInfo *m_pOrigITI; // Original "Current" ITypeInfo being converted, - // represents TKIND_ALIAS or is equal to m_pITI. - - TYPEATTR *m_psAttr; // "TYPEATTR" of current ITypeInfo. - - BSTR m_szName; // Name of original current ITypeInfo. - BSTR m_szMember; // Name of current Member (method or field). - LPWSTR m_szMngName; // Full name of the managed type. - - ULONG m_cbVtableSlot; // Size of a vtable slot. - ULONG m_Slot; // "Current" vtbl index within an interface. - - void *m_psClass; // "Current" class record. - mdTypeDef m_tdTypeDef; // Current TypeDef. - mdTypeDef m_tdHasDefault; // Most recent TypeDef with a default. - enum {eImplIfaceNone, eImplIfaceDefault, eImplIface} m_ImplIface; - mdToken m_tkInterface; // Interface being added to a coclass. - BSTR m_szInterface; // Interface name for decoration. - - CImpTlbTypeRef m_TRMap; // Typeref map. - CImpTlbLibRef m_LibRefs; // Referenced typelibs. - CImpTlbDefItfToClassItfMap m_DefItfToClassItfMap; // The default interface to class interface map. - - CImpTlbReservedNames m_ReservedNames; // Reserved names. - CImpTlbEventInfoMap m_EventInfoMap; // Map of event info's. - - ITypeLibImporterNotifySink *m_Notify; // Notification object. - Assembly *m_pAssembly; // Containing assembly. - Module *m_pModule; // Module we are emiting into. - -#if defined(TLB_STATS) - LARGE_INTEGER m_freqVal; // Frequency of perf counter. - BOOL m_bStats; // If true, collect timings. -#endif // TLB_STATS -}; - - - -#endif - -//-eof-************************************************************************ diff --git a/src/md/inc/liteweightstgdb.h b/src/md/inc/liteweightstgdb.h index 1234524731..057e29d1ca 100644 --- a/src/md/inc/liteweightstgdb.h +++ b/src/md/inc/liteweightstgdb.h @@ -66,8 +66,6 @@ protected: friend class CorMetaDataScope; friend class COR; friend class RegMeta; - friend class MERGER; - friend class NEWMERGER; friend class MDInternalRO; friend class MDInternalRW; }; diff --git a/src/md/inc/metamodelrw.h b/src/md/inc/metamodelrw.h index 6e00d3cf3e..c2d24db8a5 100644 --- a/src/md/inc/metamodelrw.h +++ b/src/md/inc/metamodelrw.h @@ -1420,10 +1420,6 @@ public: void EnableDeltaMetadataGeneration() { _ASSERTE(m_OptionValue.m_UpdateMode == MDUpdateENC); -#ifndef FEATURE_CORECLR - if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_MD_UseMinimalDeltas)) - m_OptionValue.m_UpdateMode = MDUpdateDelta; -#endif //!FEATURE_CORECLR } void DisableDeltaMetadataGeneration() {m_OptionValue.m_UpdateMode = MDUpdateENC;} diff --git a/src/md/inc/rwutil.h b/src/md/inc/rwutil.h index 5d7f98919c..81966b7fb9 100644 --- a/src/md/inc/rwutil.h +++ b/src/md/inc/rwutil.h @@ -181,30 +181,6 @@ private: //********************************************************************* // -// Merge Token manager. This class is created in GetSaveSize as an agent to -// notify linker regarding token movements. It does not have the ability to -// keep track token movement. -// -//********************************************************************* -class MergeTokenManager : public IMapToken -{ -public: - STDMETHODIMP QueryInterface(REFIID riid, PVOID *pp); - STDMETHODIMP_(ULONG) AddRef(); - STDMETHODIMP_(ULONG) Release(); - STDMETHODIMP Map(mdToken tkImp, mdToken tkEmit); - MergeTokenManager(MDTOKENMAP *pTkMapList, IUnknown *pHandler); - virtual ~MergeTokenManager(); -private: - LONG m_cRef; - MDTOKENMAP *m_pTkMapList; - IMapToken *m_pDefaultHostRemap; -}; - - - -//********************************************************************* -// // This CMapToken class implemented the IMapToken. It is used in RegMeta for // filter process. This class can track all of the tokens are mapped. It also // supplies a Find function. diff --git a/src/md/inc/stgio.h b/src/md/inc/stgio.h index 96a2f1dddb..2ec873d4c8 100644 --- a/src/md/inc/stgio.h +++ b/src/md/inc/stgio.h @@ -46,10 +46,8 @@ enum DBPROPMODE { DBPROP_TMODEF_READ = 0x1, DBPROP_TMODEF_WRITE = 0x2, DBPROP_TMODEF_EXCLUSIVE = 0x4, -#ifndef FEATURE_METADATA_STANDALONE_WINRT_RO // Shared memory uses ole32.dll - we cannot depend on it in the standalone WinRT Read-Only DLL DBPROP_TMODEF_SHAREDMEM = 0x8, -#endif DBPROP_TMODEF_CREATE = 0x10, DBPROP_TMODEF_FAILIFTHERE = 0x20, DBPROP_TMODEF_SLOWSAVE = 0x100, @@ -77,10 +75,8 @@ enum STGIOTYPE STGIO_HMODULE = 2, // The file was loaded via LoadLibrary as module. STGIO_STREAM = 3, // Stream pointer has data. STGIO_MEM = 4, // In memory pointer has data. -#ifndef FEATURE_METADATA_STANDALONE_WINRT_RO // Shared memory uses ole32.dll - we cannot depend on it in the standalone WinRT Read-Only DLL STGIO_SHAREDMEM = 5, // Shared memory handle. -#endif STGIO_HFILEMEM = 6 // Handle open, but memory allocated. }; diff --git a/src/md/inc/winmdinterfaces.h b/src/md/inc/winmdinterfaces.h index 4233e615d3..47f43df083 100644 --- a/src/md/inc/winmdinterfaces.h +++ b/src/md/inc/winmdinterfaces.h @@ -103,15 +103,7 @@ HRESULT VerifyNotWinMDHelper(IUnknown *pUnknown ,int line #endif //_DEBUG ); -#if defined(FEATURE_METADATA_IN_VM) && !defined(FEATURE_CORECLR) -#ifdef _DEBUG -#define VerifyNotWinMD(pUnknown, assertMsg) VerifyNotWinMDHelper(pUnknown, assertMsg, __FILE__, __LINE__) -#else -#define VerifyNotWinMD(pUnknown, assertMsg) VerifyNotWinMDHelper(pUnknown) -#endif -#else #define VerifyNotWinMD(pUnknown, assertMsg) S_OK -#endif // FEATURE_METADATA_IN_VM #endif //__WINMDINTERFACES_H__ diff --git a/src/md/md_wks.cmake b/src/md/md_wks.cmake index ab9df6c667..4d72c55a14 100644 --- a/src/md/md_wks.cmake +++ b/src/md/md_wks.cmake @@ -3,4 +3,4 @@ add_definitions(-DFEATURE_METADATA_INTERNAL_APIS) add_definitions(-DFEATURE_METADATA_IN_VM) if(WIN32) add_definitions(-DFEATURE_METADATA_VERIFY_LAYOUTS) -endif(WIN32)
\ No newline at end of file +endif(WIN32) diff --git a/src/md/runtime/mdfileformat.cpp b/src/md/runtime/mdfileformat.cpp index 2edd2e0292..844dc3cfae 100644 --- a/src/md/runtime/mdfileformat.cpp +++ b/src/md/runtime/mdfileformat.cpp @@ -77,7 +77,6 @@ MDFormat::VerifySignature( } } -#if !defined(FEATURE_METADATA_STANDALONE_WINRT) // Only a specific version of the 0.x format is supported by this code // in order to support the NT 5 beta clients which used this format. if (pSig->GetMajorVer() == FILE_VER_MAJOR_v0) @@ -89,7 +88,6 @@ MDFormat::VerifySignature( } } else -#endif // !defined(FEATURE_METADATA_STANDALONE_WINRT) // There is currently no code to migrate an old format of the 1.x. This // would be added only under special circumstances. if ((pSig->GetMajorVer() != FILE_VER_MAJOR) || (pSig->GetMinorVer() != FILE_VER_MINOR)) diff --git a/src/md/runtime/mdinternaldisp.cpp b/src/md/runtime/mdinternaldisp.cpp index 1f5725ff01..e6e25a2110 100644 --- a/src/md/runtime/mdinternaldisp.cpp +++ b/src/md/runtime/mdinternaldisp.cpp @@ -112,11 +112,6 @@ CheckFileFormat( } else if (strcmp(pStream->GetName(), ENC_MODEL_STREAM_A) == 0) { -#ifdef FEATURE_METADATA_STANDALONE_WINRT - Debug_ReportError("ENC model stream #- is not supported."); - hr = CLDB_E_FILE_CORRUPT; - goto ErrExit; -#else //!FEATURE_METADATA_STANDALONE_WINRT // Validate that only one of compressed/uncompressed is present. if (*pFormat != MDFormat_Invalid) { // Already found a good stream. @@ -126,21 +121,14 @@ CheckFileFormat( } // Found the ENC meta data stream. *pFormat = MDFormat_ReadWrite; -#endif //!FEATURE_METADATA_STANDALONE_WINRT } else if (strcmp(pStream->GetName(), SCHEMA_STREAM_A) == 0) { -#ifdef FEATURE_METADATA_STANDALONE_WINRT - Debug_ReportError("Schema stream #Schema is not supported."); - hr = CLDB_E_FILE_CORRUPT; - goto ErrExit; -#else //!FEATURE_METADATA_STANDALONE_WINRT // Found the uncompressed format *pFormat = MDFormat_ICR; // keep going. We may find the compressed format later. // If so, we want to use the compressed format. -#endif //!FEATURE_METADATA_STANDALONE_WINRT } // Pick off the next stream if there is one. @@ -228,1607 +216,5 @@ ErrExit: } // GetMDInternalInterface -#ifdef FEATURE_FUSION - -#ifndef DACCESS_COMPILE - -//***************************************************************************** -// GetAssemblyMDInternalImport. -// Instantiating an instance of AssemblyMDInternalImport. -// This class can support the IMetaDataAssemblyImport and some functionalities -// of IMetaDataImport on the internal import interface (IMDInternalImport). -//***************************************************************************** -STDAPI GetAssemblyMDInternalImport( // Return code. - LPCWSTR szFileName, // [in] The scope to open. - REFIID riid, // [in] The interface desired. - IUnknown **ppIUnk) // [out] Return interface on success. -{ - return GetAssemblyMDInternalImportEx(szFileName, riid, MDInternalImport_Default, ppIUnk); -} - -STDAPI GetAssemblyMDInternalImportEx( // Return code. - LPCWSTR szFileName, // [in] The scope to open. - REFIID riid, // [in] The interface desired. - MDInternalImportFlags flags, // [in] Flags to control opening the assembly - IUnknown **ppIUnk, // [out] Return interface on success. - HANDLE hFile) -{ - HRESULT hr; - - if (!szFileName || !szFileName[0] || !ppIUnk) - return E_INVALIDARG; - - // Sanity check the name. - if (wcslen(szFileName) >= _MAX_PATH) - return E_INVALIDARG; - - if (memcmp(szFileName, W("file:"), 10) == 0) - szFileName = &szFileName[5]; - - HCORMODULEHolder hModule; - DWORD dwFileLength; - - BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(return COR_E_STACKOVERFLOW); - - IfFailGoto(RuntimeOpenImageInternal(szFileName, &hModule, &dwFileLength, flags, hFile), ErrAsmExpected); - - IfFailGo(GetAssemblyMDInternalImportHelper(hModule, riid, flags, ppIUnk)); - - -ErrAsmExpected: - if(hr == COR_E_BADIMAGEFORMAT) - hr = COR_E_ASSEMBLYEXPECTED; - -ErrExit: -; - END_SO_INTOLERANT_CODE; - - return hr; -} - -HRESULT GetAssemblyMDInternalImportFromImage( - HCORMODULE hImage, - REFIID riid, - IUnknown **ppIUnk) -{ - - HRESULT hr; - - IfFailGo(GetAssemblyMDInternalImportHelper(hImage, riid, MDInternalImport_Default, ppIUnk)); - -ErrExit: - return hr; -} - -STDAPI GetAssemblyMDInternalImportByStream( // Return code. - IStream *pIStream, // [in] The IStream for the file - UINT64 AssemblyId, // [in] Unique Id for the assembly - REFIID riid, // [in] The interface desired. - IUnknown **ppIUnk) // [out] Return interface on success. -{ - return GetAssemblyMDInternalImportByStreamEx(pIStream, AssemblyId, riid, MDInternalImport_Default, ppIUnk); -} - -STDAPI GetAssemblyMDInternalImportByStreamEx( // Return code. - IStream *pIStream, // [in] The IStream for the file - UINT64 AssemblyId, // [in] Unique Id for the assembly - REFIID riid, // [in] The interface desired. - MDInternalImportFlags flags, // [in[ Flags to control opening the assembly - IUnknown **ppIUnk) // [out] Return interface on success. -{ - if (!pIStream || !ppIUnk) - return E_INVALIDARG; - - HRESULT hr; - DWORD dwFileLength; - HCORMODULEHolder hModule; - - BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(return COR_E_STACKOVERFLOW); - - IfFailGoto(RuntimeOpenImageByStream(pIStream, AssemblyId, 0, &hModule, &dwFileLength, flags), ErrAsmExpected); - - IfFailGo(GetAssemblyMDInternalImportHelper(hModule, riid, flags, ppIUnk)); - - -ErrAsmExpected: - if(hr == COR_E_BADIMAGEFORMAT) - hr = COR_E_ASSEMBLYEXPECTED; - -ErrExit: - ; - END_SO_INTOLERANT_CODE; - - return hr; -} - - -HRESULT GetAssemblyMDInternalImportHelper(HCORMODULE hModule, - REFIID riid, - MDInternalImportFlags flags, - IUnknown **ppIUnk) -{ - AssemblyMDInternalImport *pAssemblyMDInternalImport = NULL; - HRESULT hr; - LPVOID base; - PEDecoder pe; - IfFailGoto(RuntimeGetImageBase(hModule,&base,TRUE,NULL), ErrAsmExpected); - - if (base!=NULL) - IfFailGoto(pe.Init(base), ErrAsmExpected); - else - { - COUNT_T lgth; - IfFailGoto(RuntimeGetImageBase(hModule,&base,FALSE,&lgth), ErrAsmExpected); - pe.Init(base, lgth); - } - - // Both of these need to pass. - if (!pe.HasCorHeader() || !pe.CheckCorHeader()) - IfFailGo(COR_E_ASSEMBLYEXPECTED); - // Only one of these needs to. - if (!pe.CheckILFormat() && !pe.CheckNativeFormat()) - IfFailGo(COR_E_BADIMAGEFORMAT); - - COUNT_T cbMetaData; - LPCVOID pMetaData; - pMetaData = pe.GetMetadata(&cbMetaData); - - // Get the IL metadata. - IMDInternalImport *pMDInternalImport; - IfFailGo(RuntimeGetMDInternalImport(hModule, flags, &pMDInternalImport)); - if (pMDInternalImport == NULL) - IfFailGo(E_OUTOFMEMORY); - - _ASSERTE(pMDInternalImport); - pAssemblyMDInternalImport = new (nothrow) AssemblyMDInternalImport (pMDInternalImport); - if (!pAssemblyMDInternalImport) { - pMDInternalImport->Release(); - IfFailGo(E_OUTOFMEMORY); - } - - { // identify PE kind and machine type, plus the version string location - DWORD dwKind=0; - DWORD dwMachine=0; - RuntimeGetImageKind(hModule,&dwKind,&dwMachine); - pAssemblyMDInternalImport->SetPEKind(dwKind); - pAssemblyMDInternalImport->SetMachine(dwMachine); - - { - LPCSTR pString = NULL; - IfFailGo(GetImageRuntimeVersionString((PVOID)pMetaData, &pString)); - - pAssemblyMDInternalImport->SetVersionString(pString); - } - - } - - pAssemblyMDInternalImport->SetHandle(hModule); - -#ifdef FEATURE_PREJIT - // Check for zap header for INativeImageInstallInfo - // Dont do this if we are returning the IL metadata as CORCOMPILE_DEPENDENCY - // references the native image metadata, not the IL metadata. - - if (pe.HasNativeHeader() && !(flags & MDInternalImport_ILMetaData)) - { - CORCOMPILE_VERSION_INFO *pNativeVersionInfo = pe.GetNativeVersionInfo(); - - COUNT_T cDeps; - CORCOMPILE_DEPENDENCY *pDeps = pe.GetNativeDependencies(&cDeps); - - pAssemblyMDInternalImport->SetZapVersionInfo(pNativeVersionInfo, pDeps, cDeps); - } -#endif // FEATURE_PREJIT - - IfFailGo(pAssemblyMDInternalImport->QueryInterface(riid, (void**)ppIUnk)); - - return hr; - -ErrAsmExpected: - if(hr == COR_E_BADIMAGEFORMAT) - hr = COR_E_ASSEMBLYEXPECTED; - -ErrExit: - - if (pAssemblyMDInternalImport) - delete pAssemblyMDInternalImport; - - return hr; -} - -AssemblyMDInternalImport::AssemblyMDInternalImport (IMDInternalImport *pMDInternalImport) -: m_cRef(0), - m_pHandle(0), - m_pBase(NULL), -#ifdef FEATURE_PREJIT - m_pZapVersionInfo(NULL), -#endif // FEATURE_PREJIT - m_pMDInternalImport(pMDInternalImport), - m_dwPEKind(0), - m_dwMachine(0), - m_szVersionString("") -{ - _ASSERTE(m_pMDInternalImport); -} // AssemblyMDInternalImport - -AssemblyMDInternalImport::~AssemblyMDInternalImport () -{ - m_pMDInternalImport->Release(); - - if (m_pBase) - { - UnmapViewOfFile(m_pBase); - m_pBase = NULL; - CloseHandle(m_pHandle); - } - else if(m_pHandle) - { - HRESULT hr; - hr = RuntimeReleaseHandle(m_pHandle); - _ASSERTE(SUCCEEDED(hr)); - } - - m_pHandle = NULL; -} - -ULONG AssemblyMDInternalImport::AddRef() -{ - return InterlockedIncrement(&m_cRef); -} // ULONG AssemblyMDInternalImport::AddRef() - -ULONG AssemblyMDInternalImport::Release() -{ - ULONG cRef = InterlockedDecrement(&m_cRef); - if (!cRef) - { - VALIDATE_BACKOUT_STACK_CONSUMPTION; - delete this; - } - return (cRef); -} // ULONG AssemblyMDInternalImport::Release() - -HRESULT AssemblyMDInternalImport::QueryInterface(REFIID riid, void **ppUnk) -{ - *ppUnk = 0; - - if (riid == IID_IUnknown) - *ppUnk = (IUnknown *) (IMetaDataAssemblyImport *) this; - else if (riid == IID_IMetaDataAssemblyImport) - *ppUnk = (IMetaDataAssemblyImport *) this; - else if (riid == IID_IMetaDataImport) - *ppUnk = (IMetaDataImport *) this; - else if (riid == IID_IMetaDataImport2) - *ppUnk = (IMetaDataImport2 *) this; - else if (riid == IID_ISNAssemblySignature) - *ppUnk = (ISNAssemblySignature *) this; -#ifdef FEATURE_PREJIT - else if (riid == IID_IGetIMDInternalImport) - *ppUnk = (IGetIMDInternalImport *) this; - else if (riid == IID_INativeImageInstallInfo && m_pZapVersionInfo) - *ppUnk = (INativeImageInstallInfo *) this; -#endif // FEATURE_PREJIT - else - return (E_NOINTERFACE); - AddRef(); - return (S_OK); -} - - -STDMETHODIMP AssemblyMDInternalImport::GetAssemblyProps ( // S_OK or error. - mdAssembly mda, // [IN] The Assembly for which to get the properties. - const void **ppbPublicKey, // [OUT] Pointer to the public key. - ULONG *pcbPublicKey, // [OUT] Count of bytes in the public key. - ULONG *pulHashAlgId, // [OUT] Hash Algorithm. - __out_ecount (cchName) LPWSTR szName, // [OUT] Buffer to fill with name. - ULONG cchName, // [IN] Size of buffer in wide chars. - ULONG *pchName, // [OUT] Actual # of wide chars in name. - ASSEMBLYMETADATA *pMetaData, // [OUT] Assembly MetaData. - DWORD *pdwAssemblyFlags) // [OUT] Flags. -{ - HRESULT hr; - LPCSTR _szName; - AssemblyMetaDataInternal _AssemblyMetaData; - - _AssemblyMetaData.ulProcessor = 0; - _AssemblyMetaData.ulOS = 0; - - IfFailRet(m_pMDInternalImport->GetAssemblyProps( - mda, // [IN] The Assembly for which to get the properties. - ppbPublicKey, // [OUT] Pointer to the public key. - pcbPublicKey, // [OUT] Count of bytes in the public key. - pulHashAlgId, // [OUT] Hash Algorithm. - &_szName, // [OUT] Buffer to fill with name. - &_AssemblyMetaData, // [OUT] Assembly MetaData. - pdwAssemblyFlags)); // [OUT] Flags. - - if (pchName != NULL) - { - *pchName = WszMultiByteToWideChar(CP_UTF8, 0, _szName, -1, szName, cchName); - if (*pchName == 0) - { - return HRESULT_FROM_GetLastError(); - } - } - - if (pMetaData) - { - pMetaData->usMajorVersion = _AssemblyMetaData.usMajorVersion; - pMetaData->usMinorVersion = _AssemblyMetaData.usMinorVersion; - pMetaData->usBuildNumber = _AssemblyMetaData.usBuildNumber; - pMetaData->usRevisionNumber = _AssemblyMetaData.usRevisionNumber; - pMetaData->ulProcessor = 0; - pMetaData->ulOS = 0; - - pMetaData->cbLocale = WszMultiByteToWideChar(CP_UTF8, 0, _AssemblyMetaData.szLocale, -1, pMetaData->szLocale, pMetaData->cbLocale); - if (pMetaData->cbLocale == 0) - { - return HRESULT_FROM_GetLastError(); - } - } - - return S_OK; -} - -STDMETHODIMP AssemblyMDInternalImport::GetAssemblyRefProps ( // S_OK or error. - mdAssemblyRef mdar, // [IN] The AssemblyRef for which to get the properties. - const void **ppbPublicKeyOrToken, // [OUT] Pointer to the public key or token. - ULONG *pcbPublicKeyOrToken, // [OUT] Count of bytes in the public key or token. - __out_ecount (cchName) LPWSTR szName, // [OUT] Buffer to fill with name. - ULONG cchName, // [IN] Size of buffer in wide chars. - ULONG *pchName, // [OUT] Actual # of wide chars in name. - ASSEMBLYMETADATA *pMetaData, // [OUT] Assembly MetaData. - const void **ppbHashValue, // [OUT] Hash blob. - ULONG *pcbHashValue, // [OUT] Count of bytes in the hash blob. - DWORD *pdwAssemblyRefFlags) // [OUT] Flags. -{ - HRESULT hr; - LPCSTR _szName; - AssemblyMetaDataInternal _AssemblyMetaData; - - _AssemblyMetaData.ulProcessor = 0; - _AssemblyMetaData.ulOS = 0; - - IfFailRet(m_pMDInternalImport->GetAssemblyRefProps( - mdar, // [IN] The Assembly for which to get the properties. - ppbPublicKeyOrToken, // [OUT] Pointer to the public key or token. - pcbPublicKeyOrToken, // [OUT] Count of bytes in the public key or token. - &_szName, // [OUT] Buffer to fill with name. - &_AssemblyMetaData, // [OUT] Assembly MetaData. - ppbHashValue, // [OUT] Hash blob. - pcbHashValue, // [OUT] Count of bytes in the hash blob. - pdwAssemblyRefFlags)); // [OUT] Flags. - - if (pchName != NULL) - { - *pchName = WszMultiByteToWideChar(CP_UTF8, 0, _szName, -1, szName, cchName); - if (*pchName == 0) - { - return HRESULT_FROM_GetLastError(); - } - } - - pMetaData->usMajorVersion = _AssemblyMetaData.usMajorVersion; - pMetaData->usMinorVersion = _AssemblyMetaData.usMinorVersion; - pMetaData->usBuildNumber = _AssemblyMetaData.usBuildNumber; - pMetaData->usRevisionNumber = _AssemblyMetaData.usRevisionNumber; - pMetaData->ulProcessor = 0; - pMetaData->ulOS = 0; - - pMetaData->cbLocale = WszMultiByteToWideChar(CP_UTF8, 0, _AssemblyMetaData.szLocale, -1, pMetaData->szLocale, pMetaData->cbLocale); - if (pMetaData->cbLocale == 0) - { - return HRESULT_FROM_GetLastError(); - } - - return S_OK; -} - -STDMETHODIMP AssemblyMDInternalImport::GetFileProps ( // S_OK or error. - mdFile mdf, // [IN] The File for which to get the properties. - __out_ecount (cchName) LPWSTR szName, // [OUT] Buffer to fill with name. - ULONG cchName, // [IN] Size of buffer in wide chars. - ULONG *pchName, // [OUT] Actual # of wide chars in name. - const void **ppbHashValue, // [OUT] Pointer to the Hash Value Blob. - ULONG *pcbHashValue, // [OUT] Count of bytes in the Hash Value Blob. - DWORD *pdwFileFlags) // [OUT] Flags. -{ - HRESULT hr; - LPCSTR _szName; - IfFailRet(m_pMDInternalImport->GetFileProps( - mdf, - &_szName, - ppbHashValue, - pcbHashValue, - pdwFileFlags)); - - if (pchName != NULL) - { - *pchName = WszMultiByteToWideChar(CP_UTF8, 0, _szName, -1, szName, cchName); - if (*pchName == 0) - { - return HRESULT_FROM_GetLastError(); - } - } - - return S_OK; -} - -STDMETHODIMP AssemblyMDInternalImport::GetExportedTypeProps ( // S_OK or error. - mdExportedType mdct, // [IN] The ExportedType for which to get the properties. - __out_ecount (cchName) LPWSTR szName, // [OUT] Buffer to fill with name. - ULONG cchName, // [IN] Size of buffer in wide chars. - ULONG *pchName, // [OUT] Actual # of wide chars in name. - mdToken *ptkImplementation, // [OUT] mdFile or mdAssemblyRef or mdExportedType. - mdTypeDef *ptkTypeDef, // [OUT] TypeDef token within the file. - DWORD *pdwExportedTypeFlags) // [OUT] Flags. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::GetManifestResourceProps ( // S_OK or error. - mdManifestResource mdmr, // [IN] The ManifestResource for which to get the properties. - __out_ecount (cchName) LPWSTR szName, // [OUT] Buffer to fill with name. - ULONG cchName, // [IN] Size of buffer in wide chars. - ULONG *pchName, // [OUT] Actual # of wide chars in name. - mdToken *ptkImplementation, // [OUT] mdFile or mdAssemblyRef that provides the ManifestResource. - DWORD *pdwOffset, // [OUT] Offset to the beginning of the resource within the file. - DWORD *pdwResourceFlags) // [OUT] Flags. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::EnumAssemblyRefs ( // S_OK or error - HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. - mdAssemblyRef rAssemblyRefs[], // [OUT] Put AssemblyRefs here. - ULONG cMax, // [IN] Max AssemblyRefs to put. - ULONG *pcTokens) // [OUT] Put # put here. -{ - HENUMInternal **ppmdEnum = reinterpret_cast<HENUMInternal **> (phEnum); - HRESULT hr = NOERROR; - HENUMInternal *pEnum; - - if (*ppmdEnum == NULL) - { - // create the enumerator. - IfFailGo(HENUMInternal::CreateSimpleEnum( - mdtAssemblyRef, - 0, - 1, - &pEnum)); - - IfFailGo(m_pMDInternalImport->EnumInit(mdtAssemblyRef, 0, pEnum)); - - // set the output parameter. - *ppmdEnum = pEnum; - } - else - { - pEnum = *ppmdEnum; - } - - // we can only fill the minimum of what the caller asked for or what we have left. - IfFailGo(HENUMInternal::EnumWithCount(pEnum, cMax, rAssemblyRefs, pcTokens)); -ErrExit: - HENUMInternal::DestroyEnumIfEmpty(ppmdEnum); - - return hr; -} - -STDMETHODIMP AssemblyMDInternalImport::EnumFiles ( // S_OK or error - HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. - mdFile rFiles[], // [OUT] Put Files here. - ULONG cMax, // [IN] Max Files to put. - ULONG *pcTokens) // [OUT] Put # put here. -{ - HENUMInternal **ppmdEnum = reinterpret_cast<HENUMInternal **> (phEnum); - HRESULT hr = NOERROR; - HENUMInternal *pEnum; - - if (*ppmdEnum == NULL) - { - // create the enumerator. - IfFailGo(HENUMInternal::CreateSimpleEnum( - mdtFile, - 0, - 1, - &pEnum)); - - IfFailGo(m_pMDInternalImport->EnumInit(mdtFile, 0, pEnum)); - - // set the output parameter. - *ppmdEnum = pEnum; - } - else - { - pEnum = *ppmdEnum; - } - - // we can only fill the minimum of what the caller asked for or what we have left. - IfFailGo(HENUMInternal::EnumWithCount(pEnum, cMax, rFiles, pcTokens)); - -ErrExit: - HENUMInternal::DestroyEnumIfEmpty(ppmdEnum); - return hr; -} - -STDMETHODIMP AssemblyMDInternalImport::EnumExportedTypes ( // S_OK or error - HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. - mdExportedType rExportedTypes[], // [OUT] Put ExportedTypes here. - ULONG cMax, // [IN] Max ExportedTypes to put. - ULONG *pcTokens) // [OUT] Put # put here. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::EnumManifestResources ( // S_OK or error - HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. - mdManifestResource rManifestResources[], // [OUT] Put ManifestResources here. - ULONG cMax, // [IN] Max Resources to put. - ULONG *pcTokens) // [OUT] Put # put here. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::GetAssemblyFromScope ( // S_OK or error - mdAssembly *ptkAssembly) // [OUT] Put token here. -{ - return m_pMDInternalImport->GetAssemblyFromScope (ptkAssembly); -} - -STDMETHODIMP AssemblyMDInternalImport::FindExportedTypeByName (// S_OK or error - LPCWSTR szName, // [IN] Name of the ExportedType. - mdToken mdtExportedType, // [IN] ExportedType for the enclosing class. - mdExportedType *ptkExportedType) // [OUT] Put the ExportedType token here. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::FindManifestResourceByName ( // S_OK or error - LPCWSTR szName, // [IN] Name of the ManifestResource. - mdManifestResource *ptkManifestResource) // [OUT] Put the ManifestResource token here. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -void AssemblyMDInternalImport::CloseEnum ( - HCORENUM hEnum) // Enum to be closed. -{ - HENUMInternal *pmdEnum = reinterpret_cast<HENUMInternal *> (hEnum); - - if (pmdEnum == NULL) - return; - - HENUMInternal::DestroyEnum(pmdEnum); -} - -STDMETHODIMP AssemblyMDInternalImport::FindAssembliesByName ( // S_OK or error - LPCWSTR szAppBase, // [IN] optional - can be NULL - LPCWSTR szPrivateBin, // [IN] optional - can be NULL - LPCWSTR szAssemblyName, // [IN] required - this is the assembly you are requesting - IUnknown *ppIUnk[], // [OUT] put IMetaDataAssemblyImport pointers here - ULONG cMax, // [IN] The max number to put - ULONG *pcAssemblies) // [OUT] The number of assemblies returned. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::CountEnum (HCORENUM hEnum, ULONG *pulCount) -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::ResetEnum (HCORENUM hEnum, ULONG ulPos) -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::EnumTypeDefs (HCORENUM *phEnum, mdTypeDef rTypeDefs[], - ULONG cMax, ULONG *pcTypeDefs) -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::EnumInterfaceImpls (HCORENUM *phEnum, mdTypeDef td, - mdInterfaceImpl rImpls[], ULONG cMax, - ULONG* pcImpls) -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::EnumTypeRefs (HCORENUM *phEnum, mdTypeRef rTypeRefs[], - ULONG cMax, ULONG* pcTypeRefs) -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::FindTypeDefByName ( // S_OK or error. - LPCWSTR szTypeDef, // [IN] Name of the Type. - mdToken tkEnclosingClass, // [IN] TypeDef/TypeRef for Enclosing class. - mdTypeDef *ptd) // [OUT] Put the TypeDef token here. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::GetScopeProps ( // S_OK or error. - __out_ecount (cchName) LPWSTR szName, // [OUT] Put the name here. - ULONG cchName, // [IN] Size of name buffer in wide chars. - ULONG *pchName, // [OUT] Put size of name (wide chars) here. - GUID *pmvid) // [OUT, OPTIONAL] Put MVID here. -{ - HRESULT hr; - LPCSTR _szName; - - if (!m_pMDInternalImport->IsValidToken(m_pMDInternalImport->GetModuleFromScope())) - return COR_E_BADIMAGEFORMAT; - - IfFailRet(m_pMDInternalImport->GetScopeProps(&_szName, pmvid)); - - if (pchName != NULL) - { - *pchName = WszMultiByteToWideChar(CP_UTF8, 0, _szName, -1, szName, cchName); - if (*pchName == 0) - { - return HRESULT_FROM_GetLastError(); - } - } - - return S_OK; - -} - -STDMETHODIMP AssemblyMDInternalImport::GetModuleFromScope ( // S_OK. - mdModule *pmd) // [OUT] Put mdModule token here. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::GetTypeDefProps ( // S_OK or error. - mdTypeDef td, // [IN] TypeDef token for inquiry. - __out_ecount (cchTypeDef) LPWSTR szTypeDef, // [OUT] Put name here. - ULONG cchTypeDef, // [IN] size of name buffer in wide chars. - ULONG *pchTypeDef, // [OUT] put size of name (wide chars) here. - DWORD *pdwTypeDefFlags, // [OUT] Put flags here. - mdToken *ptkExtends) // [OUT] Put base class TypeDef/TypeRef here. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::GetInterfaceImplProps ( // S_OK or error. - mdInterfaceImpl iiImpl, // [IN] InterfaceImpl token. - mdTypeDef *pClass, // [OUT] Put implementing class token here. - mdToken *ptkIface) // [OUT] Put implemented interface token here. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::GetTypeRefProps ( // S_OK or error. - mdTypeRef tr, // [IN] TypeRef token. - mdToken *ptkResolutionScope, // [OUT] Resolution scope, ModuleRef or AssemblyRef. - __out_ecount (cchName) LPWSTR szName, // [OUT] Name of the TypeRef. - ULONG cchName, // [IN] Size of buffer. - ULONG *pchName) // [OUT] Size of Name. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::ResolveTypeRef (mdTypeRef tr, REFIID riid, IUnknown **ppIScope, mdTypeDef *ptd) -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::EnumMembers ( // S_OK, S_FALSE, or error. - HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. - mdTypeDef cl, // [IN] TypeDef to scope the enumeration. - mdToken rMembers[], // [OUT] Put MemberDefs here. - ULONG cMax, // [IN] Max MemberDefs to put. - ULONG *pcTokens) // [OUT] Put # put here. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::EnumMembersWithName ( // S_OK, S_FALSE, or error. - HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. - mdTypeDef cl, // [IN] TypeDef to scope the enumeration. - LPCWSTR szName, // [IN] Limit results to those with this name. - mdToken rMembers[], // [OUT] Put MemberDefs here. - ULONG cMax, // [IN] Max MemberDefs to put. - ULONG *pcTokens) // [OUT] Put # put here. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::EnumMethods ( // S_OK, S_FALSE, or error. - HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. - mdTypeDef cl, // [IN] TypeDef to scope the enumeration. - mdMethodDef rMethods[], // [OUT] Put MethodDefs here. - ULONG cMax, // [IN] Max MethodDefs to put. - ULONG *pcTokens) // [OUT] Put # put here. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::EnumMethodsWithName ( // S_OK, S_FALSE, or error. - HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. - mdTypeDef cl, // [IN] TypeDef to scope the enumeration. - LPCWSTR szName, // [IN] Limit results to those with this name. - mdMethodDef rMethods[], // [OU] Put MethodDefs here. - ULONG cMax, // [IN] Max MethodDefs to put. - ULONG *pcTokens) // [OUT] Put # put here. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::EnumFields ( // S_OK, S_FALSE, or error. - HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. - mdTypeDef cl, // [IN] TypeDef to scope the enumeration. - mdFieldDef rFields[], // [OUT] Put FieldDefs here. - ULONG cMax, // [IN] Max FieldDefs to put. - ULONG *pcTokens) // [OUT] Put # put here. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::EnumFieldsWithName ( // S_OK, S_FALSE, or error. - HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. - mdTypeDef cl, // [IN] TypeDef to scope the enumeration. - LPCWSTR szName, // [IN] Limit results to those with this name. - mdFieldDef rFields[], // [OUT] Put MemberDefs here. - ULONG cMax, // [IN] Max MemberDefs to put. - ULONG *pcTokens) // [OUT] Put # put here. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - - -STDMETHODIMP AssemblyMDInternalImport::EnumParams ( // S_OK, S_FALSE, or error. - HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. - mdMethodDef mb, // [IN] MethodDef to scope the enumeration. - mdParamDef rParams[], // [OUT] Put ParamDefs here. - ULONG cMax, // [IN] Max ParamDefs to put. - ULONG *pcTokens) // [OUT] Put # put here. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::EnumMemberRefs ( // S_OK, S_FALSE, or error. - HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. - mdToken tkParent, // [IN] Parent token to scope the enumeration. - mdMemberRef rMemberRefs[], // [OUT] Put MemberRefs here. - ULONG cMax, // [IN] Max MemberRefs to put. - ULONG *pcTokens) // [OUT] Put # put here. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::EnumMethodImpls ( // S_OK, S_FALSE, or error - HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. - mdTypeDef td, // [IN] TypeDef to scope the enumeration. - mdToken rMethodBody[], // [OUT] Put Method Body tokens here. - mdToken rMethodDecl[], // [OUT] Put Method Declaration tokens here. - ULONG cMax, // [IN] Max tokens to put. - ULONG *pcTokens) // [OUT] Put # put here. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::EnumPermissionSets ( // S_OK, S_FALSE, or error. - HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. - mdToken tk, // [IN] if !NIL, token to scope the enumeration. - DWORD dwActions, // [IN] if !0, return only these actions. - mdPermission rPermission[], // [OUT] Put Permissions here. - ULONG cMax, // [IN] Max Permissions to put. - ULONG *pcTokens) // [OUT] Put # put here. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::FindMember ( - mdTypeDef td, // [IN] given typedef - LPCWSTR szName, // [IN] member name - PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of COM+ signature - ULONG cbSigBlob, // [IN] count of bytes in the signature blob - mdToken *pmb) // [OUT] matching memberdef -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::FindMethod ( - mdTypeDef td, // [IN] given typedef - LPCWSTR szName, // [IN] member name - PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of COM+ signature - ULONG cbSigBlob, // [IN] count of bytes in the signature blob - mdMethodDef *pmb) // [OUT] matching memberdef -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::FindField ( - mdTypeDef td, // [IN] given typedef - LPCWSTR szName, // [IN] member name - PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of COM+ signature - ULONG cbSigBlob, // [IN] count of bytes in the signature blob - mdFieldDef *pmb) // [OUT] matching memberdef -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::FindMemberRef ( - mdTypeRef td, // [IN] given typeRef - LPCWSTR szName, // [IN] member name - PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of COM+ signature - ULONG cbSigBlob, // [IN] count of bytes in the signature blob - mdMemberRef *pmr) // [OUT] matching memberref -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::GetMethodProps ( - mdMethodDef mb, // The method for which to get props. - mdTypeDef *pClass, // Put method's class here. - __out_ecount (cchMethod) LPWSTR szMethod, // Put method's name here. - ULONG cchMethod, // Size of szMethod buffer in wide chars. - ULONG *pchMethod, // Put actual size here - DWORD *pdwAttr, // Put flags here. - PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to the blob value of meta data - ULONG *pcbSigBlob, // [OUT] actual size of signature blob - ULONG *pulCodeRVA, // [OUT] codeRVA - DWORD *pdwImplFlags) // [OUT] Impl. Flags -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::GetMemberRefProps ( // S_OK or error. - mdMemberRef mr, // [IN] given memberref - mdToken *ptk, // [OUT] Put classref or classdef here. - __out_ecount (cchMember) LPWSTR szMember, // [OUT] buffer to fill for member's name - ULONG cchMember, // [IN] the count of char of szMember - ULONG *pchMember, // [OUT] actual count of char in member name - PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to meta data blob value - ULONG *pbSig) // [OUT] actual size of signature blob -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::EnumProperties ( // S_OK, S_FALSE, or error. - HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. - mdTypeDef td, // [IN] TypeDef to scope the enumeration. - mdProperty rProperties[], // [OUT] Put Properties here. - ULONG cMax, // [IN] Max properties to put. - ULONG *pcProperties) // [OUT] Put # put here. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::EnumEvents ( // S_OK, S_FALSE, or error. - HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. - mdTypeDef td, // [IN] TypeDef to scope the enumeration. - mdEvent rEvents[], // [OUT] Put events here. - ULONG cMax, // [IN] Max events to put. - ULONG *pcEvents) // [OUT] Put # put here. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::GetEventProps ( // S_OK, S_FALSE, or error. - mdEvent ev, // [IN] event token - mdTypeDef *pClass, // [OUT] typedef containing the event declarion. - LPCWSTR szEvent, // [OUT] Event name - ULONG cchEvent, // [IN] the count of wchar of szEvent - ULONG *pchEvent, // [OUT] actual count of wchar for event's name - DWORD *pdwEventFlags, // [OUT] Event flags. - mdToken *ptkEventType, // [OUT] EventType class - mdMethodDef *pmdAddOn, // [OUT] AddOn method of the event - mdMethodDef *pmdRemoveOn, // [OUT] RemoveOn method of the event - mdMethodDef *pmdFire, // [OUT] Fire method of the event - mdMethodDef rmdOtherMethod[], // [OUT] other method of the event - ULONG cMax, // [IN] size of rmdOtherMethod - ULONG *pcOtherMethod) // [OUT] total number of other method of this event -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::EnumMethodSemantics ( // S_OK, S_FALSE, or error. - HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. - mdMethodDef mb, // [IN] MethodDef to scope the enumeration. - mdToken rEventProp[], // [OUT] Put Event/Property here. - ULONG cMax, // [IN] Max properties to put. - ULONG *pcEventProp) // [OUT] Put # put here. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::GetMethodSemantics ( // S_OK, S_FALSE, or error. - mdMethodDef mb, // [IN] method token - mdToken tkEventProp, // [IN] event/property token. - DWORD *pdwSemanticsFlags) // [OUT] the role flags for the method/propevent pair -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::GetClassLayout ( - mdTypeDef td, // [IN] give typedef - DWORD *pdwPackSize, // [OUT] 1, 2, 4, 8, or 16 - COR_FIELD_OFFSET rFieldOffset[], // [OUT] field offset array - ULONG cMax, // [IN] size of the array - ULONG *pcFieldOffset, // [OUT] needed array size - ULONG *pulClassSize) // [OUT] the size of the class -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::GetFieldMarshal ( - mdToken tk, // [IN] given a field's memberdef - PCCOR_SIGNATURE *ppvNativeType, // [OUT] native type of this field - ULONG *pcbNativeType) // [OUT] the count of bytes of *ppvNativeType -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::GetRVA ( // S_OK or error. - mdToken tk, // Member for which to set offset - ULONG *pulCodeRVA, // The offset - DWORD *pdwImplFlags) // the implementation flags -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::GetPermissionSetProps ( - mdPermission pm, // [IN] the permission token. - DWORD *pdwAction, // [OUT] CorDeclSecurity. - void const **ppvPermission, // [OUT] permission blob. - ULONG *pcbPermission) // [OUT] count of bytes of pvPermission. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::GetSigFromToken ( // S_OK or error. - mdSignature mdSig, // [IN] Signature token. - PCCOR_SIGNATURE *ppvSig, // [OUT] return pointer to token. - ULONG *pcbSig) // [OUT] return size of signature. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::GetModuleRefProps ( // S_OK or error. - mdModuleRef mur, // [IN] moduleref token. - __out_ecount (cchName) LPWSTR szName, // [OUT] buffer to fill with the moduleref name. - ULONG cchName, // [IN] size of szName in wide characters. - ULONG *pchName) // [OUT] actual count of characters in the name. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::EnumModuleRefs ( // S_OK or error. - HCORENUM *phEnum, // [IN|OUT] pointer to the enum. - mdModuleRef rModuleRefs[], // [OUT] put modulerefs here. - ULONG cmax, // [IN] max memberrefs to put. - ULONG *pcModuleRefs) // [OUT] put # put here. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::GetTypeSpecFromToken ( // S_OK or error. - mdTypeSpec typespec, // [IN] TypeSpec token. - PCCOR_SIGNATURE *ppvSig, // [OUT] return pointer to TypeSpec signature - ULONG *pcbSig) // [OUT] return size of signature. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::GetNameFromToken ( // Not Recommended! May be removed! - mdToken tk, // [IN] Token to get name from. Must have a name. - MDUTF8CSTR *pszUtf8NamePtr) // [OUT] Return pointer to UTF8 name in heap. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::EnumUnresolvedMethods ( // S_OK, S_FALSE, or error. - HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. - mdToken rMethods[], // [OUT] Put MemberDefs here. - ULONG cMax, // [IN] Max MemberDefs to put. - ULONG *pcTokens) // [OUT] Put # put here. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::GetUserString ( // S_OK or error. - mdString stk, // [IN] String token. - __out_ecount (cchString) LPWSTR szString, // [OUT] Copy of string. - ULONG cchString, // [IN] Max chars of room in szString. - ULONG *pchString) // [OUT] How many chars in actual string. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::GetPinvokeMap ( // S_OK or error. - mdToken tk, // [IN] FieldDef or MethodDef. - DWORD *pdwMappingFlags, // [OUT] Flags used for mapping. - __out_ecount (cchImportName) LPWSTR szImportName, // [OUT] Import name. - ULONG cchImportName, // [IN] Size of the name buffer. - ULONG *pchImportName, // [OUT] Actual number of characters stored. - mdModuleRef *pmrImportDLL) // [OUT] ModuleRef token for the target DLL. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::EnumSignatures ( // S_OK or error. - HCORENUM *phEnum, // [IN|OUT] pointer to the enum. - mdSignature rSignatures[], // [OUT] put signatures here. - ULONG cmax, // [IN] max signatures to put. - ULONG *pcSignatures) // [OUT] put # put here. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::EnumTypeSpecs ( // S_OK or error. - HCORENUM *phEnum, // [IN|OUT] pointer to the enum. - mdTypeSpec rTypeSpecs[], // [OUT] put TypeSpecs here. - ULONG cmax, // [IN] max TypeSpecs to put. - ULONG *pcTypeSpecs) // [OUT] put # put here. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::EnumUserStrings ( // S_OK or error. - HCORENUM *phEnum, // [IN/OUT] pointer to the enum. - mdString rStrings[], // [OUT] put Strings here. - ULONG cmax, // [IN] max Strings to put. - ULONG *pcStrings) // [OUT] put # put here. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::GetParamForMethodIndex ( // S_OK or error. - mdMethodDef md, // [IN] Method token. - ULONG ulParamSeq, // [IN] Parameter sequence. - mdParamDef *ppd) // [IN] Put Param token here. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::EnumCustomAttributes ( // S_OK or error. - HCORENUM *phEnum, // [IN, OUT] COR enumerator. - mdToken tk, // [IN] Token to scope the enumeration, 0 for all. - mdToken tkType, // [IN] Type of interest, 0 for all. - mdCustomAttribute rCustomAttributes[], // [OUT] Put custom attribute tokens here. - ULONG cMax, // [IN] Size of rCustomAttributes. - ULONG *pcCustomAttributes) // [OUT, OPTIONAL] Put count of token values here. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::GetCustomAttributeProps ( // S_OK or error. - mdCustomAttribute cv, // [IN] CustomAttribute token. - mdToken *ptkObj, // [OUT, OPTIONAL] Put object token here. - mdToken *ptkType, // [OUT, OPTIONAL] Put AttrType token here. - void const **ppBlob, // [OUT, OPTIONAL] Put pointer to data here. - ULONG *pcbSize) // [OUT, OPTIONAL] Put size of date here. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::FindTypeRef ( - mdToken tkResolutionScope, // [IN] ModuleRef, AssemblyRef or TypeRef. - LPCWSTR szName, // [IN] TypeRef Name. - mdTypeRef *ptr) // [OUT] matching TypeRef. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::GetMemberProps ( - mdToken mb, // The member for which to get props. - mdTypeDef *pClass, // Put member's class here. - __out_ecount (cchMember) LPWSTR szMember, // Put member's name here. - ULONG cchMember, // Size of szMember buffer in wide chars. - ULONG *pchMember, // Put actual size here - DWORD *pdwAttr, // Put flags here. - PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to the blob value of meta data - ULONG *pcbSigBlob, // [OUT] actual size of signature blob - ULONG *pulCodeRVA, // [OUT] codeRVA - DWORD *pdwImplFlags, // [OUT] Impl. Flags - DWORD *pdwCPlusTypeFlag, // [OUT] flag for value type. selected ELEMENT_TYPE_* - UVCP_CONSTANT *ppValue, // [OUT] constant value - ULONG *pcchValue) // [OUT] size of constant string in chars, 0 for non-strings. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::GetFieldProps ( - mdFieldDef mb, // The field for which to get props. - mdTypeDef *pClass, // Put field's class here. - __out_ecount (cchField) LPWSTR szField, // Put field's name here. - ULONG cchField, // Size of szField buffer in wide chars. - ULONG *pchField, // Put actual size here - DWORD *pdwAttr, // Put flags here. - PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to the blob value of meta data - ULONG *pcbSigBlob, // [OUT] actual size of signature blob - DWORD *pdwCPlusTypeFlag, // [OUT] flag for value type. selected ELEMENT_TYPE_* - UVCP_CONSTANT *ppValue, // [OUT] constant value - ULONG *pcchValue) // [OUT] size of constant string in chars, 0 for non-strings. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::GetPropertyProps ( // S_OK, S_FALSE, or error. - mdProperty prop, // [IN] property token - mdTypeDef *pClass, // [OUT] typedef containing the property declarion. - LPCWSTR szProperty, // [OUT] Property name - ULONG cchProperty, // [IN] the count of wchar of szProperty - ULONG *pchProperty, // [OUT] actual count of wchar for property name - DWORD *pdwPropFlags, // [OUT] property flags. - PCCOR_SIGNATURE *ppvSig, // [OUT] property type. pointing to meta data internal blob - ULONG *pbSig, // [OUT] count of bytes in *ppvSig - DWORD *pdwCPlusTypeFlag, // [OUT] flag for value type. selected ELEMENT_TYPE_* - UVCP_CONSTANT *ppDefaultValue, // [OUT] constant value - ULONG *pcchDefaultValue, // [OUT] size of constant string in chars, 0 for non-strings. - mdMethodDef *pmdSetter, // [OUT] setter method of the property - mdMethodDef *pmdGetter, // [OUT] getter method of the property - mdMethodDef rmdOtherMethod[], // [OUT] other method of the property - ULONG cMax, // [IN] size of rmdOtherMethod - ULONG *pcOtherMethod) // [OUT] total number of other method of this property -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::GetParamProps ( // S_OK or error. - mdParamDef tk, // [IN]The Parameter. - mdMethodDef *pmd, // [OUT] Parent Method token. - ULONG *pulSequence, // [OUT] Parameter sequence. - __out_ecount (cchName) LPWSTR szName, // [OUT] Put name here. - ULONG cchName, // [OUT] Size of name buffer. - ULONG *pchName, // [OUT] Put actual size of name here. - DWORD *pdwAttr, // [OUT] Put flags here. - DWORD *pdwCPlusTypeFlag, // [OUT] Flag for value type. selected ELEMENT_TYPE_*. - UVCP_CONSTANT *ppValue, // [OUT] Constant value. - ULONG *pcchValue) // [OUT] size of constant string in chars, 0 for non-strings. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::GetCustomAttributeByName ( // S_OK or error. - mdToken tkObj, // [IN] Object with Custom Attribute. - LPCWSTR szName, // [IN] Name of desired Custom Attribute. - const void **ppData, // [OUT] Put pointer to data here. - ULONG *pcbData) // [OUT] Put size of data here. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -BOOL AssemblyMDInternalImport::IsValidToken ( // True or False. - mdToken tk) // [IN] Given token. -{ - _ASSERTE(!"NYI"); - return FALSE; -} - -STDMETHODIMP AssemblyMDInternalImport::GetNestedClassProps ( // S_OK or error. - mdTypeDef tdNestedClass, // [IN] NestedClass token. - mdTypeDef *ptdEnclosingClass) // [OUT] EnclosingClass token. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::GetNativeCallConvFromSig ( // S_OK or error. - void const *pvSig, // [IN] Pointer to signature. - ULONG cbSig, // [IN] Count of signature bytes. - ULONG *pCallConv) // [OUT] Put calling conv here (see CorPinvokemap). -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::IsGlobal ( // S_OK or error. - mdToken pd, // [IN] Type, Field, or Method token. - int *pbGlobal) // [OUT] Put 1 if global, 0 otherwise. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::GetMethodSpecProps( - mdMethodSpec mi, // [IN] The method instantiation - mdToken *tkParent, // [OUT] MethodDef or MemberRef - PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to the blob value of meta data - ULONG *pcbSigBlob) // [OUT] actual size of signature blob -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -// *** ISNAssemblySignature methods *** - -STDMETHODIMP AssemblyMDInternalImport::GetSNAssemblySignature( - BYTE *pbSig, // [IN, OUT] Buffer to write signature - DWORD *pcbSig) // [IN, OUT] Size of buffer, bytes written -{ - return RuntimeGetAssemblyStrongNameHashForModule(m_pHandle, this, pbSig, pcbSig); -} - - -#include "strongname.h" - -#ifdef FEATURE_PREJIT -// *** IGetIMDInternalImport *** -STDMETHODIMP AssemblyMDInternalImport::GetIMDInternalImport( - IMDInternalImport ** pIMDInternalImport) -{ - m_pMDInternalImport->AddRef(); - *pIMDInternalImport = m_pMDInternalImport; - return S_OK; -} - - - -// =========================================================================== - -class CNativeImageDependency : public INativeImageDependency -{ -public: - CNativeImageDependency(CORCOMPILE_DEPENDENCY * pDependency) - : m_cRef(1), m_pDependency(pDependency) - { - } - - ~CNativeImageDependency() - { - } - - // - // IUnknown - // - - STDMETHODIMP_(ULONG) AddRef() - { - return InterlockedIncrement(&m_cRef); - } - - STDMETHODIMP_(ULONG) Release() - { - ULONG cRef = InterlockedDecrement(&m_cRef); - if (!cRef) - delete this; - return (cRef); - } - - STDMETHODIMP QueryInterface(REFIID riid, void **ppUnk) - { - *ppUnk = 0; - - if (riid == IID_IUnknown) - *ppUnk = (IUnknown *) (IMetaDataAssemblyImport *) this; - else if (riid == IID_INativeImageDependency) - *ppUnk = (INativeImageDependency *) this; - else - return (E_NOINTERFACE); - AddRef(); - return (S_OK); - } - - // - // INativeImageDependency - // - - STDMETHODIMP GetILAssemblyRef(mdAssemblyRef * pAssemblyRef) - { - BEGIN_ENTRYPOINT_NOTHROW; - - *pAssemblyRef = m_pDependency->dwAssemblyRef; - END_ENTRYPOINT_NOTHROW; - - return S_OK; - } - - STDMETHODIMP GetILAssemblyDef( - mdAssemblyRef * ppAssemblyDef, - CORCOMPILE_ASSEMBLY_SIGNATURE * pSign) - { - BEGIN_ENTRYPOINT_NOTHROW; - - *ppAssemblyDef = m_pDependency->dwAssemblyDef; - *pSign = m_pDependency->signAssemblyDef; - END_ENTRYPOINT_NOTHROW; - - return S_OK; - } - - STDMETHODIMP GetNativeAssemblyDef(CORCOMPILE_NGEN_SIGNATURE * pNativeSign) - { - BEGIN_ENTRYPOINT_NOTHROW; - - *pNativeSign = m_pDependency->signNativeImage; - END_ENTRYPOINT_NOTHROW; - - return S_OK; - } - - STDMETHODIMP GetPEKind(PEKIND *pPEKind) - { - BEGIN_ENTRYPOINT_NOTHROW; - - *pPEKind = PEKIND((m_pDependency->dependencyInfo & CORCOMPILE_DEPENDENCY_PEKIND_MASK) >> CORCOMPILE_DEPENDENCY_PEKIND_SHIFT); - END_ENTRYPOINT_NOTHROW; - - return S_OK; - } - -protected: - - LONG m_cRef; - CORCOMPILE_DEPENDENCY * m_pDependency; -}; - -// =========================================================================== -// *** INativeImageInstallInfo *** -// =========================================================================== - -STDMETHODIMP AssemblyMDInternalImport::GetSignature(CORCOMPILE_NGEN_SIGNATURE * pNgenSign) -{ - BEGIN_ENTRYPOINT_NOTHROW; - - *pNgenSign = m_pZapVersionInfo->signature; - END_ENTRYPOINT_NOTHROW; - - return S_OK; -} - -STDMETHODIMP AssemblyMDInternalImport::GetVersionInfo(CORCOMPILE_VERSION_INFO * pVersionInfo) -{ - BEGIN_ENTRYPOINT_NOTHROW; - - *pVersionInfo = *m_pZapVersionInfo; - END_ENTRYPOINT_NOTHROW; - return S_OK; -} - - - -STDMETHODIMP AssemblyMDInternalImport::GetILSignature(CORCOMPILE_ASSEMBLY_SIGNATURE * pILSign) -{ - BEGIN_ENTRYPOINT_NOTHROW; - - *pILSign = m_pZapVersionInfo->sourceAssembly; - END_ENTRYPOINT_NOTHROW; - return S_OK; -} - -STDMETHODIMP AssemblyMDInternalImport::GetConfigMask(DWORD * pConfigMask) -{ - BEGIN_ENTRYPOINT_NOTHROW; - - *pConfigMask = m_pZapVersionInfo->wConfigFlags; - END_ENTRYPOINT_NOTHROW; - - return S_OK; -} - -STDMETHODIMP AssemblyMDInternalImport::EnumDependencies ( - HCORENUM * phEnum, // [IN/OUT] - Pointer to the enum - INativeImageDependency *rDeps[], // [OUT] - ULONG cMax, // Max dependancies to enumerate in this iteration - DWORD * pdwCount // [OUT] - Number of dependancies actually enumerated - ) -{ - HRESULT hr = S_OK; - - BEGIN_ENTRYPOINT_NOTHROW; - - CORCOMPILE_DEPENDENCY * pDependenciesEnd = m_pZapDependencies + m_cZapDependencies; - - CORCOMPILE_DEPENDENCY * pNextDependency; - - // Is the enum just being initialized, or are we walking an existing one? - if ((*phEnum) == NULL) - pNextDependency = m_pZapDependencies; - else - pNextDependency = (CORCOMPILE_DEPENDENCY *)(*phEnum); - - DWORD count; - for (count = 0; - pNextDependency < pDependenciesEnd && count < cMax; - count++, pNextDependency++) - { - CNativeImageDependency * pDep = new (nothrow) CNativeImageDependency(pNextDependency); - IfNullGo( pDep ); - - rDeps[count] = pDep; - } - - *phEnum = (HCORENUM)(pNextDependency < pDependenciesEnd) ? pNextDependency : NULL; - *pdwCount = count; - -ErrExit: - END_ENTRYPOINT_NOTHROW; - - return hr; -} - - -STDMETHODIMP AssemblyMDInternalImport::GetDependency ( - const CORCOMPILE_NGEN_SIGNATURE *pcngenSign, // [IN] ngenSig of dependency you want - CORCOMPILE_DEPENDENCY *pDep // [OUT] matching dependency - ) -{ - HRESULT hr = S_OK; - - BEGIN_ENTRYPOINT_NOTHROW; - - _ASSERTE(pcngenSign != NULL); - _ASSERTE(*pcngenSign != INVALID_NGEN_SIGNATURE); - _ASSERTE(pDep != NULL); - - CORCOMPILE_DEPENDENCY * pDependenciesEnd = m_pZapDependencies + m_cZapDependencies; - CORCOMPILE_DEPENDENCY * pNextDependency = m_pZapDependencies; - while (pNextDependency != pDependenciesEnd) - { - if (pNextDependency->signNativeImage == *pcngenSign) - { - *pDep = *pNextDependency; - hr = S_OK; - goto ErrExit; - } - pNextDependency++; - } - hr = S_FALSE; - -ErrExit: - END_ENTRYPOINT_NOTHROW; - - return hr; -} - - -#endif // FEATURE_PREJIT - - -//***************************************************************************** -// IMetaDataImport2 methods -//***************************************************************************** -STDMETHODIMP AssemblyMDInternalImport::GetGenericParamProps( // S_OK or error. - mdGenericParam gp, // [IN] GenericParam - ULONG *pulParamSeq, // [OUT] Index of the type parameter - DWORD *pdwParamFlags, // [OUT] Flags, for future use (e.g. variance) - mdToken *ptOwner, // [OUT] Owner (TypeDef or MethodDef) - DWORD *reserved, // [OUT] For future use (e.g. non-type parameters) - __out_ecount (cchName) LPWSTR wzname, // [OUT] Put name here - ULONG cchName, // [IN] Size of buffer - ULONG *pchName) // [OUT] Put size of name (wide chars) here. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::GetGenericParamConstraintProps( // S_OK or error. - mdGenericParamConstraint gpc, // [IN] GenericParamConstraint - mdGenericParam *ptGenericParam, // [OUT] GenericParam that is constrained - mdToken *ptkConstraintType) // [OUT] TypeDef/Ref/Spec constraint -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::EnumGenericParams( // S_OK or error. - HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. - mdToken tk, // [IN] TypeDef or MethodDef whose generic parameters are requested - mdGenericParam rGenericParams[], // [OUT] Put GenericParams here. - ULONG cMax, // [IN] Max GenericParams to put. - ULONG *pcGenericParams) // [OUT] Put # put here. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::EnumGenericParamConstraints( // S_OK or error. - HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. - mdGenericParam tk, // [IN] GenericParam whose constraints are requested - mdGenericParamConstraint rGenericParamConstraints[], // [OUT] Put GenericParamConstraints here. - ULONG cMax, // [IN] Max GenericParamConstraints to put. - ULONG *pcGenericParamConstraints) // [OUT] Put # put here. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::EnumMethodSpecs( // S_OK or error. - HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. - mdToken tk, // [IN] MethodDef or MemberRef whose MethodSpecs are requested - mdMethodSpec rMethodSpecs[], // [OUT] Put MethodSpecs here. - ULONG cMax, // [IN] Max tokens to put. - ULONG *pcMethodSpecs) // [OUT] Put actual count here. -{ - _ASSERTE(!"NYI"); - return E_NOTIMPL; -} - -STDMETHODIMP AssemblyMDInternalImport::GetPEKind( // S_OK or error. - DWORD* pdwPEKind, // [OUT] The kind of PE (0 - not a PE) - DWORD* pdwMachine) // [OUT] Machine as defined in NT header -{ - HRESULT hr = S_OK; - if(pdwPEKind) *pdwPEKind = m_dwPEKind; - if(pdwMachine) *pdwMachine = m_dwMachine; - return hr; -} - -STDMETHODIMP AssemblyMDInternalImport::GetVersionString( // S_OK or error. - __out_ecount (ccBufSize) LPWSTR pwzBuf, // Put version string here. - DWORD ccBufSize, // [in] size of the buffer, in wide chars - DWORD *pccBufSize) // [out] Size of the version string, wide chars, including terminating nul. -{ - HRESULT hr=S_OK; - DWORD L = WszMultiByteToWideChar(CP_UTF8,0,m_szVersionString,-1,pwzBuf,ccBufSize); - if(ccBufSize < L) - hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW); - - if(pccBufSize) *pccBufSize = L; - return hr; -} - -#endif //!DACCESS_COMPILE - -#endif // FEATURE_FUSION #endif //FEATURE_METADATA_INTERNAL_APIS diff --git a/src/md/runtime/metamodel.cpp b/src/md/runtime/metamodel.cpp index 293e5b6b5e..83addc6d6c 100644 --- a/src/md/runtime/metamodel.cpp +++ b/src/md/runtime/metamodel.cpp @@ -519,7 +519,6 @@ CMiniMdBase::SchemaPopulate( { // No it's not. Is this an older version that we support? -#ifndef FEATURE_METADATA_STANDALONE_WINRT // Is this v1.0? if ((m_Schema.m_major == METAMODEL_MAJOR_VER_V1_0) && (m_Schema.m_minor == METAMODEL_MINOR_VER_V1_0)) @@ -535,7 +534,6 @@ CMiniMdBase::SchemaPopulate( m_TableDefs[TBL_GenericParam].m_pColDefs = BYTEARRAY_TO_COLDES(s_GenericParamCol); } else -#endif //!FEATURE_METADATA_STANDALONE_WINRT { // We don't support this version of the metadata Debug_ReportError("Unsupported version of MetaData."); return PostError(CLDB_E_FILE_OLDVER, m_Schema.m_major, m_Schema.m_minor); diff --git a/src/md/runtime/wks/CMakeLists.txt b/src/md/runtime/wks/CMakeLists.txt index 9a1f72ed25..3e2a8cc6be 100644 --- a/src/md/runtime/wks/CMakeLists.txt +++ b/src/md/runtime/wks/CMakeLists.txt @@ -1,5 +1,7 @@ include(../../md_wks.cmake) +add_definitions(-DFEATURE_METADATA_EMIT_ALL) + add_precompiled_header(stdafx.h ../stdafx.cpp MDRUNTIME_SOURCES) add_library_clr(mdruntime_wks ${MDRUNTIME_SOURCES}) diff --git a/src/md/winmd/adapter.cpp b/src/md/winmd/adapter.cpp index 2c9dd1b9fd..d4e95b7f8b 100644 --- a/src/md/winmd/adapter.cpp +++ b/src/md/winmd/adapter.cpp @@ -1185,14 +1185,12 @@ void WinMDAdapter::GetExtraAssemblyRefProps(FrameworkAssemblyIndex index, if (ppPublicKeytoken) { -#ifdef FEATURE_CORECLR if (index == FrameworkAssembly_Mscorlib) { *ppPublicKeytoken = g_rbTheSilverlightPlatformKeyToken; *pTokenLength = sizeof(g_rbTheSilverlightPlatformKeyToken); } else -#endif { if (index == FrameworkAssembly_SystemNumericsVectors || index == FrameworkAssembly_SystemRuntime || index == FrameworkAssembly_SystemObjectModel) { diff --git a/src/md/winmd/inc/adapter.h b/src/md/winmd/inc/adapter.h index e42992f81f..cc422017b6 100644 --- a/src/md/winmd/inc/adapter.h +++ b/src/md/winmd/inc/adapter.h @@ -236,14 +236,12 @@ public: if (pusRevisionNumber != nullptr) *pusRevisionNumber = VER_ASSEMBLYBUILD_QFE; -#ifdef FEATURE_CORECLR // Under CoreCLR, we replace the ECMA key in the mscorlib assembly ref with the CoreCLR platform public key token if (ppbPublicKeyOrToken != nullptr) { *ppbPublicKeyOrToken = g_rbTheSilverlightPlatformKeyToken; *pcbPublicKeyOrToken = _countof(g_rbTheSilverlightPlatformKeyToken); } -#endif } else if (RidFromToken(mdar) > m_rawAssemblyRefCount) { @@ -632,11 +630,7 @@ public: case FrameworkAssembly_SystemRuntimeWindowsRuntimeUIXaml: return "System.Runtime.WindowsRuntime.UI.Xaml"; case FrameworkAssembly_SystemNumericsVectors: -#ifdef FEATURE_CORECLR return "System.Numerics.Vectors"; -#else - return "System.Numerics"; -#endif default: _ASSERTE(!"Invalid AssemblyRef token!"); return NULL; diff --git a/src/md/winmd/wks/CMakeLists.txt b/src/md/winmd/wks/CMakeLists.txt index 139b68b28c..defcc1d51d 100644 --- a/src/md/winmd/wks/CMakeLists.txt +++ b/src/md/winmd/wks/CMakeLists.txt @@ -1,4 +1,6 @@ include(../../md_wks.cmake) +add_definitions(-DFEATURE_METADATA_EMIT_ALL) + add_precompiled_header(stdafx.h ../stdafx.cpp MDWINMD_SOURCES) -add_library_clr(mdwinmd_wks ${MDWINMD_SOURCES})
\ No newline at end of file +add_library_clr(mdwinmd_wks ${MDWINMD_SOURCES}) |