summaryrefslogtreecommitdiff
path: root/src/md/winmd
diff options
context:
space:
mode:
Diffstat (limited to 'src/md/winmd')
-rw-r--r--src/md/winmd/.gitmirror1
-rw-r--r--src/md/winmd/CMakeLists.txt18
-rw-r--r--src/md/winmd/WinMD.settings.targets49
-rw-r--r--src/md/winmd/adapter.cpp2745
-rw-r--r--src/md/winmd/crossgen/.gitmirror1
-rw-r--r--src/md/winmd/crossgen/CMakeLists.txt5
-rw-r--r--src/md/winmd/crossgen/MDWinMD_crossgen.nativeproj14
-rw-r--r--src/md/winmd/dac/.gitmirror1
-rw-r--r--src/md/winmd/dac/CMakeLists.txt6
-rw-r--r--src/md/winmd/dac/dirs.proj19
-rw-r--r--src/md/winmd/dbi/.gitmirror1
-rw-r--r--src/md/winmd/dbi/CMakeLists.txt4
-rw-r--r--src/md/winmd/dbi/MDWinMD-dbi.props9
-rw-r--r--src/md/winmd/dbi/MDWinMD_dbi.nativeproj17
-rw-r--r--src/md/winmd/dbi/dirs.proj19
-rw-r--r--src/md/winmd/dirs.proj21
-rw-r--r--src/md/winmd/inc/.gitmirror1
-rw-r--r--src/md/winmd/inc/adapter.h951
-rw-r--r--src/md/winmd/inc/memotable.h205
-rw-r--r--src/md/winmd/stdafx.cpp12
-rw-r--r--src/md/winmd/stdafx.h27
-rw-r--r--src/md/winmd/winmdimport.cpp2132
-rw-r--r--src/md/winmd/winmdinternalimportro.cpp1804
-rw-r--r--src/md/winmd/wks/.gitmirror1
-rw-r--r--src/md/winmd/wks/CMakeLists.txt4
-rw-r--r--src/md/winmd/wks/MDWinMD_wks.nativeproj19
26 files changed, 8086 insertions, 0 deletions
diff --git a/src/md/winmd/.gitmirror b/src/md/winmd/.gitmirror
new file mode 100644
index 0000000000..f507630f94
--- /dev/null
+++ b/src/md/winmd/.gitmirror
@@ -0,0 +1 @@
+Only contents of this folder, excluding subfolders, will be mirrored by the Git-TFS Mirror. \ No newline at end of file
diff --git a/src/md/winmd/CMakeLists.txt b/src/md/winmd/CMakeLists.txt
new file mode 100644
index 0000000000..9fb7d839ac
--- /dev/null
+++ b/src/md/winmd/CMakeLists.txt
@@ -0,0 +1,18 @@
+set(MDWINMD_SOURCES
+ adapter.cpp
+ winmdimport.cpp
+ winmdinternalimportro.cpp
+)
+
+convert_to_absolute_path(MDWINMD_SOURCES ${MDWINMD_SOURCES})
+
+if(CLR_CMAKE_PLATFORM_UNIX)
+ add_compile_options(-fPIC)
+endif(CLR_CMAKE_PLATFORM_UNIX)
+
+add_subdirectory(dac)
+add_subdirectory(wks)
+if(WIN32)
+ add_subdirectory(dbi)
+ add_subdirectory(crossgen)
+endif(WIN32)
diff --git a/src/md/winmd/WinMD.settings.targets b/src/md/winmd/WinMD.settings.targets
new file mode 100644
index 0000000000..58fa8ee682
--- /dev/null
+++ b/src/md/winmd/WinMD.settings.targets
@@ -0,0 +1,49 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+
+ <!--
+ We build MetaData in several flavors:
+ - Full version (wks) - part of clr.dll/coreclr.dll.
+ - dac version - does not need Emit APIs.
+ - Standalone versions for:
+ * mscordbi.dll (hands the interfaces over to debugger client (e.g. VS) - does not need Emit APIs.
+ * CorDbg - does not need Emit APIs.
+ * WinRT
+ - Read-Only version (ships in Windows) - does not need Emit and Internal APIs.
+ - Read-Writer version (ships as private component of MidlRt.exe SDK tool) - does not need Internal APIs.
+ -->
+
+ <!--Import the settings-->
+ <Import Project="$(_NTDRIVE)$(_NTROOT)\ndp\clr\src\MD\MD.props" />
+
+ <PropertyGroup>
+ <MDWinMDSrcDirectory>$(ClrSrcDirectory)\MD\WinMD\</MDWinMDSrcDirectory>
+ <UserIncludes>
+ $(UserIncludes);
+ $(ClrSrcDirectory)\MD\inc;
+ $(ClrSrcDirectory)\vm;
+ $(ClrSrcDirectory)\strongname\inc
+ </UserIncludes>
+ <ClAdditionalOptions>$(ClAdditionalOptions) -DUNICODE -D_UNICODE</ClAdditionalOptions>
+ <!--OK to delete NO_NTDLL for devdiv builds.-->
+ <OutputPath>$(ClrLibDest)</OutputPath>
+ <TargetType>LIBRARY</TargetType>
+ <PCHHeader>stdafx.h</PCHHeader>
+ <EnableCxxPCHHeaders>true</EnableCxxPCHHeaders>
+ <!--PCH: Both precompiled header and cpp are on the same ..\ path this is likely to be wrong.-->
+ <PCHCompile>$(MDWinMDSrcDirectory)\stdafx.cpp</PCHCompile>
+ <PCHObject>stdafx_winmd.obj</PCHObject>
+ <LinkUseCMT>false</LinkUseCMT>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <ProjectReference Include="$(ClrSrcDirectory)inc\corguids.nativeproj">
+ <Comment>clrinternal.h</Comment>
+ </ProjectReference>
+ </ItemGroup>
+
+ <ItemGroup>
+ <CppCompile Include="$(MDWinMDSrcDirectory)\Adapter.cpp" />
+ <CppCompile Include="$(MDWinMDSrcDirectory)\WinMDImport.cpp" />
+ <CppCompile Include="$(MDWinMDSrcDirectory)\WinMDInternalImportRO.cpp" />
+ </ItemGroup>
+</Project>
diff --git a/src/md/winmd/adapter.cpp b/src/md/winmd/adapter.cpp
new file mode 100644
index 0000000000..5b4d95cc7c
--- /dev/null
+++ b/src/md/winmd/adapter.cpp
@@ -0,0 +1,2745 @@
+// 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.
+#include "stdafx.h"
+#include "sigparser.h"
+#include "sigbuilder.h"
+#include "inc/adapter.h"
+
+//#CLRRuntimeHostInternal_GetImageVersionString
+// External implementation of call to code:ICLRRuntimeHostInternal::GetImageVersionString.
+// Implemented in clr.dll and mscordbi.dll.
+HRESULT
+CLRRuntimeHostInternal_GetImageVersionString(
+ __out_ecount(*pcchBuffer)
+ LPWSTR wszBuffer,
+ DWORD * pcchBuffer);
+
+//----------------------------------------------------------------------------------------------------
+// The name prefixes used by WinMD to hide/unhide WinRT and CLR versions of RuntimeClasses.
+//----------------------------------------------------------------------------------------------------
+
+static const char s_szWinRTPrefix[] = "<WinRT>";
+//static const size_t s_ncWinRTPrefix = sizeof(s_szWinRTPrefix) - 1;
+
+static const char s_szCLRPrefix[] = "<CLR>";
+static const size_t s_ncCLRPrefix = sizeof(s_szCLRPrefix) - 1;
+
+// the public key token of the ecma key used by some framework assemblies (mscorlib, system, etc).
+// note that some framework assemblies use a different key: b03f5f7f11d50a3a
+static const BYTE s_pbFrameworkPublicKeyToken[] = {0xB7,0x7A,0x5C,0x56,0x19,0x34,0xE0,0x89};
+
+
+//-----------------------------------------------------------------------------------------------------
+// Returns:
+// S_OK: if WinMD adapter should be used.
+// S_FALSE: if not
+//-----------------------------------------------------------------------------------------------------
+HRESULT CheckIfWinMDAdapterNeeded(IMDCommon *pRawMDCommon)
+{
+ HRESULT hr;
+ _ASSERTE(pRawMDCommon != NULL);
+
+ LPCSTR szMetadataVersionString = NULL;
+
+#ifndef DACCESS_COMPILE
+#ifdef _DEBUG
+ //---------------------------------------------------------------------------------------------------------
+ // set COMPLUS_INTERNAL_MD_WinMD_AssertOnIllegalUsage=1
+ //
+ // to turn the WinMD adapter off universally.
+ //---------------------------------------------------------------------------------------------------------
+ if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_MD_WinMD_Disable))
+ {
+ hr = S_FALSE;
+ goto ErrExit;
+ }
+#endif //_DEBUG
+#endif
+
+ //---------------------------------------------------------------------------------------------------------
+ // This is the real check: activate WinMD based on metadata version string.
+ //---------------------------------------------------------------------------------------------------------
+ static const LPCSTR g_szWindowsRuntimeVersion = "WindowsRuntime ";
+ IfFailGo(pRawMDCommon->GetVersionString(&szMetadataVersionString));
+ if (0 == strncmp(szMetadataVersionString, g_szWindowsRuntimeVersion, strlen(g_szWindowsRuntimeVersion)))
+ {
+ hr = S_OK;
+ goto ErrExit;
+ }
+ else
+ {
+ hr = S_FALSE;
+ goto ErrExit;
+ }
+
+ ErrExit:
+ return hr;
+}
+
+
+//------------------------------------------------------------------------------
+
+//
+// Factory for WinMDAdapters. Caller must use "delete" to destroy adapter when done.
+//
+/*static*/ HRESULT WinMDAdapter::Create(IMDCommon *pRawMDCommon, /*[out]*/ WinMDAdapter **ppAdapter)
+{
+ HRESULT hr;
+ LPWSTR wszCorVersion = NULL;
+ WinMDAdapter* pNewAdapter = NULL;
+
+ *ppAdapter = NULL;
+
+ pNewAdapter = new (nothrow) WinMDAdapter(pRawMDCommon);
+ if (!pNewAdapter)
+ {
+ IfFailGo(E_OUTOFMEMORY);
+ }
+
+ //------------------------------------------------------------------------------------------------
+ // Create a stored string to hold our phantom metadata version string.
+ //------------------------------------------------------------------------------------------------
+ LPCSTR szVersion;
+ IfFailGo(pRawMDCommon->GetVersionString(&szVersion));
+ const char *szClrPortion = strchr(szVersion, ';');
+ if (szClrPortion)
+ {
+ pNewAdapter->m_scenario = kWinMDExp;
+ szClrPortion++;
+
+ // skip the "CLR" prefix if present
+ if ((szClrPortion[0] == 'c' || szClrPortion[0] == 'C') &&
+ (szClrPortion[1] == 'l' || szClrPortion[1] == 'L') &&
+ (szClrPortion[2] == 'r' || szClrPortion[2] == 'R'))
+ {
+ szClrPortion += 3;
+ }
+ while (szClrPortion[0] == ' ')
+ {
+ szClrPortion++;
+ }
+
+ size_t ncClrPortion = strlen(szClrPortion);
+ pNewAdapter->m_pRedirectedVersionString = new (nothrow) char[ncClrPortion + 1];
+ IfNullGo(pNewAdapter->m_pRedirectedVersionString);
+ memcpy(pNewAdapter->m_pRedirectedVersionString, szClrPortion, ncClrPortion + 1);
+ }
+ else
+ {
+ pNewAdapter->m_scenario = kWinMDNormal;
+#ifndef DACCESS_COMPILE
+ WCHAR wszCorVersion[_MAX_PATH];
+ DWORD cchWszCorVersion = _countof(wszCorVersion);
+ IfFailGo(CLRRuntimeHostInternal_GetImageVersionString (wszCorVersion, &cchWszCorVersion));
+ MAKE_UTF8PTR_FROMWIDE_NOTHROW(szCorVersion, wszCorVersion);
+ IfNullGo(szCorVersion);
+ size_t nch = strlen(szCorVersion) + 1;
+ pNewAdapter->m_pRedirectedVersionString = new (nothrow) char[nch];
+ IfNullGo(pNewAdapter->m_pRedirectedVersionString);
+ memcpy(pNewAdapter->m_pRedirectedVersionString, szCorVersion, nch);
+#else
+ pNewAdapter->m_pRedirectedVersionString = new (nothrow) char[1];
+ pNewAdapter->m_pRedirectedVersionString[0] = 0;
+#endif
+ }
+
+
+ //------------------------------------------------------------------------------------------------
+ // Find an assemblyRef to mscorlib (required to exist in .winmd files precisely to make the adapter's job easier.
+ //------------------------------------------------------------------------------------------------
+ ULONG numAssemblyRefs = pNewAdapter->m_pRawMetaModelCommonRO->CommonGetRowCount(mdtAssemblyRef);
+ pNewAdapter->m_assemblyRefMscorlib = 0;
+ pNewAdapter->m_fReferencesMscorlibV4 = FALSE;
+ for (ULONG rid = 1; rid <= numAssemblyRefs; rid++)
+ {
+ mdAssemblyRef mdar = mdtAssemblyRef|rid;
+ LPCSTR arefName;
+ USHORT usMajorVersion;
+ IfFailGo(pNewAdapter->m_pRawMetaModelCommonRO->CommonGetAssemblyRefProps(mdar, &usMajorVersion, NULL, NULL, NULL, NULL, NULL, NULL, &arefName, NULL, NULL, NULL));
+
+ // We check for legacy Core library name since Windows.winmd references mscorlib and not System.Private.CoreLib
+ if (0 == strcmp(arefName, LegacyCoreLibName_A))
+ {
+ pNewAdapter->m_assemblyRefMscorlib = mdar;
+
+ if (usMajorVersion == 4)
+ {
+ // Older WinMDExp used to incorrectly generate an assemblyRef to 4.0.0.0 mscorlib.
+ // We use this flag to implement back-compat quirks.
+ pNewAdapter->m_fReferencesMscorlibV4 = TRUE;
+ }
+
+ break;
+ }
+ }
+ if (pNewAdapter->m_assemblyRefMscorlib == 0)
+ {
+ // .winmd files are required to have an assemblyRef to mscorlib.
+ IfFailGo(COR_E_BADIMAGEFORMAT);
+ }
+
+
+ //------------------------------------------------------------------------------------------------
+ // All initialization tasks done.
+ //------------------------------------------------------------------------------------------------
+ *ppAdapter = pNewAdapter;
+ hr = S_OK;
+
+ ErrExit:
+ delete wszCorVersion;
+ if (FAILED(hr))
+ delete pNewAdapter;
+ return hr;
+}
+
+
+//------------------------------------------------------------------------------
+
+WinMDAdapter::WinMDAdapter(IMDCommon *pRawMDCommon)
+ : m_typeRefTreatmentMemoTable(pRawMDCommon->GetMetaModelCommonRO()->CommonGetRowCount(mdtTypeRef), kTrNotYetInitialized)
+ , m_typeDefTreatmentMemoTable(pRawMDCommon->GetMetaModelCommonRO()->CommonGetRowCount(mdtTypeDef), kTdNotYetInitialized)
+ , m_methodDefTreatmentMemoTable(pRawMDCommon->GetMetaModelCommonRO()->CommonGetRowCount(mdtMethodDef), kMdNotYetInitialized)
+ , m_redirectedCABlobsMemoTable(pRawMDCommon->GetMetaModelCommonRO()->CommonGetRowCount(mdtCustomAttribute), NULL)
+ , m_redirectedMethodDefSigMemoTable(pRawMDCommon->GetMetaModelCommonRO()->CommonGetRowCount(mdtMethodDef), NULL)
+ , m_redirectedFieldDefSigMemoTable(pRawMDCommon->GetMetaModelCommonRO()->CommonGetRowCount(mdtFieldDef), NULL)
+ , m_redirectedMemberRefSigMemoTable(pRawMDCommon->GetMetaModelCommonRO()->CommonGetRowCount(mdtMemberRef), NULL)
+ , m_redirectedPropertySigMemoTable(pRawMDCommon->GetMetaModelCommonRO()->CommonGetRowCount(mdtProperty), NULL)
+ , m_redirectedTypeSpecSigMemoTable(pRawMDCommon->GetMetaModelCommonRO()->CommonGetRowCount(mdtTypeSpec), NULL)
+ , m_redirectedMethodSpecSigMemoTable(pRawMDCommon->GetMetaModelCommonRO()->CommonGetRowCount(mdtMethodSpec), NULL)
+ , m_mangledTypeNameTable(pRawMDCommon->GetMetaModelCommonRO()->CommonGetRowCount(mdtTypeDef), NULL)
+ , m_extraAssemblyRefCount(-1)
+{
+ m_rawAssemblyRefCount = pRawMDCommon->GetMetaModelCommonRO()->CommonGetRowCount(mdtAssemblyRef);
+ m_pRedirectedVersionString = NULL;
+ m_pRawMetaModelCommonRO = pRawMDCommon->GetMetaModelCommonRO();
+}
+
+//------------------------------------------------------------------------------
+
+WinMDAdapter::~WinMDAdapter()
+{
+ delete m_pRedirectedVersionString;
+}
+
+
+//------------------------------------------------------------------------------
+// Hides projected jupiter struct helper class & interfaces
+
+struct HiddenWinRTTypeInfo
+{
+ LPCSTR szWinRTNamespace;
+ LPCSTR szWinRTName;
+};
+
+#define DEFINE_PROJECTED_JUPITER_STRUCT(szWinRTNamespace, szWinRTName, szClrNamespace, szClrName, nClrAssemblyIndex, nContractAssemblyIndex, WinRTRedirectedTypeIndex, ClrRedirectedTypeIndex, fieldSizes) \
+ { \
+ szWinRTNamespace, \
+ szWinRTName "Helper" \
+ },
+
+#define DEFINE_HIDDEN_WINRT_TYPE(szWinRTNamespace, szWinRTName) \
+ { \
+ szWinRTNamespace, \
+ szWinRTName \
+ },
+
+#define DEFINE_PROJECTED_TYPE(szWinRTNS, szWinRTName, szClrNS, szClrName, nClrAsmIdx, nContractAsmIdx, nWinRTIndex, nClrIndex, nWinMDTypeKind)
+
+static const HiddenWinRTTypeInfo g_rgHiddenWinRTTypes[] =
+{
+ #include "WinRTProjectedTypes.h"
+};
+
+#undef DEFINE_PROJECTED_JUPITER_STRUCT
+#undef DEFINE_HIDDEN_WINRT_TYPE
+#undef DEFINE_PROJECTED_TYPE
+
+// Whether the WinRT type should be hidden from managed code
+// Example: helper class for projected jupiter structs
+// (helper class interfaces are already private by default)
+BOOL WinMDAdapter::IsHiddenWinRTType(LPCSTR szWinRTNamespace, LPCSTR szWinRTName)
+{
+ _ASSERTE(szWinRTNamespace && szWinRTName);
+
+ for (UINT i = 0; i < _countof(g_rgHiddenWinRTTypes); i++)
+ {
+ if (0 == strcmp(szWinRTNamespace, g_rgHiddenWinRTTypes[i].szWinRTNamespace))
+ {
+ if (0 == strcmp(szWinRTName, g_rgHiddenWinRTTypes[i].szWinRTName))
+ {
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+//------------------------------------------------------------------------------
+
+struct RedirectedTypeInfo
+{
+ LPCSTR szWinRTNamespace;
+ LPCSTR szWinRTName;
+ LPCSTR szWinRTFullName;
+ LPCWSTR wszWinRTFullName;
+ LPCSTR szClrNamespace;
+ LPCSTR szClrName;
+ LPCSTR szClrFullName;
+ LPCWSTR wszClrFullName;
+ const WinMDAdapter::FrameworkAssemblyIndex nClrAssemblyIndex;
+ const WinMDAdapter::ContractAssemblyIndex nContractAssemblyIndex;
+ const WinMDAdapter::WinMDTypeKind nTypeKind;
+#ifdef _DEBUG
+ // Indexes for verification of constants RedirectedTypeIndex_*
+ const UINT dbg_nIndex1;
+ const UINT dbg_nIndex2;
+#endif
+};
+
+#define DEFINE_PROJECTED_TYPE(szWinRTNS, szWinRTName, szClrNS, szClrName, nClrAsmIdx, nContractAsmIdx, nWinRTIndex, nClrIndex, nWinMDTypeKind) \
+ { \
+ szWinRTNS, \
+ szWinRTName, \
+ szWinRTNS "." szWinRTName, \
+ L##szWinRTNS W(".") L##szWinRTName, \
+ szClrNS, \
+ szClrName, \
+ szClrNS "." szClrName, \
+ L##szClrNS W(".") L##szClrName, \
+ WinMDAdapter::FrameworkAssembly_ ## nClrAsmIdx, \
+ WinMDAdapter::ContractAssembly_ ## nContractAsmIdx, \
+ WinMDAdapter::WinMDTypeKind_ ## nWinMDTypeKind \
+ COMMA_INDEBUG(WinMDAdapter::RedirectedTypeIndex_ ## nWinRTIndex) \
+ COMMA_INDEBUG(WinMDAdapter::RedirectedTypeIndex_ ## nClrIndex) \
+ },
+
+static const RedirectedTypeInfo
+g_rgRedirectedTypes[WinMDAdapter::RedirectedTypeIndex_Count] =
+{
+#include "WinRTProjectedTypes.h"
+
+
+};
+#undef SCAT
+#undef DEFINE_PROJECTED_TYPE
+
+//------------------------------------------------------------------------------
+
+/*static*/ BOOL WinMDAdapter::ConvertWellKnownTypeNameFromWinRTToClr(LPCSTR *pszNamespace, LPCSTR *pszName)
+{
+ return ConvertWellKnownTypeNameFromWinRTToClr(pszNamespace, pszName, NULL);
+}
+
+
+// Maps well-known WinRT typenames to CLR typename. If the incoming name is not a well-known WinRT typename,
+// this function leaves *pszNamespace and *pszName alone and returns FALSE. Otherwise, it overwrites
+// them with pointers to const strings, returns the index into the rewrite table in *pIndex and returns TRUE.
+//
+// (Note: munged names from WinMDExp are not "well-known" names. Since the idea of munging them is to hide them,
+// this function will not transform such names. Not to mention, it would be hard to return such strings
+// in a function that no error return mechanism.)
+//
+/*static*/ BOOL WinMDAdapter::ConvertWellKnownTypeNameFromWinRTToClr(LPCSTR *pszNamespace, LPCSTR *pszName, UINT *pIndex)
+{
+ _ASSERTE(pszNamespace && pszName);
+ for (UINT i = 0; i < RedirectedTypeIndex_Count; i++)
+ {
+ _ASSERTE(g_rgRedirectedTypes[i].dbg_nIndex1 == i);
+ _ASSERTE(g_rgRedirectedTypes[i].dbg_nIndex2 == i);
+
+ if (0 == strcmp(*pszNamespace, g_rgRedirectedTypes[i].szWinRTNamespace))
+ {
+ if (0 == strcmp(*pszName, g_rgRedirectedTypes[i].szWinRTName))
+ {
+ *pszNamespace = g_rgRedirectedTypes[i].szClrNamespace;
+ *pszName = g_rgRedirectedTypes[i].szClrName;
+ if (pIndex)
+ *pIndex = i;
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+/*static*/ BOOL WinMDAdapter::ConvertWellKnownFullTypeNameFromWinRTToClr(LPCWSTR *pwszFullName, RedirectedTypeIndex *pIndex)
+{
+ _ASSERTE(pwszFullName);
+ for (UINT i = 0; i < RedirectedTypeIndex_Count; i++)
+ {
+ _ASSERTE(g_rgRedirectedTypes[i].dbg_nIndex1 == i);
+ _ASSERTE(g_rgRedirectedTypes[i].dbg_nIndex2 == i);
+
+ if (0 == wcscmp(*pwszFullName, g_rgRedirectedTypes[i].wszWinRTFullName))
+ {
+ *pwszFullName = g_rgRedirectedTypes[i].wszClrFullName;
+ if (pIndex)
+ *pIndex = static_cast<RedirectedTypeIndex>(i);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+//------------------------------------------------------------------------------
+
+// Maps well-known CLR typenames to WinRT typename. If the incoming name is not a well-known CLR typename,
+// this function leaves *pszNamespace and *pszName alone and returns FALSE. Otherwise, it overwrites
+// them with pointers to const strings and returns TRUE.
+//
+// (Note: munged names from WinMDExp are not "well-known" names. Since the idea of munging them is to hide them,
+// this function will not transform such names. Not to mention, it would be hard to return such strings
+// in a function that no error return mechanism.)
+//
+/*static*/ BOOL WinMDAdapter::ConvertWellKnownTypeNameFromClrToWinRT(LPCSTR *pszFullName)
+{
+ _ASSERTE(pszFullName);
+
+ for (UINT i = 0; i < RedirectedTypeIndex_Count; i++)
+ {
+ if (0 == strcmp(g_rgRedirectedTypes[i].szClrFullName, *pszFullName))
+ {
+ *pszFullName = g_rgRedirectedTypes[i].szWinRTFullName;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/*static*/ BOOL WinMDAdapter::ConvertWellKnownTypeNameFromClrToWinRT(LPCSTR *pszNamespace, LPCSTR *pszName)
+{
+ _ASSERTE(pszNamespace);
+ _ASSERTE(pszName);
+
+ for (UINT i = 0; i < RedirectedTypeIndex_Count; i++)
+ {
+ if (0 == strcmp(g_rgRedirectedTypes[i].szClrNamespace, *pszNamespace) &&
+ 0 == strcmp(g_rgRedirectedTypes[i].szClrName, *pszName))
+ {
+ *pszNamespace = g_rgRedirectedTypes[i].szWinRTNamespace;
+ *pszName = g_rgRedirectedTypes[i].szWinRTName;
+
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+//---------------------------------------------------------------------------------------
+//
+// Returns names of redirected type 'index'.
+//
+//static
+void
+WinMDAdapter::GetRedirectedTypeInfo(
+ RedirectedTypeIndex index,
+ LPCSTR * pszClrNamespace,
+ LPCSTR * pszClrName,
+ LPCSTR * pszFullWinRTName,
+ FrameworkAssemblyIndex * pFrameworkAssemblyIdx,
+ ContractAssemblyIndex * pContractAssemblyIdx,
+ WinMDTypeKind * pWinMDTypeKind)
+{
+ _ASSERTE(index < RedirectedTypeIndex_Count);
+
+ if (pszClrName != nullptr)
+ {
+ *pszClrName = g_rgRedirectedTypes[index].szClrName;
+ }
+ if (pszClrNamespace != nullptr)
+ {
+ *pszClrNamespace = g_rgRedirectedTypes[index].szClrNamespace;
+ }
+ if (pszFullWinRTName != nullptr)
+ {
+ *pszFullWinRTName = g_rgRedirectedTypes[index].szWinRTFullName;
+ }
+ if (pFrameworkAssemblyIdx != nullptr)
+ {
+ *pFrameworkAssemblyIdx = g_rgRedirectedTypes[index].nClrAssemblyIndex;
+ }
+ if (pContractAssemblyIdx != nullptr)
+ {
+ *pContractAssemblyIdx = g_rgRedirectedTypes[index].nContractAssemblyIndex;
+ }
+ if (pWinMDTypeKind != nullptr)
+ {
+ *pWinMDTypeKind = g_rgRedirectedTypes[index].nTypeKind;
+ }
+}
+
+//---------------------------------------------------------------------------------------
+//
+// Returns WinRT name of redirected type 'index'.
+//
+//static
+LPCWSTR
+WinMDAdapter::GetRedirectedTypeFullWinRTName(
+ RedirectedTypeIndex index)
+{
+ _ASSERTE(index < RedirectedTypeIndex_Count);
+
+ return g_rgRedirectedTypes[index].wszWinRTFullName;
+}
+
+//---------------------------------------------------------------------------------------
+//
+// Returns CLR name of redirected type 'index'.
+//
+//static
+LPCSTR
+WinMDAdapter::GetRedirectedTypeFullCLRName(
+ RedirectedTypeIndex index)
+{
+ _ASSERTE(index < RedirectedTypeIndex_Count);
+
+ return g_rgRedirectedTypes[index].szClrFullName;
+}
+
+//------------------------------------------------------------------------------
+//
+// Get TypeRefTreatment value for a TypeRef
+//
+HRESULT
+ WinMDAdapter::GetTypeDefTreatment(
+ mdTypeDef tkTypeDef,
+ ULONG * pTypeDefTreatment)
+{
+ HRESULT hr;
+
+ _ASSERTE(pTypeDefTreatment != NULL);
+ _ASSERTE(TypeFromToken(tkTypeDef) == mdtTypeDef);
+
+ ULONG typeDefIndex = RidFromToken(tkTypeDef) - 1;
+ ULONG treatment;
+ IfFailGo(m_typeDefTreatmentMemoTable.GetEntry(typeDefIndex, &treatment));
+ if (hr == S_FALSE)
+ {
+ LPCSTR szNamespace;
+ LPCSTR szName;
+ ULONG dwFlags;
+ mdToken extends;
+ IfFailGo(m_pRawMetaModelCommonRO->CommonGetTypeDefProps(tkTypeDef, &szNamespace, &szName, &dwFlags, &extends, NULL));
+ treatment = kTdOther;
+ ULONG baseTypeRefTreatment = kTrNotYetInitialized;
+
+ // We only want to treat this type special if it has metadata that was encoded as WinRT metadata
+ if (IsTdWindowsRuntime(dwFlags))
+ {
+ // We need to know whether the typeDef is an Enum/Struct/Delegate/Attribute
+ if (TypeFromToken(extends) == mdtTypeRef)
+ {
+ IfFailGo(GetTypeRefTreatment(extends, &baseTypeRefTreatment));
+ }
+ // Force tdWindowsRuntime flag on (@todo: WinMDExp already does this on its own - if AppModel could do so, we could get rid of this code)
+ if (m_scenario == kWinMDNormal)
+ {
+ BOOL isAttribute = FALSE;
+ if (TypeFromToken(extends) == mdtTypeRef)
+ {
+ ULONG treatment;
+ IfFailGo(GetTypeRefTreatment(extends, &treatment));
+ if (treatment == kTrSystemAttribute)
+ {
+ isAttribute = TRUE;
+ }
+ }
+
+ if (!isAttribute)
+ {
+ treatment = kTdNormalNonAttribute;
+ }
+ else
+ {
+ treatment = kTdNormalAttribute;
+ }
+ }
+
+ // Windows.Foundation.WinMD: Hide any type defs that define well-known types that we'd redirect to mscorlib equivalents.
+ LPCSTR szTempNamespace = szNamespace;
+ LPCSTR szTempName = szName;
+ if ((treatment != kTdOther) && ConvertWellKnownTypeNameFromWinRTToClr(&szTempNamespace, &szTempName))
+ {
+ if (treatment == kTdNormalNonAttribute)
+ treatment = kTdRedirectedToCLRType;
+ else
+ treatment = kTdRedirectedToCLRAttribute;
+ }
+ else
+ {
+ // WinMDExp emits two versions of RuntimeClasses and Enums:
+ //
+ // public class Foo {} // the WinRT reference class
+ // internal class <CLR>Foo {} // the implementation class that we want WinRT consumers to ignore
+ //
+ // The adapter's job is to undo WinMDExp's transformations. I.e. turn the above into:
+ //
+ // internal class <WinRT>Foo {} // the WinRT reference class that we want CLR consumers to ignore
+ // public class Foo {} // the implementation class
+ //
+ // We only add the <WinRT> prefix here since the WinRT view is the only view that is marked tdWindowsRuntime
+ // De-mangling the CLR name is done below.
+ if (m_scenario == kWinMDExp && !IsTdNested(dwFlags) && IsTdPublic(dwFlags) && !IsTdInterface(dwFlags))
+ {
+ switch (baseTypeRefTreatment)
+ {
+ case kTrSystemDelegate:
+ case kTrSystemAttribute:
+ case kTrSystemValueType:
+ {
+ // Delegates, Attributes, and Structs have only one version
+ break;
+ }
+
+ case kTrSystemEnum:
+ {
+ if (m_fReferencesMscorlibV4 && !IsTdSpecialName(dwFlags))
+ {
+ // This is a back-compat quirk. Enums exported with an older WinMDExp have only one version
+ // not marked with tdSpecialName. These enums should *not* be mangled and flipped to private.
+ break;
+ }
+ // fall-thru
+ }
+ default:
+ {
+ // Prepend "<WinRT>" and flip the visibility to private
+ treatment = kTdPrefixWinRTName;
+ }
+ }
+ }
+ }
+
+ // Scan through Custom Attributes on type, looking for interesting bits. We only need to do this for RuntimeClasses. (The if check below is conservative.)
+ if (!IsTdInterface(dwFlags) && ((treatment == kTdPrefixWinRTName) || (treatment == kTdNormalNonAttribute)))
+ {
+ HRESULT hrCA;
+ hrCA = m_pRawMetaModelCommonRO->CommonGetCustomAttributeByNameEx(tkTypeDef, "Windows.UI.Xaml.TreatAsAbstractComposableClassAttribute", NULL, NULL, NULL);
+ if (hrCA == S_OK)
+ {
+ treatment |= kTdMarkAbstractFlag;
+ }
+ }
+
+ if ((treatment == kTdNormalNonAttribute || treatment == kTdNormalAttribute) && // native WinMD, not redirected
+ IsHiddenWinRTType(szTempNamespace, szTempName) // hidden type
+ )
+ {
+ // Hide those WinRT types. Examples of those WinRT types that we need to hide are Jupiter struct helpers
+ treatment |= kTdMarkInternalFlag;
+ }
+ }
+ else if (m_scenario == kWinMDExp && !IsTdNested(dwFlags))
+ {
+ // <CLR> implementation classes are not marked tdWindowsRuntime, but still need to be modified
+ // by the adapter. See if we have one of those here.
+ LPCSTR szUnmangledName;
+ IfFailGo(CheckIfClrImplementationType(szName, dwFlags, &szUnmangledName));
+ if (hr == S_OK)
+ {
+ treatment = kTdUnmangleWinRTName;
+ }
+ }
+
+ if (baseTypeRefTreatment == kTrSystemEnum)
+ {
+ // The typeDef is an Enum. We need to store the treatment.
+ treatment |= kTdEnum;
+ }
+
+ IfFailGo(m_typeDefTreatmentMemoTable.InitEntry(typeDefIndex, &treatment));
+ }
+ _ASSERTE(treatment != kTdNotYetInitialized);
+
+ *pTypeDefTreatment = treatment;
+ hr = S_OK;
+
+ErrExit:
+ return hr;
+} // WinMDAdapter::GetTypeDefTreatment
+
+//------------------------------------------------------------------------------
+// Returns renamed typedefs
+HRESULT WinMDAdapter::GetTypeDefProps(mdTypeDef tkTypeDef, // [IN] given typedef
+ LPCUTF8 *pszNamespace, // [OUT] return typedef namespace
+ LPCUTF8 *pszName, // [OUT] return typedef name
+ DWORD *pdwFlags, // [OUT] return typedef flags
+ mdToken *ptkExtends // [OUT] Put base class TypeDef/TypeRef here.
+ )
+{
+ HRESULT hr;
+
+ _ASSERTE(TypeFromToken(tkTypeDef) == mdtTypeDef);
+
+ LPCSTR szNamespace;
+ LPCSTR szName;
+ ULONG dwFlags;
+ mdToken extends;
+ ULONG treatment;
+ IfFailGo(m_pRawMetaModelCommonRO->CommonGetTypeDefProps(tkTypeDef, &szNamespace, &szName, &dwFlags, &extends, NULL));
+ IfFailGo(GetTypeDefTreatment(tkTypeDef, &treatment));
+
+ switch (treatment & kTdTreatmentMask)
+ {
+ case kTdOther:
+ break;
+
+ case kTdNormalNonAttribute:
+ // Force tdWindowsRuntime flag on (@todo: WinMDExp already does this on its own - if AppModel could do so, we could get rid of this code)
+ dwFlags |= tdWindowsRuntime | tdImport;
+ break;
+
+ case kTdNormalAttribute:
+ // Attribute types don't really exist, so we don't want to allow derivation from them either
+ dwFlags |= tdWindowsRuntime | tdSealed;
+ break;
+
+ case kTdUnmangleWinRTName:
+ szName = szName + s_ncCLRPrefix;
+ dwFlags |= tdPublic;
+ dwFlags &= ~tdSpecialName;
+ break;
+
+ case kTdPrefixWinRTName:
+ {
+ // Prepend "<WinRT>" and flip the visibility to private
+ LPCSTR szPrefixedName;
+ ULONG index = RidFromToken(tkTypeDef) - 1;
+ IfFailGo(m_mangledTypeNameTable.GetEntry(index, &szPrefixedName));
+ if (hr == S_FALSE)
+ {
+ IfFailGo(CreatePrefixedName(s_szWinRTPrefix, szName, &szPrefixedName));
+ IfFailGo(m_mangledTypeNameTable.InitEntry(index, &szPrefixedName));
+ }
+ szName = szPrefixedName;
+ dwFlags &= ~tdPublic;
+ dwFlags |= tdImport;
+ break;
+ }
+
+ case kTdRedirectedToCLRType:
+ dwFlags &= ~tdPublic;
+ dwFlags |= tdImport;
+ break;
+
+ case kTdRedirectedToCLRAttribute:
+ dwFlags &= ~tdPublic;
+ break;
+
+ default:
+ UNREACHABLE();
+ }
+
+ if ((treatment & kTdMarkAbstractFlag) == kTdMarkAbstractFlag)
+ {
+ dwFlags |= tdAbstract;
+ }
+ if ((treatment & kTdMarkInternalFlag) == kTdMarkInternalFlag)
+ {
+ dwFlags &= ~tdPublic;
+ }
+
+ if (pszNamespace)
+ *pszNamespace = szNamespace;
+ if (pszName)
+ *pszName = szName;
+ if (pdwFlags)
+ *pdwFlags = dwFlags;
+ if (ptkExtends)
+ *ptkExtends = extends;
+
+ hr = S_OK;
+
+ ErrExit:
+ return hr;
+}
+
+//------------------------------------------------------------------------------
+
+// Find TypeDef by name
+HRESULT WinMDAdapter::FindTypeDef(
+ LPCSTR szTypeDefNamespace, // [IN] Namespace for the TypeDef.
+ LPCSTR szTypeDefName, // [IN] Name of the TypeDef.
+ mdToken tkEnclosingClass, // [IN] TypeDef/TypeRef of enclosing class.
+ mdTypeDef * ptkTypeDef // [OUT] return typedef
+)
+{
+ HRESULT hr = S_OK;
+
+ _ASSERTE((szTypeDefName != NULL) && (ptkTypeDef != NULL));
+ _ASSERTE((TypeFromToken(tkEnclosingClass) == mdtTypeRef) ||
+ (TypeFromToken(tkEnclosingClass) == mdtTypeDef) ||
+ IsNilToken(tkEnclosingClass));
+
+ // initialize the output parameter
+ *ptkTypeDef = mdTypeDefNil;
+
+ // Treat no namespace as empty string.
+ if (szTypeDefNamespace == NULL)
+ szTypeDefNamespace = "";
+
+ // Do a linear search
+ ULONG cTypeDefRecs = m_pRawMetaModelCommonRO->CommonGetRowCount(mdtTypeDef);
+
+ // Get TypeDef of the tkEnclosingClass passed in
+ if (TypeFromToken(tkEnclosingClass) == mdtTypeRef)
+ {
+ LPCUTF8 szNamespace;
+ LPCUTF8 szName;
+ mdToken tkResolutionScope;
+
+ IfFailRet(this->GetTypeRefProps(tkEnclosingClass, &szNamespace, &szName, &tkResolutionScope));
+ // Update tkEnclosingClass to TypeDef
+ IfFailRet(this->FindTypeDef(
+ szNamespace,
+ szName,
+ (TypeFromToken(tkResolutionScope) == mdtTypeRef) ? tkResolutionScope : mdTokenNil,
+ &tkEnclosingClass));
+ _ASSERTE(TypeFromToken(tkEnclosingClass) == mdtTypeDef);
+ }
+
+ // Search for the TypeDef
+ for (ULONG i = 1; i <= cTypeDefRecs; i++)
+ {
+ LPCUTF8 szNamespace;
+ LPCUTF8 szName;
+ ULONG dwFlags;
+
+ mdTypeDef tkTypeDefCandidate = TokenFromRid(i, mdtTypeDef);
+
+ IfFailRet(this->GetTypeDefProps(tkTypeDefCandidate, &szNamespace, &szName, &dwFlags, NULL));
+ if (!IsTdNested(dwFlags) && !IsNilToken(tkEnclosingClass))
+ {
+ // If the class is not Nested and EnclosingClass passed in is not nil
+ continue;
+ }
+ else if (IsTdNested(dwFlags) && IsNilToken(tkEnclosingClass))
+ {
+ // If the class is nested and EnclosingClass passed is nil
+ continue;
+ }
+ else if (!IsNilToken(tkEnclosingClass))
+ {
+ _ASSERTE(TypeFromToken(tkEnclosingClass) == mdtTypeDef);
+
+ mdTypeDef enclosingTypeDef;
+ IfFailRet(m_pRawMetaModelCommonRO->CommonGetEnclosingClassOfTypeDef(tkTypeDefCandidate, &enclosingTypeDef));
+ if (enclosingTypeDef != tkEnclosingClass)
+ {
+ // Type was not nested by tkEnclosingClass
+ continue;
+ }
+ }
+
+ if (strcmp(szTypeDefName, szName) == 0)
+ {
+ if (strcmp(szTypeDefNamespace, szNamespace) == 0)
+ {
+ *ptkTypeDef = TokenFromRid(i, mdtTypeDef);
+ return S_OK;
+ }
+ }
+ }
+ // Cannot find the TypeDef by name
+ return CLDB_E_RECORD_NOTFOUND;
+}
+
+//------------------------------------------------------------------------------
+//
+// Modifies TypeRef names and resolution scope.
+//
+HRESULT
+WinMDAdapter::GetTypeRefProps(
+ mdTypeRef tkTypeRef,
+ LPCSTR * pszNamespace,
+ LPCSTR * pszName,
+ mdToken * ptkResolutionScope)
+{
+
+ HRESULT hr;
+ ULONG treatment;
+ IfFailGo(GetTypeRefTreatment(tkTypeRef, &treatment));
+ _ASSERTE(treatment != kTrNotYetInitialized);
+
+ ULONG treatmentClass = treatment & kTrClassMask;
+ if (treatmentClass == kTrClassWellKnownRedirected)
+ {
+ ULONG nRewritePairIndex = treatment & ~kTrClassMask;
+ if (pszNamespace != NULL)
+ *pszNamespace = g_rgRedirectedTypes[nRewritePairIndex].szClrNamespace;
+ if (pszName != NULL)
+ *pszName = g_rgRedirectedTypes[nRewritePairIndex].szClrName;
+ if (ptkResolutionScope != NULL)
+ {
+ ContractAssemblyIndex assemblyIndex = g_rgRedirectedTypes[nRewritePairIndex].nContractAssemblyIndex;
+ _ASSERTE(assemblyIndex < ContractAssembly_Count);
+ *ptkResolutionScope = mdtAssemblyRef | (m_rawAssemblyRefCount + assemblyIndex + 1);
+ }
+ }
+ else
+ {
+ _ASSERTE(treatmentClass == kTrClassMisc);
+ switch (treatment)
+ {
+ case kTrNoRewriteNeeded:
+ case kTrSystemValueType:
+ case kTrSystemEnum:
+ IfFailGo(m_pRawMetaModelCommonRO->CommonGetTypeRefProps(tkTypeRef, pszNamespace, pszName, ptkResolutionScope));
+ break;
+
+ case kTrSystemDelegate:
+ if (pszNamespace != NULL) *pszNamespace = "System";
+ if (pszName != NULL) *pszName = "MulticastDelegate";
+ if (ptkResolutionScope) *ptkResolutionScope = mdtAssemblyRef | (m_rawAssemblyRefCount + ContractAssembly_SystemRuntime + 1);
+ break;
+
+ case kTrSystemAttribute:
+ if (pszNamespace != NULL) *pszNamespace = "System";
+ if (pszName != NULL) *pszName = "Attribute";
+ if (ptkResolutionScope != NULL) *ptkResolutionScope = mdtAssemblyRef | (m_rawAssemblyRefCount + ContractAssembly_SystemRuntime + 1);
+ break;
+
+ default:
+ _ASSERTE(!"Unknown treatment value.");
+ break;
+
+ }
+ }
+ hr = S_OK;
+
+ErrExit:
+ return hr;
+} // WinMDAdapter::GetTypeRefProps
+
+//------------------------------------------------------------------------------
+//
+// Get TypeRefTreatment value for a TypeRef
+//
+HRESULT
+WinMDAdapter::GetTypeRefTreatment(
+ mdTypeRef tkTypeRef,
+ ULONG * pTypeRefTreatment)
+{
+ HRESULT hr;
+
+ _ASSERTE(pTypeRefTreatment != NULL);
+ _ASSERTE(TypeFromToken(tkTypeRef) == mdtTypeRef);
+
+ ULONG typeRefIndex = RidFromToken(tkTypeRef) - 1;
+ ULONG treatment;
+ IfFailGo(m_typeRefTreatmentMemoTable.GetEntry(typeRefIndex, &treatment));
+ if (hr == S_FALSE)
+ {
+ LPCSTR szFromNamespace;
+ LPCSTR szFromName;
+ mdToken tkResolutionScope;
+ IfFailGo(m_pRawMetaModelCommonRO->CommonGetTypeRefProps(tkTypeRef, &szFromNamespace, &szFromName, &tkResolutionScope));
+ treatment = kTrNoRewriteNeeded;
+ UINT redirIndex;
+ if (ConvertWellKnownTypeNameFromWinRTToClr(&szFromNamespace, &szFromName, &redirIndex))
+ {
+ treatment = kTrClassWellKnownRedirected | redirIndex;
+ }
+ else
+ {
+ if (0 == strcmp(szFromNamespace, "System"))
+ {
+ if (0 == strcmp(szFromName, "MulticastDelegate"))
+ {
+ treatment = kTrSystemDelegate;
+ }
+ else if (0 == strcmp(szFromName, "Attribute"))
+ {
+ treatment = kTrSystemAttribute;
+ }
+ else if (0 == strcmp(szFromName, "Enum"))
+ {
+ treatment = kTrSystemEnum;
+ }
+ else if (0 == strcmp(szFromName, "ValueType"))
+ {
+ treatment = kTrSystemValueType;
+ }
+ }
+ }
+
+ // Note that we intentionally do not mangle names of TypeRef's pointing to mangled TypeDef's
+ // in the same module. This allows WinMDExp to generate "conditional TypeRef's", i.e. references
+ // to the WinMD view or CLR view, depending on whether the adapter is on.
+
+ IfFailGo(m_typeRefTreatmentMemoTable.InitEntry(typeRefIndex, &treatment));
+ }
+ _ASSERTE(treatment != kTrNotYetInitialized);
+
+ *pTypeRefTreatment = treatment;
+ hr = S_OK;
+
+ErrExit:
+ return hr;
+} // WinMDAdapter::GetTypeRefTreatment
+
+
+//------------------------------------------------------------------------------
+//
+// Get TypeRef's index in array code:g_rgRedirectedTypes.
+// Returns S_OK if TypeRef is redirected and fills its index (*pIndex).
+// Returns S_FALSE if type is not well known redirected type (*pIndex is not initialized).
+
+//
+HRESULT
+WinMDAdapter::GetTypeRefRedirectedInfo(
+ mdTypeRef tkTypeRef,
+ RedirectedTypeIndex * pIndex)
+{
+ _ASSERTE(TypeFromToken(tkTypeRef) == mdtTypeRef);
+ _ASSERTE(pIndex != NULL);
+
+ HRESULT hr;
+ ULONG treatment;
+ IfFailGo(GetTypeRefTreatment(tkTypeRef, &treatment));
+
+ ULONG treatmentClass = treatment & kTrClassMask;
+ if (treatmentClass == kTrClassWellKnownRedirected)
+ {
+ *pIndex = (RedirectedTypeIndex)(treatment & ~kTrClassMask);
+ _ASSERTE(*pIndex < RedirectedTypeIndex_Count);
+ hr = S_OK;
+ }
+ else
+ {
+ // Do not initialize *pIndex
+ hr = S_FALSE;
+ }
+
+ErrExit:
+ return hr;
+}
+
+//------------------------------------------------------------------------------
+//
+// Finds a typeref by its (transformed) name
+//
+HRESULT WinMDAdapter::FindTypeRef( // S_OK or error.
+ LPCSTR szNamespace, // [IN] Namespace for the TypeRef.
+ LPCSTR szName, // [IN] Name of the TypeRef.
+ mdToken tkResolutionScope, // [IN] Resolution Scope fo the TypeRef.
+ mdTypeRef *ptk) // [OUT] TypeRef token returned.
+{
+ HRESULT hr;
+
+ _ASSERTE(szName); // Crash on NULL pszName (just like the real metadata importer)
+ _ASSERTE(ptk); // Crash on NULL ptk (just like the real metadata importer)
+
+
+ // initialize the output parameter
+ *ptk = mdTypeRefNil;
+
+ // Treat no namespace as empty string.
+ if (!szNamespace)
+ szNamespace = "";
+
+ ULONG cTypeRefRecs = m_pRawMetaModelCommonRO->CommonGetRowCount(mdtTypeRef);
+
+ for (ULONG i = 1; i <= cTypeRefRecs; i++)
+ {
+ LPCUTF8 szNamespaceTmp;
+ LPCUTF8 szNameTmp;
+ mdToken tkRes;
+
+ mdTypeRef tr = TokenFromRid(i, mdtTypeRef);
+ IfFailGo(GetTypeRefProps(tr, &szNamespaceTmp, &szNameTmp, &tkRes));
+ if (IsNilToken(tkRes))
+ {
+ if (!IsNilToken(tkResolutionScope))
+ continue;
+ }
+ else if (tkRes != tkResolutionScope)
+ continue;
+
+ if (strcmp(szNamespace, szNamespaceTmp))
+ continue;
+
+ if (!strcmp(szNameTmp, szName))
+ {
+ *ptk = tr;
+ hr = S_OK;
+ goto ErrExit;
+ }
+ }
+
+ // cannot find the typedef
+ hr = CLDB_E_RECORD_NOTFOUND;
+ErrExit:
+ return hr;
+}
+
+//------------------------------------------------------------------------------
+
+HRESULT WinMDAdapter::ModifyExportedTypeName(
+ mdExportedType tkExportedType, // [IN] exportedType token
+ LPCSTR *pszNamespace, // [IN,OUT,OPTIONAL] namespace to modify
+ LPCSTR *pszName // [IN,OUT,OPTIONAL] name to modify
+)
+{
+ _ASSERTE(TypeFromToken(tkExportedType) == mdtExportedType);
+
+ if (m_scenario == kWinMDExp)
+ {
+ if (pszName && 0 == strncmp(*pszName, s_szCLRPrefix, s_ncCLRPrefix))
+ {
+ (*pszName) += s_ncCLRPrefix;
+ }
+ }
+ return S_OK;
+}
+
+//------------------------------------------------------------------------------
+
+// We must optionaly add an assembly ref for System.Numerics.Vectors.dll since this assembly is not available
+// on downlevel platforms.
+//
+// This function assumes that System.Numerics.Vectors.dll is the last assembly that
+// we add so if we find a reference then we return ContractAssembly_Count otherwise we return
+// ContractAssembly_Count - 1.
+int WinMDAdapter::GetExtraAssemblyRefCount()
+{
+ HRESULT hr;
+
+ if (m_extraAssemblyRefCount == -1)
+ {
+ mdAssemblyRef tkSystemNumericsVectors = TokenFromRid(m_rawAssemblyRefCount + ContractAssembly_SystemNumericsVectors + 1, mdtAssemblyRef);
+ ULONG cTypeRefRecs = m_pRawMetaModelCommonRO->CommonGetRowCount(mdtTypeRef);
+ BOOL systemNumericsVectorsTypeFound = FALSE;
+
+ for (ULONG i = 1; i <= cTypeRefRecs; i++)
+ {
+ mdToken tkResolutionScope;
+ mdTypeRef tkTypeRef = TokenFromRid(i, mdtTypeRef);
+
+ // Get the resolution scope(AssemblyRef) token for the type. GetTypeRefProps does the type redirection.
+ IfFailGo(GetTypeRefProps(tkTypeRef, nullptr, nullptr, &tkResolutionScope));
+
+ if (tkResolutionScope == tkSystemNumericsVectors)
+ {
+ systemNumericsVectorsTypeFound = TRUE;
+ break;
+ }
+ }
+
+ if (systemNumericsVectorsTypeFound)
+ {
+ m_extraAssemblyRefCount = ContractAssembly_Count;
+ }
+ else
+ {
+ m_extraAssemblyRefCount = ContractAssembly_Count - 1;
+ }
+ }
+
+ErrExit:
+ if (m_extraAssemblyRefCount == -1)
+ {
+ // Setting m_extraAssemblyRefCount to ContractAssembly_Count so that this function returns a stable value and
+ // that if there is a System.Numerics type ref that it does not have a dangling assembly ref
+ m_extraAssemblyRefCount = ContractAssembly_Count;
+ }
+
+ return m_extraAssemblyRefCount;
+}
+
+//------------------------------------------------------------------------------
+
+/*static*/
+void WinMDAdapter::GetExtraAssemblyRefProps(FrameworkAssemblyIndex index,
+ LPCSTR* ppName,
+ AssemblyMetaDataInternal* pContext,
+ PCBYTE * ppPublicKeytoken,
+ DWORD* pTokenLength,
+ DWORD* pdwFlags)
+{
+ _ASSERTE(index >= 0 && index < FrameworkAssembly_Count);
+ _ASSERTE(index != FrameworkAssembly_Mscorlib);
+
+ if (ppName)
+ {
+ *ppName = GetExtraAssemblyRefNameFromIndex((FrameworkAssemblyIndex)index);
+ }
+
+ if (pContext)
+ {
+ ::memset(pContext, 0, sizeof(AssemblyMetaDataInternal));
+
+ pContext->usMajorVersion = VER_ASSEMBLYMAJORVERSION;
+ pContext->usMinorVersion = VER_ASSEMBLYMINORVERSION;
+ pContext->usBuildNumber = VER_ASSEMBLYBUILD;
+ pContext->usRevisionNumber = VER_ASSEMBLYBUILD_QFE;
+
+ pContext->szLocale = "";
+ }
+
+ 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)
+ {
+ *ppPublicKeytoken = s_pbContractPublicKeyToken;
+ *pTokenLength = sizeof(s_pbContractPublicKeyToken);
+ }
+ else
+ {
+ *ppPublicKeytoken = s_pbFrameworkPublicKeyToken;
+ *pTokenLength = sizeof(s_pbFrameworkPublicKeyToken);
+ }
+ }
+ }
+
+ if (pdwFlags)
+ {
+ // ppPublicKeytoken contains the public key token, not the whole key.
+ *pdwFlags = 0;
+ }
+}
+
+//--------------------------------------------------------------------------------
+
+HRESULT WinMDAdapter::FindExportedType(
+ LPCUTF8 szNamespace, // [IN] expected namespace
+ LPCUTF8 szName, // [IN] expected name
+ mdToken tkEnclosingType, // [IN] expected tkEnclosingType
+ mdExportedType *ptkExportedType // [OUT] ExportedType token returned.
+)
+{
+ HRESULT hr;
+
+ _ASSERTE(szName && ptkExportedType);
+
+ // Set NULL namespace to empty string.
+ if (!szNamespace)
+ szNamespace = "";
+
+ // Set output to Nil.
+ *ptkExportedType = mdTokenNil;
+
+ ULONG ulCount = m_pRawMetaModelCommonRO->CommonGetRowCount(mdtExportedType);
+ while (ulCount)
+ {
+ mdExportedType tkCandidateExportedType = TokenFromRid(ulCount--, mdtExportedType);
+
+ LPCSTR szCandidateNamespace;
+ LPCSTR szCandidateName;
+ mdToken tkCandidateImpl;
+
+ IfFailRet(m_pRawMetaModelCommonRO->CommonGetExportedTypeProps(tkCandidateExportedType, &szCandidateNamespace, &szCandidateName, &tkCandidateImpl));
+ IfFailRet(this->ModifyExportedTypeName(tkCandidateExportedType, &szCandidateNamespace, &szCandidateName));
+ // Handle the case of nested vs. non-nested classes.
+ if (TypeFromToken(tkCandidateImpl) == mdtExportedType && !IsNilToken(tkCandidateImpl))
+ {
+ // Current ExportedType being looked at is a nested type, so
+ // comparing the implementation token.
+ if (tkCandidateImpl != tkEnclosingType)
+ continue;
+ }
+ else if (TypeFromToken(tkEnclosingType) == mdtExportedType &&
+ !IsNilToken(tkEnclosingType))
+ {
+ // ExportedType passed in is nested but the current ExportedType is not.
+ continue;
+ }
+
+ if (0 != strcmp(szName, szCandidateName))
+ continue;
+
+ if (0 != strcmp(szNamespace, szCandidateNamespace))
+ continue;
+
+ *ptkExportedType = tkCandidateExportedType;
+ return S_OK;
+ }
+ return CLDB_E_RECORD_NOTFOUND;
+}
+
+
+//------------------------------------------------------------------------------
+
+// Modifies methodDef flags and RVA
+HRESULT WinMDAdapter::ModifyMethodProps(mdMethodDef tkMethodDef, /*[in, out]*/ DWORD *pdwAttr, /* [in,out] */ DWORD *pdwImplFlags, /* [in,out] */ ULONG *pulRVA, /* [in, out] */ LPCSTR *pszName)
+{
+ HRESULT hr;
+ _ASSERTE(TypeFromToken(tkMethodDef) == mdtMethodDef);
+
+ ULONG mdTreatment;
+ IfFailGo(GetMethodDefTreatment(tkMethodDef, &mdTreatment));
+
+ DWORD dwAttr = pdwAttr ? *pdwAttr: 0;
+ DWORD dwImplFlags = pdwImplFlags ? *pdwImplFlags : 0;
+ ULONG ulRVA = pulRVA ? *pulRVA : 0;
+
+ switch (mdTreatment & kMdTreatmentMask)
+ {
+ case kMdInterface:
+ // Method is declared on an interface
+ dwImplFlags |= miRuntime|miInternalCall;
+ break;
+
+ case kMdDelegate:
+ // Method is declared on a delegate
+ dwAttr &= ~mdMemberAccessMask;
+ dwAttr |= mdPublic;
+ ulRVA = 0;
+ dwImplFlags |= miRuntime;
+ break;
+
+ case kMdAttribute:
+ // Method is declared on an attribute
+ ulRVA = 0;
+ dwImplFlags |= miRuntime|miInternalCall;
+ break;
+
+ case kMdImplementation:
+ // CLR implementation class. Needs no adjustment.
+ break;
+
+ case kMdHiddenImpl:
+ dwAttr &= ~mdMemberAccessMask;
+ dwAttr |= mdPrivate;
+ // fall-through
+
+ case kMdOther:
+
+ // All other cases
+ ulRVA = 0;
+ dwImplFlags |= miRuntime|miInternalCall;
+
+ if (mdTreatment & kMdMarkAbstractFlag)
+ {
+ dwAttr |= mdAbstract;
+ }
+
+ if (mdTreatment & kMdMarkPublicFlag)
+ {
+ dwAttr &= ~mdMemberAccessMask;
+ dwAttr |= mdPublic;
+ }
+
+ break;
+
+ case kMdRenameToDisposeMethod:
+ ulRVA = 0;
+ dwImplFlags |= miRuntime|miInternalCall;
+ if(pszName)
+ {
+ *pszName = "Dispose";
+ }
+ break;
+
+ default:
+ UNREACHABLE();
+
+ }
+
+ dwAttr |= mdHideBySig;
+
+ if (pdwAttr)
+ (*pdwAttr) = dwAttr;
+ if (pdwImplFlags)
+ (*pdwImplFlags) = dwImplFlags;
+ if (pulRVA)
+ *pulRVA = ulRVA;
+ hr = S_OK;
+
+ ErrExit:
+ return hr;
+}
+
+HRESULT WinMDAdapter::ModifyFieldProps (mdToken tkField, mdToken tkParent, LPCSTR szFieldName, DWORD *pdwFlags)
+{
+ _ASSERTE(szFieldName != NULL);
+
+ HRESULT hr;
+ if (pdwFlags && IsFdPrivate(*pdwFlags) && (0 == strcmp(szFieldName, "value__")))
+ {
+ ULONG treatment;
+ BOOL isEnum = FALSE;
+ if(TypeFromToken(tkParent) == mdtTypeDef)
+ {
+ IfFailGo(GetTypeDefTreatment(tkParent, &treatment));
+
+ if ((treatment & kTdEnum) == kTdEnum)
+ {
+ isEnum = TRUE;
+ }
+ }
+
+ if (isEnum)
+ {
+ // We have found the value__ field of the enum.
+ // We need to change its flags from private to public
+ *pdwFlags = (*pdwFlags & ~fdPrivate) | fdPublic;
+ }
+ }
+
+ hr = S_OK;
+
+ErrExit:
+ return hr;
+}
+
+
+HRESULT WinMDAdapter::ModifyFieldDefProps (mdFieldDef tkFielddDef, DWORD *pdwFlags)
+{
+ HRESULT hr;
+
+ if (pdwFlags)
+ {
+ mdTypeDef tkParent;
+ LPCSTR szName;
+ IfFailGo(m_pRawMetaModelCommonRO->CommonGetFieldDefProps(tkFielddDef, &tkParent, &szName, pdwFlags));
+ IfFailGo(ModifyFieldProps(tkFielddDef, tkParent, szName, pdwFlags));
+ }
+
+ hr = S_OK;
+ErrExit:
+ return hr;
+}
+
+//------------------------------------------------------------------------------
+
+HRESULT WinMDAdapter::ModifyMemberProps(mdToken tkMember, /*[in, out]*/ DWORD *pdwAttr, /* [in,out] */ DWORD *pdwImplFlags, /* [in,out] */ ULONG *pulRVA, LPCSTR *pszNewName)
+{
+ HRESULT hr;
+ switch(TypeFromToken(tkMember))
+ {
+ case mdtMethodDef: IfFailGo(ModifyMethodProps(tkMember, pdwAttr, pdwImplFlags, pulRVA, pszNewName));
+ break;
+
+ case mdtMemberRef:
+ {
+ //
+ // We need to rename the MemberRef for IClosable.Close as well
+ // so that the MethodImpl for Dispose method can correctly be shown as IDisposable.Dispose
+ // instead of IDisposable.Close
+ //
+ UINT nIndex = WinMDAdapter::RedirectedTypeIndex_Invalid;
+ if (pszNewName &&
+ CheckIfMethodImplImplementsARedirectedInterface(tkMember, &nIndex) == S_OK &&
+ nIndex == WinMDAdapter::RedirectedTypeIndex_Windows_Foundation_IClosable)
+ {
+ *pszNewName = "Dispose";
+ }
+ }
+ break;
+
+ case mdtFieldDef:
+ IfFailGo(ModifyFieldDefProps(tkMember, pdwAttr));
+ break;
+ }
+
+ hr = S_OK;
+ErrExit:
+ return hr;
+}
+
+//------------------------------------------------------------------------------
+
+// Get MethodTreatment value for a methodDef
+HRESULT WinMDAdapter::GetMethodDefTreatment(mdMethodDef tkMethodDef, ULONG *ppMethodDefTreatment)
+{
+ HRESULT hr;
+
+ _ASSERTE(TypeFromToken(tkMethodDef) == mdtMethodDef);
+ ULONG index = RidFromToken(tkMethodDef) - 1;
+
+ // Thread-safety: No lock is needed to update this table as we're monotonically advancing a kMdNotYetInitialized to
+ // some other fixed byte. The work to decide this value is idempotent and side-effect free so
+ // there's no harm if two threads do it concurrently.
+ ULONG mdTreatment;
+ IfFailGo(m_methodDefTreatmentMemoTable.GetEntry(index, &mdTreatment));
+ if (hr == S_FALSE)
+ {
+ mdTypeDef declaringTypeDef;
+ IfFailGo(m_pRawMetaModelCommonRO->FindParentOfMethodHelper(tkMethodDef, &declaringTypeDef));
+ ULONG firstMethodRid;
+ IfFailGo(m_pRawMetaModelCommonRO->CommonGetTypeDefProps(declaringTypeDef, NULL, NULL, NULL, NULL, &firstMethodRid));
+ IfFailGo(ComputeMethodDefTreatment(tkMethodDef, declaringTypeDef, &mdTreatment));
+ _ASSERTE(mdTreatment != kMdNotYetInitialized);
+ IfFailGo(m_methodDefTreatmentMemoTable.InitEntry(index, &mdTreatment));
+
+ // Since the mdTreatment is only a function of the declaring type in most cases, cache it for all the declared method since
+ // we took the time to look up the declaring type. Do enough validity checks to avoid corrupting the heap
+ // or table but otherwise, swallow validity errors as this is just an optimization.
+ // Methods on RuntimeClasses need to get treatment data per method.
+ if (((mdTreatment & kMdTreatmentMask) != kMdOther) &&
+ ((mdTreatment & kMdTreatmentMask) != kMdHiddenImpl) &&
+ ((mdTreatment & kMdTreatmentMask) != kMdRenameToDisposeMethod))
+ {
+ const ULONG methodDefCount = m_pRawMetaModelCommonRO->CommonGetRowCount(mdtMethodDef);
+ const ULONG startIndex = RidFromToken(firstMethodRid) - 1;
+ if (startIndex < methodDefCount)
+ {
+ const ULONG typeDefCount = m_pRawMetaModelCommonRO->CommonGetRowCount(mdtTypeDef);
+ if (RidFromToken(declaringTypeDef) < typeDefCount)
+ {
+ ULONG stopMethodRid;
+ if (S_OK == m_pRawMetaModelCommonRO->CommonGetTypeDefProps(declaringTypeDef + 1, NULL, NULL, NULL, NULL, &stopMethodRid))
+ {
+ ULONG stopIndex = RidFromToken(stopMethodRid) - 1;
+ if (startIndex < methodDefCount && stopIndex <= methodDefCount)
+ {
+ ULONG walkIndex = startIndex;
+ while (walkIndex < stopIndex)
+ {
+ IfFailGo(m_methodDefTreatmentMemoTable.InitEntry(walkIndex++, &mdTreatment));
+ }
+ }
+ }
+ }
+ else
+ {
+ // This was final typeDef - blast the mdTreatment into the rest of the table.
+ for (ULONG i = startIndex; i < methodDefCount; i++)
+ {
+ IfFailGo(m_methodDefTreatmentMemoTable.InitEntry(i, &mdTreatment));
+ }
+ }
+ }
+ }
+ }
+
+ *ppMethodDefTreatment = mdTreatment;
+ hr = S_OK;
+
+ ErrExit:
+ return hr;
+}
+
+//------------------------------------------------------------------------------
+
+// Compute MethodTreatment value for a methodDef (unlike GetMethodDefTreatment, this
+// does not cache.)
+//
+HRESULT WinMDAdapter::ComputeMethodDefTreatment(mdMethodDef tkMethodDef, mdTypeDef tkDeclaringTypeDef, ULONG *ppMethodDefTreatment)
+{
+ HRESULT hr;
+
+ BYTE mdTreatment = kMdImplementation;
+
+ LPCSTR szDeclaringTypeName;
+ DWORD parentTdAttr;
+ mdToken extends;
+ IfFailGo(m_pRawMetaModelCommonRO->CommonGetTypeDefProps(tkDeclaringTypeDef, NULL, &szDeclaringTypeName, &parentTdAttr, &extends, NULL));
+
+ // We only want to treat this method special if it has metadata exposed to WinRT
+ if (IsTdWindowsRuntime(parentTdAttr))
+ {
+ LPCSTR szUnmangledName;
+ IfFailGo(CheckIfClrImplementationType(szDeclaringTypeName, parentTdAttr, &szUnmangledName));
+ if (hr == S_OK)
+ {
+ mdTreatment = kMdImplementation;
+ }
+ else if (IsTdNested(parentTdAttr))
+ {
+ // nested types are implementation
+ mdTreatment = kMdImplementation;
+ }
+ else if (parentTdAttr & tdInterface)
+ {
+ // Method is declared on an interface.
+ mdTreatment = kMdInterface;
+ }
+ else if (m_scenario == kWinMDExp && (parentTdAttr & tdPublic) == 0)
+ {
+ // internal classes generated by WinMDExp are implementation
+ mdTreatment = kMdImplementation;
+ }
+ else
+ {
+ mdTreatment = kMdOther;
+
+ if (TypeFromToken(extends) == mdtTypeRef)
+ {
+ ULONG trTreatment;
+ IfFailGo(GetTypeRefTreatment(extends, &trTreatment));
+ if (trTreatment == kTrSystemDelegate)
+ {
+ // Method is declared on a delegate
+ mdTreatment = kMdDelegate;
+ }
+ else if (trTreatment == kTrSystemAttribute)
+ {
+ // Method is declared on a attribute
+ mdTreatment = kMdAttribute;
+ }
+ }
+ }
+ }
+ if (mdTreatment == kMdOther)
+ {
+ // we want to hide the method if it implements only redirected interfaces
+ // Also we want to check if the methodImpl is IClosable.Close then we will change the name.
+ bool fSeenRedirectedInterfaces = false;
+ bool fSeenNonRedirectedInterfaces = false;
+
+ bool isIClosableCloseMethod = false;
+
+ mdToken tkMethodImplFirst;
+ ULONG count;
+ mdTypeRef mtTypeRef;
+ IfFailGo(m_pRawMetaModelCommonRO->CommonGetMethodImpls(tkDeclaringTypeDef, &tkMethodImplFirst, &count));
+ for (ULONG i = 0; i < count; i++)
+ {
+ mdToken tkMethodImpl = tkMethodImplFirst + i;
+ mdToken tkBody, tkDecl;
+ IfFailGo(m_pRawMetaModelCommonRO->CommonGetMethodImplProps(tkMethodImpl, &tkBody, &tkDecl));
+
+ if (tkBody == tkMethodDef)
+ {
+ // See if this MethodImpl implements a redirected interface
+ UINT nIndex;
+ IfFailGo(CheckIfMethodImplImplementsARedirectedInterface(tkDecl, &nIndex));
+ if (hr == S_FALSE)
+ {
+ // Now we know this implements a non-redirected interface
+ // But we need to keep looking, just in case we got a MethodImpl that implements
+ // the IClosable.Close method and needs to be renamed
+ fSeenNonRedirectedInterfaces = true;
+ }
+ else if (SUCCEEDED(hr))
+ {
+ fSeenRedirectedInterfaces = true;
+ if (nIndex == WinMDAdapter::RedirectedTypeIndex_Windows_Foundation_IClosable)
+ {
+ // This method implements IClosable.Close
+ // Let's rename it to Dispose later
+ // Once we know this implements IClosable.Close, we are done looking as we know
+ // we won't hide it
+ isIClosableCloseMethod = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (isIClosableCloseMethod)
+ {
+ // Rename IClosable.Close to Dispose
+ mdTreatment = kMdRenameToDisposeMethod;
+ }
+ else if (fSeenRedirectedInterfaces && !fSeenNonRedirectedInterfaces)
+ {
+ // Only hide if all the interfaces implemented are redirected
+ mdTreatment = kMdHiddenImpl;
+ }
+ }
+
+ // If treatment is other, then this is a non-managed WinRT runtime class definition. Find out about various bits that we apply via attrubtes and name parsing.
+ if (mdTreatment == kMdOther)
+ {
+ // Scan through Custom Attributes on type, looking for interesting bits.
+ HRESULT hrCA;
+ hrCA = m_pRawMetaModelCommonRO->CommonGetCustomAttributeByNameEx(tkMethodDef, "Windows.UI.Xaml.TreatAsPublicMethodAttribute", NULL, NULL, NULL);
+ if (hrCA == S_OK)
+ {
+ mdTreatment |= kMdMarkPublicFlag;
+ }
+
+
+ hrCA = m_pRawMetaModelCommonRO->CommonGetCustomAttributeByNameEx(tkMethodDef, "Windows.UI.Xaml.TreatAsAbstractMethodAttribute", NULL, NULL, NULL);
+ if (hrCA == S_OK)
+ {
+ mdTreatment |= kMdMarkAbstractFlag;
+ }
+
+ LPCSTR szName;
+ DWORD dwFlags;
+ IfFailRet(m_pRawMetaModelCommonRO->CommonGetMethodDefProps(tkMethodDef, &szName, &dwFlags, NULL, NULL));
+ }
+ *ppMethodDefTreatment = mdTreatment;
+ hr = S_OK;
+
+ErrExit:
+ return hr;
+}
+
+//------------------------------------------------------------------------------
+
+//
+// Finds a CA by its (transformed) name
+//
+HRESULT WinMDAdapter::GetCustomAttributeByName( // S_OK or error.
+ mdToken tkObj, // [IN] Object with Custom Attribute.
+ LPCUTF8 szName, // [IN] Name of desired Custom Attribute.
+ mdCustomAttribute *ptkCA, // [OUT] Put custom attribute token here
+ const void **ppData, // [OUT] Put pointer to data here.
+ ULONG *pcbData) // [OUT] Put size of data here.
+{
+ HRESULT hr;
+ _ASSERTE(szName);
+
+ if (ConvertWellKnownTypeNameFromClrToWinRT(&szName))
+ {
+ mdCustomAttribute tkCA;
+ IfFailGo(m_pRawMetaModelCommonRO->CommonGetCustomAttributeByNameEx(tkObj, szName, &tkCA, NULL, NULL));
+ if (hr == S_FALSE)
+ goto ErrExit;
+ if (ptkCA)
+ *ptkCA = tkCA;
+ IfFailGo(GetCustomAttributeBlob(tkCA, ppData, pcbData));
+ }
+ else
+ {
+ IfFailGo(m_pRawMetaModelCommonRO->CommonGetCustomAttributeByNameEx(tkObj, szName, ptkCA, ppData, pcbData));
+ }
+ ErrExit:
+ return hr;
+}
+
+//------------------------------------------------------------------------------
+
+//
+// Modify CA blobs
+//
+HRESULT WinMDAdapter::GetCustomAttributeBlob(
+ mdCustomAttribute tkCA,
+ const void **ppData, // [OUT] Put pointer to data here.
+ ULONG *pcbData) // [OUT] Put size of data here.
+{
+ HRESULT hr;
+
+ _ASSERTE(TypeFromToken(tkCA) == mdtCustomAttribute);
+ ULONG index = RidFromToken(tkCA) - 1;
+
+ // If someone already queried this CA, use the previous result.
+ CABlob * pCABlob;
+ IfFailGo(m_redirectedCABlobsMemoTable.GetEntry(index, &pCABlob));
+ if (hr == S_FALSE)
+ {
+ // No, we're the first. Initialize the entry (keeping in mind we may be racing with other threads.)
+ pCABlob = CABlob::NOREDIRECT;
+ mdToken tkOwner;
+ mdToken tkCtor;
+ IfFailGo(m_pRawMetaModelCommonRO->CommonGetCustomAttributeProps(tkCA, &tkOwner, &tkCtor, NULL, NULL));
+ if (TypeFromToken(tkOwner) == mdtTypeDef) // AttributeUsageAttribute only goes on a typeDef, so if the owner isn't a typeDef, no point in going further.
+ {
+ if (TypeFromToken(tkCtor) == mdtMemberRef) // REX has promised to use a memberRef (not Def) here.
+ {
+ mdToken tkCtorType;
+ IfFailGo(m_pRawMetaModelCommonRO->CommonGetMemberRefProps(tkCtor, &tkCtorType));
+ if (TypeFromToken(tkCtorType) == mdtTypeRef) // REX has promised to use a typeRef (not a Def, or heavens forbid, a Spec) here
+ {
+ RedirectedTypeIndex redirectedTypeIndex;
+ IfFailGo(GetTypeRefRedirectedInfo(tkCtorType, &redirectedTypeIndex));
+ _ASSERTE((hr == S_OK) || (hr == S_FALSE));
+
+ if ((hr == S_OK) && (redirectedTypeIndex == RedirectedTypeIndex_Windows_Foundation_Metadata_AttributeUsageAttribute))
+ {
+ // We found a Windows.Foundation.Metadata.AttributeUsageAttribute. The TypeRef redirection already makes this
+ // look like a System.AttributeUsageAttribute. Must munge the blob so that it matches the CLR expections.
+ BOOL allowMultiple;
+ DWORD clrTargetValue;
+ IfFailGo(TranslateWinMDAttributeUsageAttribute(tkOwner, &clrTargetValue, &allowMultiple));
+ if (hr == S_OK)
+ {
+ CABlob *pNewCABlob = NULL;
+ IfFailGo(CreateClrAttributeUsageAttributeCABlob(clrTargetValue, allowMultiple, &pNewCABlob));
+ pCABlob = pNewCABlob;
+ }
+ }
+ }
+ }
+ }
+
+ IfFailGo(m_redirectedCABlobsMemoTable.InitEntry(index, &pCABlob));
+ }
+
+ _ASSERTE(pCABlob != NULL);
+ const void *pData;
+ ULONG cbData;
+ if (pCABlob == CABlob::NOREDIRECT)
+ {
+ // The normal case: don't rewrite the blob.
+ IfFailGo(m_pRawMetaModelCommonRO->CommonGetCustomAttributeProps(tkCA, NULL, NULL, &pData, &cbData));
+ }
+ else
+ {
+ // The special cases: Blob was rewritten, return the rewritten blob.
+ pData = pCABlob->data;
+ cbData = pCABlob->cbBlob;
+ }
+ if (ppData)
+ *ppData = pData;
+ if (pcbData)
+ *pcbData = cbData;
+
+ hr = S_OK;
+ ErrExit:
+ return hr;
+}
+
+//------------------------------------------------------------------------------
+
+// Note: This method will look in a cache for the reinterpreted signature, but does not add any values to
+// the cache or do any work on failure. If we can't find it then it returns S_FALSE.
+HRESULT WinMDAdapter::GetCachedSigForToken(
+ mdToken token, // [IN] given token
+ MemoTable<SigData*, SigData::Destroy> &memoTable, // [IN] the MemoTable to use
+ ULONG *pcbSigBlob, // [OUT] count of bytes in the signature blob
+ PCCOR_SIGNATURE *ppSig, // [OUT] new signature
+ BOOL *pfPassThrough // [OUT] did the cache say we don't need to reinterpret this sig?
+)
+{
+ _ASSERTE(pfPassThrough != NULL);
+
+ HRESULT hr;
+
+ ULONG index = RidFromToken(token) - 1;
+
+ // If someone already queried this method signature, use the previous result.
+ SigData *pSigData = NULL;
+ IfFailGo(memoTable.GetEntry(index, &pSigData));
+ if (hr == S_FALSE)
+ {
+ *pfPassThrough = FALSE;
+ return S_FALSE;
+ }
+
+ _ASSERTE(pSigData != NULL);
+
+ if (pSigData == SigData::NOREDIRECT)
+ {
+ // The normal case: don't rewrite the signature.
+ *pfPassThrough = TRUE;
+ return S_FALSE;
+ }
+ else
+ {
+ *pfPassThrough = FALSE;
+ // The signature was rewritten, return the rewritten sig.
+ if (ppSig)
+ *ppSig = (PCCOR_SIGNATURE) pSigData->data;
+ if (pcbSigBlob)
+ *pcbSigBlob = pSigData->cbSig;
+ }
+
+ hr = S_OK;
+
+ ErrExit:
+ return hr;
+}
+
+//------------------------------------------------------------------------------
+// static
+HRESULT WinMDAdapter::InsertCachedSigForToken(
+ mdToken token, // [IN] given token
+ MemoTable<SigData*, SigData::Destroy> &memoTable, // [IN] the MemoTable to use
+ SigData **ppSigData // [IN, OUT] new signature or SigData::NOREDIRECT if the signature didn't need to be reparsed,
+) // will be updated with another (but identical) SigData* if this thread lost the race
+{
+ _ASSERTE(ppSigData != NULL && *ppSigData != NULL);
+
+ HRESULT hr;
+ ULONG index = RidFromToken(token) - 1;
+
+ IfFailGo(memoTable.InitEntry(index, ppSigData));
+ hr = S_OK;
+
+ ErrExit:
+ return hr;
+}
+
+//------------------------------------------------------------------------------
+static HRESULT FinalizeSignatureRewrite(
+ SigBuilder & newSig,
+ BOOL fChangedSig,
+ WinMDAdapter::SigData **ppSigData
+ DEBUG_ARG(ULONG cbOrigSigBlob)
+ )
+{
+ // Make sure we didn't lose anything, since we wrote out the full signature.
+ ULONG cbNewSigLen;
+ BYTE * pNewSigBytes = (BYTE *) newSig.GetSignature(&cbNewSigLen);
+ _ASSERTE(cbNewSigLen == cbOrigSigBlob); // Didn't lose any data nor add anything
+
+ // Set the output SigData appropriately.
+ if (fChangedSig)
+ {
+ *ppSigData = WinMDAdapter::SigData::Create(cbNewSigLen, pNewSigBytes);
+
+ if (*ppSigData == NULL)
+ {
+ return E_OUTOFMEMORY;
+ }
+ }
+ else
+ {
+ *ppSigData = WinMDAdapter::SigData::NOREDIRECT;
+ }
+ return S_OK;
+}
+
+//------------------------------------------------------------------------------
+
+// Purpose: Translate method signatures containing classes that we're projecting as value types, and vice versa.
+// Example: ELEMENT_TYPE_CLASS [IReference<T>] to ELEMENT_TYPE_VALUETYPE [Nullable<T>]
+// Example: ELEMENT_TYPE_VALUETYPE [Windows.Foundation.HResult] to ELEMENT_TYPE_CLASS [Exception]
+HRESULT WinMDAdapter::ReinterpretMethodSignature(
+ ULONG cbOrigSigBlob, // [IN] count of bytes in the original signature blob
+ PCCOR_SIGNATURE pOrigSig, // [IN] original signature
+ SigData **ppSigData // [OUT] new signature or SigData::NOREDIRECT
+)
+{
+ _ASSERTE(pOrigSig != NULL);
+ _ASSERTE(ppSigData != NULL);
+
+ HRESULT hr;
+
+ // @REVISIT_TODO: Need to allocate memory here. We cannot take a lock though (such as any lock needed by 'new'), or we can get
+ // into deadlocks from profilers that need to inspect metadata to walk the stack. Needs some help from some loader/ngen experts.
+
+ BOOL fChangedSig = FALSE;
+
+ // The following implements MethodDef signature parsing, per ECMA CLI spec, section 23.2.1.
+ SigParser sigParser(pOrigSig, cbOrigSigBlob);
+ SigBuilder newSig(cbOrigSigBlob); // We will not change the signature size, just modify it a bit (E_T_CLASS <-> E_T_VALUETYPE)
+
+ // Read calling convention info - Note: Calling convention is always one byte
+ ULONG callingConvention;
+ IfFailGo(sigParser.GetCallingConvInfo(&callingConvention));
+ _ASSERTE((callingConvention & 0xff) == callingConvention);
+ newSig.AppendByte((BYTE)callingConvention);
+
+ // If it is generic, read the generic parameter count
+ if ((callingConvention & CORINFO_CALLCONV_GENERIC) != 0)
+ {
+ ULONG genericArgsCount;
+ IfFailGo(sigParser.GetData(&genericArgsCount));
+ newSig.AppendData(genericArgsCount);
+ }
+
+ // Read number of locals / method parameters
+ ULONG cParameters;
+ IfFailGo(sigParser.GetData(&cParameters));
+ newSig.AppendData(cParameters);
+
+ if (callingConvention != CORINFO_CALLCONV_LOCAL_SIG)
+ {
+ // Read return type
+ IfFailGo(RewriteTypeInSignature(&sigParser, &newSig, &fChangedSig));
+ }
+
+ // Visit each local / parameter
+ for (ULONG i = 0; i < cParameters; i++)
+ {
+ IfFailGo(RewriteTypeInSignature(&sigParser, &newSig, &fChangedSig));
+ }
+
+ IfFailGo(FinalizeSignatureRewrite(newSig, fChangedSig, ppSigData DEBUG_ARG(cbOrigSigBlob)));
+ return S_OK;
+
+ErrExit:
+ Debug_ReportError("Couldn't parse a signature in WinMDAdapter::ReinterpretMethodSignature!");
+ return hr;
+} // WinMDAdapter::ReinterpretMethodSignature
+
+
+//------------------------------------------------------------------------------
+
+// Purpose: Translate FieldDef signatures containing classes that we're projecting as value types, and vice versa.
+// Example: ELEMENT_TYPE_VALUETYPE [Windows.Foundation.HResult] to ELEMENT_TYPE_CLASS [Exception]
+HRESULT WinMDAdapter::ReinterpretFieldSignature(
+ ULONG cbOrigSigBlob, // [IN] count of bytes in the original signature blob
+ PCCOR_SIGNATURE pOrigSig, // [IN] original signature
+ SigData **ppSigData // [OUT] new signature or SigData::NOREDIRECT
+)
+{
+ _ASSERTE(pOrigSig != NULL);
+ _ASSERTE(ppSigData != NULL);
+
+ HRESULT hr = S_OK;
+ BOOL fChangedSig = FALSE;
+
+ // The following implements FieldDef signature parsing, per ECMA CLI spec, section 23.2.4.
+ // Format is FIELD [custom modifiers]* Type
+ SigParser sigParser(pOrigSig, cbOrigSigBlob);
+ SigBuilder newSig(cbOrigSigBlob); // We will not change the signature size, just modify it a bit (E_T_CLASS <-> E_T_VALUETYPE)
+
+ // Read calling convention info - this should be IMAGE_CEE_CS_CALLCONV_FIELD.
+ ULONG callingConvention;
+ IfFailGo(sigParser.GetCallingConvInfo(&callingConvention));
+ _ASSERTE((callingConvention & 0xff) == callingConvention);
+ _ASSERTE(callingConvention == IMAGE_CEE_CS_CALLCONV_FIELD);
+ newSig.AppendByte((BYTE)callingConvention);
+
+ // Rewrite field type
+ IfFailGo(RewriteTypeInSignature(&sigParser, &newSig, &fChangedSig));
+
+ IfFailGo(FinalizeSignatureRewrite(newSig, fChangedSig, ppSigData DEBUG_ARG(cbOrigSigBlob)));
+ return S_OK;
+
+ErrExit:
+ Debug_ReportError("Couldn't parse a signature in WinMDAdapter::ReinterpretFieldSignature!");
+ return hr;
+} // WinMDAdapter::ReinterpretFieldSignature
+
+
+//------------------------------------------------------------------------------
+
+// Purpose: Translate TypeSpec signatures containing classes that we're projecting as value types, and vice versa.
+HRESULT WinMDAdapter::ReinterpretTypeSpecSignature(
+ ULONG cbOrigSigBlob, // [IN] count of bytes in the original signature blob
+ PCCOR_SIGNATURE pOrigSig, // [IN] original signature
+ SigData **ppSigData // [OUT] new signature or SigData::NOREDIRECT
+)
+{
+ _ASSERTE(pOrigSig != NULL);
+ _ASSERTE(ppSigData != NULL);
+
+ HRESULT hr = S_OK;
+ BOOL fChangedSig = FALSE;
+
+ // The following implements TypeSpec signature parsing, per ECMA CLI spec, section 23.2.14.
+ // Format is [custom modifiers]* Type
+ SigParser sigParser(pOrigSig, cbOrigSigBlob);
+ SigBuilder newSig(cbOrigSigBlob); // We will not change the signature size, just modify it a bit (E_T_CLASS <-> E_T_VALUETYPE)
+
+ // Rewrite the type
+ IfFailGo(RewriteTypeInSignature(&sigParser, &newSig, &fChangedSig));
+
+ IfFailGo(FinalizeSignatureRewrite(newSig, fChangedSig, ppSigData DEBUG_ARG(cbOrigSigBlob)));
+ return S_OK;
+
+ErrExit:
+ Debug_ReportError("Couldn't parse a signature in WinMDAdapter::ReinterpretTypeSpecSignature!");
+ return hr;
+} // WinMDAdapter::ReinterpretTypeSpecSignature
+
+
+//------------------------------------------------------------------------------
+
+// Purpose: Translate MethodSpec signatures containing classes that we're projecting as value types, and vice versa.
+HRESULT WinMDAdapter::ReinterpretMethodSpecSignature(
+ ULONG cbOrigSigBlob, // [IN] count of bytes in the original signature blob
+ PCCOR_SIGNATURE pOrigSig, // [IN] original signature
+ SigData **ppSigData // [OUT] new signature or SigData::NOREDIRECT
+)
+{
+ _ASSERTE(pOrigSig != NULL);
+ _ASSERTE(ppSigData != NULL);
+
+ HRESULT hr = S_OK;
+ BOOL fChangedSig = FALSE;
+
+ // The following implements MethodSpec signature parsing, per ECMA CLI spec, section 23.2.15.
+ // Format is GENERICINST GenArgCount Type+
+ SigParser sigParser(pOrigSig, cbOrigSigBlob);
+ SigBuilder newSig(cbOrigSigBlob); // We will not change the signature size, just modify it a bit (E_T_CLASS <-> E_T_VALUETYPE)
+
+ // Read calling convention info - this should be IMAGE_CEE_CS_CALLCONV_GENERICINST.
+ ULONG callingConvention;
+ IfFailGo(sigParser.GetCallingConvInfo(&callingConvention));
+ _ASSERTE((callingConvention & 0xff) == callingConvention);
+ _ASSERTE(callingConvention == IMAGE_CEE_CS_CALLCONV_GENERICINST);
+ newSig.AppendByte((BYTE)callingConvention);
+
+ // Read number of generic arguments
+ ULONG cArguments;
+ IfFailGo(sigParser.GetData(&cArguments));
+ newSig.AppendData(cArguments);
+
+ // Rewrite each argument
+ for (ULONG i = 0; i < cArguments; i++)
+ {
+ IfFailGo(RewriteTypeInSignature(&sigParser, &newSig, &fChangedSig));
+ }
+
+ IfFailGo(FinalizeSignatureRewrite(newSig, fChangedSig, ppSigData DEBUG_ARG(cbOrigSigBlob)));
+ return S_OK;
+
+ErrExit:
+ Debug_ReportError("Couldn't parse a signature in WinMDAdapter::ReinterpretMethodSpecSignature!");
+ return hr;
+} // WinMDAdapter::ReinterpretMethodSpecSignature
+
+
+//------------------------------------------------------------------------------
+//
+// We expose some WinRT types to managed as CLR types, while changing reference type <-> value type:
+// E_T_CLASS Windows.Foundation.IReference<T> ---> E_T_VALUETYPE System.Nullable<T>
+// E_T_CLASS Windows.Foundation.Collections.IKeyValuePair<U,V> ---> E_T_VALUETYPE System.Collections.Generic.KeyValuePair<U,V>
+// E_T_VALUETYPE Windows.UI.Xaml.Interop.TypeName ---> E_T_CLASS System.Type
+// E_T_VALUETYPE Windows.Foundation.HResult ---> E_T_CLASS System.Exception
+HRESULT WinMDAdapter::RewriteTypeInSignature(
+ SigParser * pSigParser,
+ SigBuilder * pSigBuilder,
+ BOOL * pfChangedSig)
+{
+ HRESULT hr;
+
+ BYTE elementType;
+ IfFailGo(pSigParser->GetByte(&elementType));
+
+ switch (elementType)
+ {
+ // Simple types with no additional data in the signature
+ case ELEMENT_TYPE_VOID:
+ case ELEMENT_TYPE_BOOLEAN:
+ case ELEMENT_TYPE_CHAR:
+ case ELEMENT_TYPE_I1:
+ case ELEMENT_TYPE_U1:
+ case ELEMENT_TYPE_I2:
+ case ELEMENT_TYPE_U2:
+ case ELEMENT_TYPE_I4:
+ case ELEMENT_TYPE_U4:
+ case ELEMENT_TYPE_I8:
+ case ELEMENT_TYPE_U8:
+ case ELEMENT_TYPE_R4:
+ case ELEMENT_TYPE_R8:
+ case ELEMENT_TYPE_STRING:
+ case ELEMENT_TYPE_I:
+ case ELEMENT_TYPE_U:
+ case ELEMENT_TYPE_OBJECT:
+ case ELEMENT_TYPE_TYPEDBYREF: // TYPEDREF (it takes no args) a typed reference to some other type
+ {
+ pSigBuilder->AppendByte(elementType);
+ break;
+ }
+
+ // Read a token
+ case ELEMENT_TYPE_CLASS:
+ {
+ mdToken token;
+ IfFailGo(pSigParser->GetToken(&token));
+
+ if (TypeFromToken(token) == mdtTypeRef)
+ {
+ RedirectedTypeIndex nRedirectedTypeIndex;
+ IfFailGo(this->GetTypeRefRedirectedInfo(token, &nRedirectedTypeIndex));
+ _ASSERTE((hr == S_OK) || (hr == S_FALSE));
+
+ if (hr == S_OK)
+ { // TypeRef is well known redirectetd type (with index in array code:g_rgRedirectedTypes)
+ if (nRedirectedTypeIndex == RedirectedTypeIndex_Windows_Foundation_IReference ||
+ nRedirectedTypeIndex == RedirectedTypeIndex_Windows_Foundation_Collections_IKeyValuePair)
+ { // The TypeRef name was changed to System.Nullable or System.Collections.Generic.KeyValuePair`2 (value type, not class)
+ elementType = ELEMENT_TYPE_VALUETYPE;
+ *pfChangedSig = TRUE;
+ }
+ }
+ // We do not want to return S_FALSE
+ hr = S_OK;
+ }
+
+ pSigBuilder->AppendByte(elementType);
+ pSigBuilder->AppendToken(token);
+
+ break;
+ }
+ case ELEMENT_TYPE_VALUETYPE:
+ {
+ mdToken token;
+ IfFailGo(pSigParser->GetToken(&token));
+
+ if (TypeFromToken(token) == mdtTypeRef)
+ {
+ RedirectedTypeIndex nRedirectedTypeIndex;
+ IfFailGo(this->GetTypeRefRedirectedInfo(token, &nRedirectedTypeIndex));
+ _ASSERTE((hr == S_OK) || (hr == S_FALSE));
+
+ if (hr == S_OK)
+ { // TypeRef is well known redirectetd type (with index in array code:g_rgRedirectedTypes)
+ if (nRedirectedTypeIndex == RedirectedTypeIndex_Windows_UI_Xaml_Interop_TypeName ||
+ nRedirectedTypeIndex == RedirectedTypeIndex_Windows_Foundation_HResult)
+ {
+ // TypeIdentifier and HResult are all value types in winmd and are mapped to reference
+ // types in CLR: Type, and Exception.
+ elementType = ELEMENT_TYPE_CLASS;
+ *pfChangedSig = TRUE;
+ }
+ }
+ // We do not want to return S_FALSE
+ hr = S_OK;
+ }
+
+ pSigBuilder->AppendByte(elementType);
+ pSigBuilder->AppendToken(token);
+
+ break;
+ }
+
+ // Read a type
+ case ELEMENT_TYPE_SZARRAY: // SZARRAY <type>
+ case ELEMENT_TYPE_PTR: // PTR <type>
+ case ELEMENT_TYPE_BYREF: // BYREF <type>
+ case ELEMENT_TYPE_SENTINEL: // sentinel for VARARGS ("..." in the parameter list), it behaves as prefix to next arg
+ {
+ pSigBuilder->AppendByte(elementType);
+
+ IfFailGo(RewriteTypeInSignature(pSigParser, pSigBuilder, pfChangedSig));
+ break;
+ }
+
+ // Read a token then a type. That type could be another custom modifier.
+ case ELEMENT_TYPE_CMOD_REQD: // required C modifier : E_T_CMOD_REQD <mdTypeRef/mdTypeDef> [followed by a type, or another custom modifier]
+ case ELEMENT_TYPE_CMOD_OPT: // optional C modifier : E_T_CMOD_OPT <mdTypeRef/mdTypeDef>
+ {
+ pSigBuilder->AppendByte(elementType);
+
+ mdToken token;
+ IfFailGo(pSigParser->GetToken(&token));
+ pSigBuilder->AppendToken(token);
+
+ // Process next type or custom modifier
+ IfFailGo(RewriteTypeInSignature(pSigParser, pSigBuilder, pfChangedSig));
+ break;
+ }
+
+ // Read a number
+ case ELEMENT_TYPE_VAR: // a class type variable VAR <number>
+ case ELEMENT_TYPE_MVAR: // a method type variable MVAR <number>
+ {
+ pSigBuilder->AppendByte(elementType);
+
+ ULONG number;
+ IfFailGo(pSigParser->GetData(&number));
+ pSigBuilder->AppendData(number);
+ break;
+ }
+
+ case ELEMENT_TYPE_ARRAY: // MDARRAY <type> <rank> <bcount> <bound1> ... <lbcount> <lb1> ...
+ {
+ pSigBuilder->AppendByte(elementType);
+
+ // Read array type
+ IfFailGo(RewriteTypeInSignature(pSigParser, pSigBuilder, pfChangedSig));
+
+ // Read rank
+ ULONG rank;
+ IfFailGo(pSigParser->GetData(&rank));
+ pSigBuilder->AppendData(rank);
+
+ // If rank is 0, then there's nothing else in the array signature
+ if (rank != 0)
+ {
+ // Read number of dimension sizes
+ ULONG cDimensionSizes;
+ IfFailGo(pSigParser->GetData(&cDimensionSizes));
+ pSigBuilder->AppendData(cDimensionSizes);
+
+ // Read all dimension sizes
+ for (ULONG i = 0; i < cDimensionSizes; i++)
+ {
+ ULONG dimensionSize;
+ IfFailGo(pSigParser->GetData(&dimensionSize));
+ pSigBuilder->AppendData(dimensionSize);
+ }
+
+ // Read number of lower bounds
+ ULONG cLowerBounds;
+ IfFailGo(pSigParser->GetData(&cLowerBounds));
+ pSigBuilder->AppendData(cLowerBounds);
+
+ // Read all lower bounds
+ for (ULONG i = 0; i < cLowerBounds; i++)
+ {
+ ULONG lowerBound;
+ IfFailGo(pSigParser->GetData(&lowerBound));
+ pSigBuilder->AppendData(lowerBound);
+ }
+ }
+ break;
+ }
+
+ case ELEMENT_TYPE_GENERICINST: // GENERICINST <generic type> <argCnt> <arg1> ... <argn>
+ {
+ pSigBuilder->AppendByte(elementType);
+
+ // Read the generic type
+ IfFailGo(RewriteTypeInSignature(pSigParser, pSigBuilder, pfChangedSig));
+
+ // Read arg count
+ ULONG cGenericTypeArguments;
+ IfFailGo(pSigParser->GetData(&cGenericTypeArguments));
+ pSigBuilder->AppendData(cGenericTypeArguments);
+
+ // Read each type argument
+ for (ULONG i = 0; i < cGenericTypeArguments; i++)
+ {
+ IfFailGo(RewriteTypeInSignature(pSigParser, pSigBuilder, pfChangedSig));
+ }
+ break;
+ }
+
+ case ELEMENT_TYPE_FNPTR: // FNPTR <complete sig for the function including calling convention>
+ /*
+ // FNPTR is not supported in C#/VB, thefore this is not a main scenario.
+ // This implementation was late during .NET 4.5, but may be useful in future releases when we decide to support more languages for managed WinMD implementation.
+ {
+ pSigBuilder->AppendByte(elementType);
+
+ // Read calling convention
+ DWORD callingConvention;
+ IfFailGo(pSigParser->GetData(&callingConvention));
+ pSigBuilder->AppendData(callingConvention);
+
+ // Read arg count
+ ULONG cArgs;
+ IfFailGo(pSigParser->GetData(&cArgs));
+ pSigBuilder->AppendData(cArgs);
+
+ // Read return argument
+ IfFailGo(RewriteTypeInSignature(pSigParser, pSigBuilder, pfChangedSig));
+
+ // Read each argument
+ for (ULONG i = 0; i < cArgs; i++)
+ {
+ IfFailGo(RewriteTypeInSignature(pSigParser, pSigBuilder, pfChangedSig));
+ }
+ break;
+ }
+ */
+ Debug_ReportError("ELEMENT_TYPE_FNPTR signature parsing in WinMD Adapter is NYI.");
+ IfFailGo(E_FAIL);
+
+ case ELEMENT_TYPE_END:
+ case ELEMENT_TYPE_INTERNAL: // INTERNAL <typehandle> (Only in ngen images, but not reachable from MetaData - no sig rewriting)
+ case ELEMENT_TYPE_PINNED: // PINNED <type>, used only in LocalSig (no sig rewriting)
+ Debug_ReportError("Unexpected CorElementType in a signature. Sig parsing failing.");
+ IfFailGo(E_FAIL);
+
+ default:
+ Debug_ReportError("Unknown CorElementType.");
+ IfFailGo(E_FAIL);
+ }
+ _ASSERTE(hr == S_OK);
+ return hr;
+
+ErrExit:
+ Debug_ReportError("Sig parsing failed.");
+ return hr;
+} // WinMDAdapter::RewriteTypeInSignature
+
+//------------------------------------------------------------------------------
+
+
+
+//---------------------------------------------------------------------------------
+// Windows.Foundation.Metadata.AttributeTarget and System.AttributeTarget enum
+// define different bits for everything (@todo: Be nice to change that before we ship.)
+// Do the conversion here.
+//---------------------------------------------------------------------------------
+static DWORD ConvertToClrAttributeTarget(DWORD winRTTarget)
+{
+ struct AttributeTargetsPair
+ {
+ DWORD WinRTValue;
+ DWORD ClrValue;
+ };
+
+ static const AttributeTargetsPair s_attributeTargetPairs[] =
+ {
+#define DEFINE_PROJECTED_TYPE(a,b,c,d,e,f,g,h,i)
+#define DEFINE_PROJECTED_ATTRIBUTETARGETS_VALUE(winrt, clr) { winrt, clr },
+#include "WinRTProjectedTypes.h"
+#undef DEFINE_PROJECTED_ATTRIBUTETARGETS_VALUES
+#undef DEFINE_PROJECTED_TYPE
+ };
+
+ if (winRTTarget == 0xffffffff /* Windows.Foundation.Metadata.AttributeTargets.All */)
+ return 0x00007fff; /* System.AttributeTargets.All */
+ DWORD clrTarget = 0;
+ for (UINT i = 0; i < sizeof(s_attributeTargetPairs)/sizeof(*s_attributeTargetPairs); i++)
+ {
+ if (winRTTarget & s_attributeTargetPairs[i].WinRTValue)
+ {
+ clrTarget |= s_attributeTargetPairs[i].ClrValue;
+ }
+ }
+ return clrTarget;
+}
+
+
+//------------------------------------------------------------------------------
+
+
+// Search a typeDef for WF.AttributeUsageAttribute and WF.AllowMultipleAttribute, and compute
+//
+// *pClrTargetValue - the equivalent System.AttributeTargets enum value
+// *pAllowMultiple - where multiple instances of the CA are allowed.
+//
+// Returns:
+// S_OK: a WF.AttributeUsageAttribute CA exists (this is the one that we will rewrite)
+// S_FALSE: no WF.AttributeUsageAttribute CA exists
+//
+HRESULT WinMDAdapter::TranslateWinMDAttributeUsageAttribute(mdTypeDef tkTypeDefOfCA, /*[out]*/ DWORD *pClrTargetValue, /*[out]*/ BOOL *pAllowMultiple)
+{
+ HRESULT hr;
+ _ASSERTE(TypeFromToken(tkTypeDefOfCA) == mdtTypeDef);
+ _ASSERTE(pClrTargetValue != NULL);
+ _ASSERTE(pAllowMultiple != NULL);
+
+ const BYTE *pbWFUsageBlob;
+ ULONG cbWFUsageBlob;
+ IfFailGo(m_pRawMetaModelCommonRO->CommonGetCustomAttributeByName(tkTypeDefOfCA, "Windows.Foundation.Metadata.AttributeUsageAttribute", (const void **)&pbWFUsageBlob, &cbWFUsageBlob));
+ if (hr == S_FALSE)
+ goto ErrExit;
+ // Expected blob format:
+ // 01 00 - Fixed prolog for CA's
+ // xx xx xx xx - The Windows.Foundation.Metadata.AttributeTarget value
+ // 00 00 - Indicates 0 name/value pairs following.
+ if (cbWFUsageBlob != 2 + sizeof(DWORD) + 2)
+ {
+ IfFailGo(COR_E_BADIMAGEFORMAT);
+ }
+ DWORD wfTargetValue = *(DWORD*)(pbWFUsageBlob + 2);
+ *pClrTargetValue = ConvertToClrAttributeTarget(wfTargetValue);
+
+ // add AttributeTargets.Method, AttributeTargets.Constructor , AttributeTargets.Property, and AttributeTargets.Event if this is the VersionAttribute
+ LPCSTR szNamespace;
+ LPCSTR szName;
+ IfFailGo(m_pRawMetaModelCommonRO->CommonGetTypeDefProps(tkTypeDefOfCA, &szNamespace, &szName, NULL, NULL, NULL));
+
+ if ((strcmp(szName, "VersionAttribute") == 0 || strcmp(szName, "DeprecatedAttribute") == 0) && strcmp(szNamespace, "Windows.Foundation.Metadata") == 0)
+ {
+ *pClrTargetValue |= 0x2E0;
+ }
+
+ const BYTE *pbWFAllowMultipleBlob;
+ ULONG cbWFAllowMultipleBlob;
+ IfFailGo(m_pRawMetaModelCommonRO->CommonGetCustomAttributeByName(tkTypeDefOfCA, "Windows.Foundation.Metadata.AllowMultipleAttribute", (const void **)&pbWFAllowMultipleBlob, &cbWFAllowMultipleBlob));
+ *pAllowMultiple = (hr == S_OK);
+ hr = S_OK;
+
+ ErrExit:
+ return hr;
+}
+
+//------------------------------------------------------------------------------
+
+/*static*/ HRESULT WinMDAdapter::CreateClrAttributeUsageAttributeCABlob(DWORD clrTargetValue, BOOL allowMultiple, CABlob **ppCABlob)
+{
+ // Emit the blob format corresponding to:
+ // [System.AttributeUsage(System.AttributeTargets.xx, AllowMultiple=yy)]
+ //
+ // 01 00 - Fixed prolog for CA's
+ // xx xx xx xx - The System.AttributeTarget value
+ // 01 00 - Indicates 1 name/value pair following.
+ // 54 - SERIALIZATION_TYPE_PROPERTY
+ // 02 - ELEMENT_TYPE_BOOLEAN
+ // 0d - strlen("AllowMultiple") - 1
+ // 41 6c ... 65 - "A" "l" "l" "o" "w" "M" "u" "l" "t" "i" "p" "l" "e"
+ // yy - The boolean selection for "AllowMultiple"
+
+ BYTE blob[] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x54, 0x02, 0x0D, 0x41, 0x6C, 0x6C, 0x6F, 0x77, 0x4D, 0x75, 0x6C, 0x74, 0x69, 0x70, 0x6C, 0x65, 0x00 };
+ blob[sizeof(blob) - 1] = allowMultiple ? 1 : 0;
+ *((DWORD*)(blob+2)) = clrTargetValue;
+ CABlob *pCABlob;
+ IfNullRet(pCABlob = CABlob::Create(blob, sizeof(blob)));
+ *ppCABlob = pCABlob;
+ return S_OK;
+}
+
+
+//------------------------------------------------------------------------------
+
+// Gets Guid from Windows.Foundation.Metadata.Guid
+HRESULT WinMDAdapter::GetItemGuid(mdToken tkObj, CLSID *pGuid)
+{
+ HRESULT hr;
+ _ASSERTE(pGuid);
+ *pGuid = GUID_NULL;
+ const BYTE *pBlob;
+ ULONG cbBlob;
+ IfFailGo(m_pRawMetaModelCommonRO->CommonGetCustomAttributeByName(tkObj, "Windows.Foundation.Metadata.GuidAttribute", (const void**)&pBlob, &cbBlob));
+ if (hr == S_OK)
+ {
+ if (cbBlob == 2 + sizeof(GUID) + 2)
+ {
+ memcpy(pGuid, pBlob + 2, sizeof(GUID));
+ hr = S_OK;
+ goto ErrExit;
+ }
+ }
+ hr = S_FALSE;
+ ErrExit:
+ return hr;
+
+}
+
+
+//------------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+// Gets filtered methodImpl list and adds it to an existing DynamicArray enum.
+//
+// This is used to hide implementations of methods on redirected interfaces after
+// we've replaced them with their CLR counterparts in the interface implementation list.
+//
+// Each filtered methodImpl adds two elements to the enum: the body and decl values
+// in that order.
+//----------------------------------------------------------------------------
+HRESULT WinMDAdapter::AddMethodImplsToEnum(mdTypeDef tkTypeDef, HENUMInternal *henum)
+{
+ _ASSERTE(henum != NULL);
+ _ASSERTE(henum->m_EnumType == MDDynamicArrayEnum);
+ _ASSERTE(TypeFromToken(tkTypeDef) == mdtTypeDef);
+
+ HRESULT hr;
+
+ mdToken tkMethodImplFirst;
+ ULONG count;
+ IfFailGo(m_pRawMetaModelCommonRO->CommonGetMethodImpls(tkTypeDef, &tkMethodImplFirst, &count));
+ for (ULONG i = 0; i < count; i++)
+ {
+ mdToken tkMethodImpl = tkMethodImplFirst + i;
+ mdToken tkBody, tkDecl;
+ IfFailGo(m_pRawMetaModelCommonRO->CommonGetMethodImplProps(tkMethodImpl, &tkBody, &tkDecl));
+ UINT nIndex;
+ IfFailGo(CheckIfMethodImplImplementsARedirectedInterface(tkDecl, &nIndex));
+ if (hr == S_FALSE ||
+ (SUCCEEDED(hr) && nIndex == WinMDAdapter::RedirectedTypeIndex_Windows_Foundation_IClosable))
+ {
+ // Keep MethodImpl for IClosable methods and non-redirected interfaces
+ IfFailGo(HENUMInternal::AddElementToEnum(henum, tkBody));
+ IfFailGo(HENUMInternal::AddElementToEnum(henum, tkDecl));
+ }
+ }
+
+ hr = S_OK;
+ ErrExit:
+ return hr;
+}
+
+//------------------------------------------------------------------------------
+
+// S_OK if this is a CLR implementation type that was mangled and hidden by WinMDExp
+//
+// Logically, this function takes a mdTypeDef, but since the caller has already extracted the
+// row data for other purposes, we'll take the row data.
+HRESULT WinMDAdapter::CheckIfClrImplementationType(LPCSTR szName, DWORD dwAttr, LPCSTR *pszUnmangledName)
+{
+ if (m_scenario != kWinMDExp)
+ return S_FALSE; // Input file not produced by WinMDExp
+ if (IsTdNested(dwAttr))
+ return S_FALSE; // Type is nested in another type
+ if ((dwAttr & (tdPublic|tdSpecialName)) != tdSpecialName)
+ return S_FALSE; // Type public or not SpecialName
+ if (0 != strncmp(szName, s_szCLRPrefix, s_ncCLRPrefix))
+ return S_FALSE; // Name does not begin with "<CLR>"
+
+ // Ran out of reasons.
+ *pszUnmangledName = szName + s_ncCLRPrefix;
+ return S_OK;
+}
+
+
+//------------------------------------------------------------------------------
+
+//-------------------------------------------------------------------------------------
+// Returns: S_OK if tkDecl of a methodImpl is a reference to a method on a redirected interface.
+//-------------------------------------------------------------------------------------
+HRESULT WinMDAdapter::CheckIfMethodImplImplementsARedirectedInterface(mdToken tkDecl, UINT *pIndex)
+{
+
+ HRESULT hr;
+ if (TypeFromToken(tkDecl) != mdtMemberRef)
+ return S_FALSE; // REX will always use memberRef and typeRefs to refer to redirected interfaces, even if in same module.
+
+ mdToken tkParent;
+ IfFailRet(m_pRawMetaModelCommonRO->CommonGetMemberRefProps(tkDecl, &tkParent));
+
+ mdTypeRef tkTypeRef;
+ if (TypeFromToken(tkParent) == mdtTypeRef)
+ {
+ tkTypeRef = tkParent;
+ }
+ else if (TypeFromToken(tkParent) == mdtTypeSpec)
+ {
+ PCCOR_SIGNATURE pvSig;
+ ULONG cbSig;
+ IfFailRet(m_pRawMetaModelCommonRO->CommonGetTypeSpecProps(tkParent, &pvSig, &cbSig));
+ static const BYTE expectedSigStart[] = {ELEMENT_TYPE_GENERICINST, ELEMENT_TYPE_CLASS};
+ if (cbSig < sizeof(expectedSigStart) + 1)
+ return S_FALSE;
+ if (0 != memcmp(pvSig, expectedSigStart, sizeof(expectedSigStart)))
+ return S_FALSE;
+ const BYTE *pCodedToken = pvSig + sizeof(expectedSigStart);
+ if (cbSig < sizeof(expectedSigStart) + CorSigUncompressedDataSize(pCodedToken))
+ return S_FALSE;
+ mdToken genericType = CorSigUncompressToken(/*modifies*/pCodedToken);
+ if (TypeFromToken(genericType) != mdtTypeRef)
+ return S_FALSE;
+ tkTypeRef = genericType;
+ }
+ else
+ {
+ return S_FALSE;
+ }
+
+ ULONG treatment;
+ IfFailRet(GetTypeRefTreatment(tkTypeRef, &treatment));
+ if ((treatment & kTrClassMask) != kTrClassWellKnownRedirected)
+ return S_FALSE;
+
+ if (pIndex)
+ *pIndex = (treatment & ~kTrClassMask);
+
+ return S_OK;
+}
+
+//-----------------------------------------------------------------------------------------------------
+
+/*static*/ HRESULT WinMDAdapter::CreatePrefixedName(LPCSTR szPrefix, LPCSTR szName, LPCSTR *ppOut)
+{
+ // This can cause allocations (thus entering the host) during a profiler stackwalk.
+ // But we're ok since we're not supporting SQL/F1 profiling with WinMDs. FUTURE:
+ // Would be nice to eliminate allocations on stack walks regardless.
+ PERMANENT_CONTRACT_VIOLATION(HostViolation, ReasonUnsupportedForSQLF1Profiling);
+
+ size_t ncPrefix = strlen(szPrefix);
+ size_t ncName = strlen(szName);
+ if (ncPrefix + ncName < ncPrefix || ncPrefix + ncName + 1 < ncPrefix + ncName)
+ return E_OUTOFMEMORY;
+ LPSTR szResult = new (nothrow) char[ncPrefix + ncName + 1];
+ IfNullRet(szResult);
+ memcpy(szResult, szPrefix, ncPrefix);
+ memcpy(szResult + ncPrefix, szName, ncName);
+ szResult[ncPrefix + ncName] = '\0';
+ *ppOut = szResult;
+ return S_OK;
+}
+
+//-----------------------------------------------------------------------------------------------------
+
+// Sentinel value in m_redirectedCABlobsMemoTable table. Means "do no blob rewriting. Return the one from the underlying importer."
+/*static*/ WinMDAdapter::CABlob * const WinMDAdapter::CABlob::NOREDIRECT = ((WinMDAdapter::CABlob *)(0x1));
+
+//-----------------------------------------------------------------------------------------------------
+
+/*static*/ WinMDAdapter::CABlob* WinMDAdapter::CABlob::Create(const BYTE *pBlob, ULONG cbBlob)
+{
+ // This can cause allocations (thus entering the host) during a profiler stackwalk.
+ // But we're ok since we're not supporting SQL/F1 profiling with WinMDs. FUTURE:
+ // Would be nice to eliminate allocations on stack walks regardless.
+ PERMANENT_CONTRACT_VIOLATION(HostViolation, ReasonUnsupportedForSQLF1Profiling);
+
+ size_t cbAlloc = sizeof(CABlob) + cbBlob; // This overestimates the needed size a bit - no biggie
+ if (cbAlloc < sizeof(CABlob))
+ return NULL;
+
+ CABlob *pNewCABlob = (CABlob*)(new (nothrow) BYTE[cbAlloc]);
+ if (!pNewCABlob)
+ return NULL;
+
+ pNewCABlob->cbBlob = cbBlob;
+ memcpy(pNewCABlob->data, pBlob, cbBlob);
+ return pNewCABlob;
+}
+
+//-----------------------------------------------------------------------------------------------------
+
+/*static*/ void WinMDAdapter::CABlob::Destroy(WinMDAdapter::CABlob *pCABlob)
+{
+ if (pCABlob != CABlob::NOREDIRECT)
+ delete [] (BYTE*)pCABlob;
+}
+
+//-----------------------------------------------------------------------------------------------------
+
+// Sentinel value in m_redirectedMethodSigMemoTable or m_redirectedFieldMemoTable.
+// Means "do no signature rewriting. Return the one from the underlying importer."
+/*static*/ WinMDAdapter::SigData * const WinMDAdapter::SigData::NOREDIRECT = ((WinMDAdapter::SigData *)(0x1));
+
+//-----------------------------------------------------------------------------------------------------
+
+/*static*/ WinMDAdapter::SigData* WinMDAdapter::SigData::Create(ULONG cbSig, PCCOR_SIGNATURE pSig)
+{
+ // This can cause allocations (thus entering the host) during a profiler stackwalk.
+ // But we're ok since we're not supporting SQL/F1 profiling with WinMDs. FUTURE:
+ // Would be nice to eliminate allocations on stack walks regardless.
+ PERMANENT_CONTRACT_VIOLATION(HostViolation, ReasonUnsupportedForSQLF1Profiling);
+
+ _ASSERTE(pSig != NULL);
+ size_t cbAlloc = sizeof(SigData) + cbSig; // This overestimates the needed size a bit - no biggie
+ if (cbAlloc < sizeof(SigData))
+ return NULL;
+
+ SigData *pNewSigData = (SigData*)(new (nothrow) BYTE[cbAlloc]);
+ if (!pNewSigData)
+ return NULL;
+
+ pNewSigData->cbSig = cbSig;
+ memcpy(pNewSigData->data, pSig, cbSig);
+ return pNewSigData;
+}
+
+//-----------------------------------------------------------------------------------------------------
+
+/*static*/ void WinMDAdapter::SigData::Destroy(WinMDAdapter::SigData *pSigData)
+{
+ if (pSigData != SigData::NOREDIRECT)
+ delete [] (BYTE*)pSigData;
+}
+
+//-----------------------------------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------------------------------
+// S_OK if pUnknown is really a WinMD wrapper. This is just a polite way of asking "is it bad to
+// to static cast pUnknown to RegMeta/MDInternalRO."
+//-----------------------------------------------------------------------------------------------------
+HRESULT CheckIfImportingWinMD(IUnknown *pUnknown)
+{
+ IUnknown *pIgnore = NULL;
+ HRESULT hr = pUnknown->QueryInterface(IID_IWinMDImport, (void**)&pIgnore);
+ if (hr == S_OK)
+ {
+ pIgnore->Release();
+ }
+ if (hr == E_NOINTERFACE)
+ {
+ hr = S_FALSE;
+ }
+ return hr;
+}
+
+
+//-----------------------------------------------------------------------------------------------------
+// E_NOTIMPL if pUnknown is really a WinMD wrapper.
+//-----------------------------------------------------------------------------------------------------
+HRESULT VerifyNotWinMDHelper(IUnknown *pUnknown
+#ifdef _DEBUG
+ ,LPCSTR assertMsg
+ ,LPCSTR file
+ ,int line
+#endif //_DEBUG
+ )
+{
+ HRESULT hr = CheckIfImportingWinMD(pUnknown);
+ if (FAILED(hr))
+ return hr;
+ if (hr == S_FALSE)
+ {
+ return S_OK;
+ }
+#ifdef _DEBUG
+#ifndef DACCESS_COMPILE
+ if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_MD_WinMD_AssertOnIllegalUsage))
+ {
+ DbgAssertDialog(file, line, assertMsg);
+ }
+#endif
+#endif
+ return E_NOTIMPL;
+}
+
+
+
diff --git a/src/md/winmd/crossgen/.gitmirror b/src/md/winmd/crossgen/.gitmirror
new file mode 100644
index 0000000000..f507630f94
--- /dev/null
+++ b/src/md/winmd/crossgen/.gitmirror
@@ -0,0 +1 @@
+Only contents of this folder, excluding subfolders, will be mirrored by the Git-TFS Mirror. \ No newline at end of file
diff --git a/src/md/winmd/crossgen/CMakeLists.txt b/src/md/winmd/crossgen/CMakeLists.txt
new file mode 100644
index 0000000000..30859c30ae
--- /dev/null
+++ b/src/md/winmd/crossgen/CMakeLists.txt
@@ -0,0 +1,5 @@
+include(${CLR_DIR}/crossgen.cmake)
+include(../../md_wks.cmake)
+
+add_precompiled_header(stdafx.h ../stdafx.cpp MDWINMD_SOURCES)
+add_library_clr(mdwinmd_crossgen ${MDWINMD_SOURCES})
diff --git a/src/md/winmd/crossgen/MDWinMD_crossgen.nativeproj b/src/md/winmd/crossgen/MDWinMD_crossgen.nativeproj
new file mode 100644
index 0000000000..88520924f6
--- /dev/null
+++ b/src/md/winmd/crossgen/MDWinMD_crossgen.nativeproj
@@ -0,0 +1,14 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="dogfood">
+ <PropertyGroup>
+ <!-- All features are set in file:..\..\MD.props -->
+ <MetadataFlavor>wks</MetadataFlavor>
+ <OutputName>mdwinmd_crossgen</OutputName>
+ </PropertyGroup>
+
+ <!--Import the settings-->
+ <Import Project="$(_NTDRIVE)$(_NTROOT)\ndp\clr\xplat\SetCrossGen.props" />
+ <Import Project="$(_NTDRIVE)$(_NTROOT)\ndp\clr\src\MD\WinMD\WinMD.settings.targets" />
+
+ <!--Import the targets-->
+ <Import Project="$(_NTDRIVE)$(_NTROOT)\ndp\clr\clr.targets" />
+</Project>
diff --git a/src/md/winmd/dac/.gitmirror b/src/md/winmd/dac/.gitmirror
new file mode 100644
index 0000000000..f507630f94
--- /dev/null
+++ b/src/md/winmd/dac/.gitmirror
@@ -0,0 +1 @@
+Only contents of this folder, excluding subfolders, will be mirrored by the Git-TFS Mirror. \ No newline at end of file
diff --git a/src/md/winmd/dac/CMakeLists.txt b/src/md/winmd/dac/CMakeLists.txt
new file mode 100644
index 0000000000..aca5cb581d
--- /dev/null
+++ b/src/md/winmd/dac/CMakeLists.txt
@@ -0,0 +1,6 @@
+
+include(${CLR_DIR}/dac.cmake)
+include(../../md_dbi.cmake)
+
+add_precompiled_header(stdafx.h ../stdafx.cpp MDWINMD_SOURCES)
+add_library_clr(mdwinmd_dac ${MDWINMD_SOURCES})
diff --git a/src/md/winmd/dac/dirs.proj b/src/md/winmd/dac/dirs.proj
new file mode 100644
index 0000000000..c73e2390db
--- /dev/null
+++ b/src/md/winmd/dac/dirs.proj
@@ -0,0 +1,19 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <!--Import the settings-->
+ <Import Project="$(_NTDRIVE)$(_NTROOT)\ndp\clr\clr.props" />
+
+ <PropertyGroup>
+ <BuildInPhase1>true</BuildInPhase1>
+ <BuildInPhaseDefault>false</BuildInPhaseDefault>
+ <BuildCoreBinaries>true</BuildCoreBinaries>
+ <BuildSysBinaries>true</BuildSysBinaries>
+ </PropertyGroup>
+
+ <!--The following projects will build during PHASE 1-->
+ <ItemGroup Condition="'$(BuildExePhase)' == '1'">
+ <ProjectFile Include="HostLocal\mdwinmd_dac.nativeproj" />
+ </ItemGroup>
+
+ <!--Import the targets-->
+ <Import Project="$(_NTDRIVE)$(_NTROOT)\tools\Microsoft.DevDiv.Traversal.targets" />
+</Project>
diff --git a/src/md/winmd/dbi/.gitmirror b/src/md/winmd/dbi/.gitmirror
new file mode 100644
index 0000000000..f507630f94
--- /dev/null
+++ b/src/md/winmd/dbi/.gitmirror
@@ -0,0 +1 @@
+Only contents of this folder, excluding subfolders, will be mirrored by the Git-TFS Mirror. \ No newline at end of file
diff --git a/src/md/winmd/dbi/CMakeLists.txt b/src/md/winmd/dbi/CMakeLists.txt
new file mode 100644
index 0000000000..89a39d3d9b
--- /dev/null
+++ b/src/md/winmd/dbi/CMakeLists.txt
@@ -0,0 +1,4 @@
+include(../../md_dbi.cmake)
+
+add_precompiled_header(stdafx.h ../stdafx.cpp MDWINMD_SOURCES)
+add_library_clr(mdwinmd_dbi ${MDWINMD_SOURCES}) \ No newline at end of file
diff --git a/src/md/winmd/dbi/MDWinMD-dbi.props b/src/md/winmd/dbi/MDWinMD-dbi.props
new file mode 100644
index 0000000000..829e1d7c6d
--- /dev/null
+++ b/src/md/winmd/dbi/MDWinMD-dbi.props
@@ -0,0 +1,9 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="dogfood">
+ <PropertyGroup>
+ <!-- All features are set in file:..\..\MD.props -->
+ <MetadataFlavor>mscordbi</MetadataFlavor>
+ </PropertyGroup>
+
+ <Import Project="$(_NTDRIVE)$(_NTROOT)\ndp\clr\src\MD\WinMD\WinMD.settings.targets" />
+
+</Project>
diff --git a/src/md/winmd/dbi/MDWinMD_dbi.nativeproj b/src/md/winmd/dbi/MDWinMD_dbi.nativeproj
new file mode 100644
index 0000000000..3223689415
--- /dev/null
+++ b/src/md/winmd/dbi/MDWinMD_dbi.nativeproj
@@ -0,0 +1,17 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="dogfood">
+ <PropertyGroup>
+ <!-- All features are set in file:..\..\MD.props -->
+ <MetadataFlavor>mscordbi</MetadataFlavor>
+ </PropertyGroup>
+
+ <Import Project="$(_NTDRIVE)$(_NTROOT)\ndp\clr\src\MD\WinMD\WinMD.settings.targets" />
+
+ <PropertyGroup>
+ <BuildCoreBinaries>true</BuildCoreBinaries>
+ <BuildSysBinaries>true</BuildSysBinaries>
+ <OutputName>MDWinMD_dbi</OutputName>
+ </PropertyGroup>
+
+ <!--Import the targets-->
+ <Import Project="$(_NTDRIVE)$(_NTROOT)\ndp\clr\clr.targets" />
+</Project>
diff --git a/src/md/winmd/dbi/dirs.proj b/src/md/winmd/dbi/dirs.proj
new file mode 100644
index 0000000000..88863b561f
--- /dev/null
+++ b/src/md/winmd/dbi/dirs.proj
@@ -0,0 +1,19 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <!--Import the settings-->
+ <Import Project="$(_NTDRIVE)$(_NTROOT)\ndp\clr\clr.props" />
+
+ <PropertyGroup>
+ <BuildInPhase1>true</BuildInPhase1>
+ <BuildInPhaseDefault>false</BuildInPhaseDefault>
+ <BuildCoreBinaries>true</BuildCoreBinaries>
+ <BuildSysBinaries>true</BuildSysBinaries>
+ </PropertyGroup>
+
+ <!--The following projects will build during PHASE 1-->
+ <ItemGroup Condition="'$(BuildExePhase)' == '1'">
+ <ProjectFile Condition="'$(FeatureDbiDebugging)'=='true'" Include="HostLocal\MDWinMD-dbi.nativeproj" />
+ </ItemGroup>
+
+ <!--Import the targets-->
+ <Import Project="$(_NTDRIVE)$(_NTROOT)\tools\Microsoft.DevDiv.Traversal.targets" />
+</Project>
diff --git a/src/md/winmd/dirs.proj b/src/md/winmd/dirs.proj
new file mode 100644
index 0000000000..7788116cc7
--- /dev/null
+++ b/src/md/winmd/dirs.proj
@@ -0,0 +1,21 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <!--Import the settings-->
+ <Import Project="$(_NTDRIVE)$(_NTROOT)\ndp\clr\clr.props" />
+
+ <PropertyGroup>
+ <BuildInPhase1>true</BuildInPhase1>
+ <BuildInPhaseDefault>false</BuildInPhaseDefault>
+ <BuildCoreBinaries>true</BuildCoreBinaries>
+ <BuildSysBinaries>true</BuildSysBinaries>
+ </PropertyGroup>
+
+ <!--The following projects will build during PHASE 1-->
+ <ItemGroup Condition="'$(BuildExePhase)' == '1'">
+ <ProjectFile Include="wks\mdwinmd_wks.nativeproj" />
+ <ProjectFile Include="dbi\dirs.proj" />
+ <ProjectFile Include="dac\dirs.proj" />
+ </ItemGroup>
+
+ <!--Import the targets-->
+ <Import Project="$(_NTDRIVE)$(_NTROOT)\tools\Microsoft.DevDiv.Traversal.targets" />
+</Project>
diff --git a/src/md/winmd/inc/.gitmirror b/src/md/winmd/inc/.gitmirror
new file mode 100644
index 0000000000..f507630f94
--- /dev/null
+++ b/src/md/winmd/inc/.gitmirror
@@ -0,0 +1 @@
+Only contents of this folder, excluding subfolders, will be mirrored by the Git-TFS Mirror. \ No newline at end of file
diff --git a/src/md/winmd/inc/adapter.h b/src/md/winmd/inc/adapter.h
new file mode 100644
index 0000000000..e69b620938
--- /dev/null
+++ b/src/md/winmd/inc/adapter.h
@@ -0,0 +1,951 @@
+// 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.
+#ifndef __MDWinMDAdapter__h__
+#define __MDWinMDAdapter__h__
+
+#include "memotable.h"
+#include "../../inc/winmdinterfaces.h"
+#include "thekey.h"
+#include "ecmakey.h"
+
+// Instantiation of template in holder.h
+template void DoNothing<ULONG>(ULONG);
+
+class SigBuilder;
+class SigParser;
+
+typedef const BYTE * PCBYTE;
+static const BYTE s_pbContractPublicKeyToken[] = {0xB0,0x3F,0x5F,0x7F,0x11,0xD5,0x0A,0x3A};
+static const BYTE s_pbContractPublicKey[] = {0x00, 0x24, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x06, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x52, 0x53, 0x41, 0x31, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x07, 0xD1, 0xFA, 0x57, 0xC4, 0xAE, 0xD9, 0xF0, 0xA3, 0x2E, 0x84, 0xAA, 0x0F, 0xAE, 0xFD, 0x0D, 0xE9, 0xE8, 0xFD, 0x6A, 0xEC, 0x8F, 0x87, 0xFB, 0x03, 0x76, 0x6C, 0x83, 0x4C, 0x99, 0x92, 0x1E, 0xB2, 0x3B, 0xE7, 0x9A, 0xD9, 0xD5, 0xDC, 0xC1, 0xDD, 0x9A, 0xD2, 0x36, 0x13, 0x21, 0x02, 0x90, 0x0B, 0x72, 0x3C, 0xF9, 0x80, 0x95, 0x7F, 0xC4, 0xE1, 0x77, 0x10, 0x8F, 0xC6, 0x07, 0x77, 0x4F, 0x29, 0xE8, 0x32, 0x0E, 0x92, 0xEA, 0x05, 0xEC, 0xE4, 0xE8, 0x21, 0xC0, 0xA5, 0xEF, 0xE8, 0xF1, 0x64, 0x5C, 0x4C, 0x0C, 0x93, 0xC1, 0xAB, 0x99, 0x28, 0x5D, 0x62, 0x2C, 0xAA, 0x65, 0x2C, 0x1D, 0xFA, 0xD6, 0x3D, 0x74, 0x5D, 0x6F, 0x2D, 0xE5, 0xF1, 0x7E, 0x5E, 0xAF, 0x0F, 0xC4, 0x96, 0x3D, 0x26, 0x1C, 0x8A, 0x12, 0x43, 0x65, 0x18, 0x20, 0x6D, 0xC0, 0x93, 0x34, 0x4D, 0x5A, 0xD2, 0x93};
+
+class DECLSPEC_UUID("996AA908-5606-476d-9985-48607B2DA076") IWinMDImport : public IUnknown
+{
+public :
+ STDMETHOD(IsScenarioWinMDExp)(BOOL *pbResult) = 0;
+ STDMETHOD(IsRuntimeClassImplementation)(mdTypeDef tkTypeDef, BOOL *pbResult) = 0;
+};
+
+//========================================================================================
+// Only IWinMDImport and IWinMDImportInternalRO QI successfully for this guid - for cases where we need to
+// tell the difference between the classic MD importers and the WinMD wrappers.
+//========================================================================================
+// {996AA908-5606-476d-9985-48607B2DA076}
+extern const IID DECLSPEC_SELECTANY IID_IWinMDImport = __uuidof(IWinMDImport);
+
+//========================================================================================
+// Popup an assert box if COMPLUS_MD_WinMD_AssertOnIllegalUsage=1
+//========================================================================================
+#if defined(_DEBUG) && !defined(DACCESS_COMPILE)
+#define WINMD_COMPAT_ASSERT(assertMsg) if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_MD_WinMD_AssertOnIllegalUsage)) DbgAssertDialog(__FILE__, __LINE__, assertMsg)
+#else
+#define WINMD_COMPAT_ASSERT(assertMsg)
+#endif
+
+
+//========================================================================================
+// class WinMDAdapter
+//
+// This object performs typeref redirection and any other chores involved in
+// masquerading WinMD files as .NET assemblies.
+//
+// WinMDAdapters act as internal helper objects to WinMDImport and WinMDInternalImportRO
+// and factor out as much common code as is practical given that these two importers
+// expose wildly different interfaces.
+//
+// The main input to this object is a standard .NET metadata importer (the "raw" importer.) Since
+// the two importers have no common public interface, we use the internal (non-COM) IMetaModelCommon
+// interface that both imports have internally and expose through the private IMDCommon
+// interface.
+//
+// Methods on this class follow the IMDInternalImport philosophy (i.e. validation? what validation?,
+// return strings as direct UTF8 pointers to internal strings allocated for the lifetime
+// of WinMDAdapter.) When used by the public IMetaDataImport adapter, it's important that the caller
+// validate parameters before invoking WinMDAdapter.
+//========================================================================================
+class WinMDAdapter
+{
+public:
+#define DEFINE_PROJECTED_TYPE(szWinRTNS, szWinRTName, szClrNS, szClrName, ClrAsmIdx, nContractAsmIdx, WinRTIndex, ClrIndex, TypeKind) \
+ RedirectedTypeIndex_ ## WinRTIndex, \
+ RedirectedTypeIndex_ ## ClrIndex = RedirectedTypeIndex_ ## WinRTIndex, \
+
+ // Indexes of well-known redirected types into array code:g_rgRedirectedTypes
+ enum RedirectedTypeIndex
+ {
+#include "WinRTProjectedTypes.h"
+ RedirectedTypeIndex_Count,
+ RedirectedTypeIndex_Invalid = -1,
+ };
+#undef DEFINE_PROJECTED_TYPE
+
+ enum FrameworkAssemblyIndex
+ {
+ FrameworkAssembly_Mscorlib,
+ FrameworkAssembly_SystemObjectModel,
+ FrameworkAssembly_SystemRuntime,
+ FrameworkAssembly_SystemRuntimeWindowsRuntime,
+ FrameworkAssembly_SystemRuntimeWindowsRuntimeUIXaml,
+ FrameworkAssembly_SystemNumericsVectors,
+
+ FrameworkAssembly_Count,
+ };
+
+ // If new contract assemblies need to be added, they must be appended to the end of the following list.
+ // Also, don't remove or change any existing assemblies in this list.
+ // Not following these rules will break existing MDIL images generated in the Store.
+ enum ContractAssemblyIndex
+ {
+ ContractAssembly_SystemRuntime,
+ ContractAssembly_SystemRuntimeInteropServicesWindowsRuntime,
+ ContractAssembly_SystemObjectModel,
+ ContractAssembly_SystemRuntimeWindowsRuntime,
+ ContractAssembly_SystemRuntimeWindowsRuntimeUIXaml,
+ ContractAssembly_SystemNumericsVectors, // GetExtraAssemblyRefCount assumes SystemNumericsVectors is the last assembly.
+ // If you add an assembly you must update GetActualExtraAssemblyRefCount.
+
+ ContractAssembly_Count,
+ };
+
+
+ enum WinMDTypeKind
+ {
+ WinMDTypeKind_Attribute,
+ WinMDTypeKind_Enum,
+ WinMDTypeKind_Delegate,
+ WinMDTypeKind_Interface,
+ WinMDTypeKind_PDelegate,
+ WinMDTypeKind_PInterface,
+ WinMDTypeKind_Struct,
+ WinMDTypeKind_Runtimeclass,
+ };
+
+ int GetExtraAssemblyRefCount();
+
+ // Factory and destructor
+ static HRESULT Create(IMDCommon *pRawMDCommon, /*[out]*/ WinMDAdapter **ppAdapter);
+ ~WinMDAdapter();
+
+ // Map a well-known WinRT typename to CLR typename
+ static BOOL ConvertWellKnownTypeNameFromWinRTToClr(LPCSTR *pszNamespace, LPCSTR *pszName);
+
+ // Map a well-known WinRT full typename to CLR full typename
+ static BOOL ConvertWellKnownFullTypeNameFromWinRTToClr(LPCWSTR *pszFullName, RedirectedTypeIndex *pIndex);
+
+ // Map a well-known CLR typename to WinRT typename
+ static BOOL ConvertWellKnownTypeNameFromClrToWinRT(LPCSTR *pszFullName);
+
+ // Map a well-known CLR typename to WinRT typename
+ static BOOL WinMDAdapter::ConvertWellKnownTypeNameFromClrToWinRT(LPCSTR *pszNamespace, LPCSTR *pszName);
+
+ // Returns names of redirected type 'index'.
+ static void GetRedirectedTypeInfo(
+ RedirectedTypeIndex index,
+ LPCSTR * pszClrNamespace,
+ LPCSTR * pszClrName,
+ LPCSTR * pszFullWinRTName,
+ FrameworkAssemblyIndex * pFrameworkAssemblyIdx,
+ ContractAssemblyIndex * pContractAssemblyIdx,
+ WinMDTypeKind * pWinMDTypeKind);
+
+ // Returns name of redirected type 'index'.
+ static LPCWSTR GetRedirectedTypeFullWinRTName(RedirectedTypeIndex index);
+ static LPCSTR GetRedirectedTypeFullCLRName(RedirectedTypeIndex index);
+
+ // Returns renamed typedefs
+ HRESULT GetTypeDefProps(
+ mdTypeDef typeDef, // [IN] given typedef
+ LPCUTF8 *pszNameSpace, // [OUT] return typedef namespace
+ LPCUTF8 *pszName, // [OUT] return typedef name
+ DWORD *pdwFlags, // [OUT] return typedef flags
+ mdToken *ptkExtends // [OUT] Put base class TypeDef/TypeRef here.
+ );
+
+ // Find TypeDef by name
+ HRESULT FindTypeDef(
+ LPCSTR szTypeDefNamespace, // [IN] Namespace for the TypeDef.
+ LPCSTR szTypeDefName, // [IN] Name of the TypeDef.
+ mdToken tkEnclosingClass, // [IN] TypeDef/TypeRef of enclosing class.
+ mdTypeDef * ptkTypeDef // [OUT] return typedef
+ );
+
+ // Returns redirected typerefs
+ HRESULT GetTypeRefProps(
+ mdTypeRef typeref, // [IN] given typeref
+ LPCSTR *psznamespace, // [OUT] return typeref namespace
+ LPCSTR *pszname, // [OUT] return typeref name
+ mdToken *ptkResolutionScope // [OUT] return typeref resolutionscope
+ );
+
+ // Find TypeRef by name
+ HRESULT FindTypeRef(
+ LPCSTR szNamespace, // [IN] Namespace for the TypeRef (NULL for standalone names)
+ LPCSTR szName, // [IN] Name of the TypeRef.
+ mdToken tkResolutionScope, // [IN] Resolution Scope fo the TypeRef.
+ mdTypeRef *ptk // [OUT] TypeRef token returned.
+ );
+
+ // Modify an ExportedType name
+ HRESULT ModifyExportedTypeName(
+ mdExportedType tkExportedType, // [IN] exportedType token
+ LPCSTR *pszNamespace, // [IN,OUT,OPTIONAL] namespace to modify
+ LPCSTR *pszName // [IN,OUT,OPTIONAL] name to modify
+ );
+
+ // Find ExportedType by name
+ HRESULT FindExportedType(
+ LPCUTF8 szNamespace, // [IN] expected namespace
+ LPCUTF8 szName, // [IN] expected name
+ mdToken tkEnclosingType, // [IN] expected tkEnclosingType
+ mdExportedType *ptkExportedType // [OUT] ExportedType token returned.
+ );
+
+ // Returns rewritten metadata version string
+ HRESULT GetVersionString(
+ LPCSTR *pszVersion // [OUT] return metadata version string
+ )
+ {
+ _ASSERTE(pszVersion != NULL);
+ *pszVersion = m_pRedirectedVersionString;
+ return S_OK;
+ }
+
+ void ModifyAssemblyRefProps(
+ mdAssemblyRef mdar,
+ const void **ppbPublicKeyOrToken,
+ ULONG *pcbPublicKeyOrToken,
+ LPCSTR *pszName,
+ USHORT *pusMajorVersion,
+ USHORT *pusMinorVersion,
+ USHORT *pusBuildNumber,
+ USHORT *pusRevisionNumber,
+ const void **ppbHashValue,
+ ULONG *pcbHashValue)
+ {
+ _ASSERTE(TypeFromToken(mdar) == mdtAssemblyRef);
+
+ // The version of the mscorlib should be 4.0.0.0
+ if (m_assemblyRefMscorlib == mdar)
+ {
+ if (pusMajorVersion != nullptr)
+ *pusMajorVersion = VER_ASSEMBLYMAJORVERSION;
+ if (pusMinorVersion != nullptr)
+ *pusMinorVersion = VER_ASSEMBLYMINORVERSION;
+ if (pusBuildNumber != nullptr)
+ *pusBuildNumber = VER_ASSEMBLYBUILD;
+ 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)
+ {
+ // This is one of the assemblies that we inject
+ UINT index = RidFromToken(mdar) - m_rawAssemblyRefCount - 1;
+
+ if (ppbPublicKeyOrToken != nullptr)
+ {
+ if (index != ContractAssemblyIndex::ContractAssembly_SystemRuntimeWindowsRuntime &&
+ index != ContractAssemblyIndex::ContractAssembly_SystemRuntimeWindowsRuntimeUIXaml)
+ {
+ // The assembly ref is a contract/facade assembly. System.Runtime.WindowsRuntime and
+ // System.Runtime.WindowsRuntime.UI.Xaml are special cased because the contract and the implementation
+ // assembly share the same identity and use mscorlib's public key/token that ppbPublicKeyOrToken
+ // alredy contains since the raw GetAssemblyRefProps was called with mscorlib's token before this
+ // function was called.
+ if (*pcbPublicKeyOrToken == sizeof(s_pbContractPublicKeyToken))
+ *ppbPublicKeyOrToken = s_pbContractPublicKeyToken;
+ else if (*pcbPublicKeyOrToken == sizeof(s_pbContractPublicKey))
+ *ppbPublicKeyOrToken = s_pbContractPublicKey;
+ }
+#ifdef FEATURE_WINDOWSPHONE
+ // System.Runtime.WindowsRuntime uses the ECMA key on Windows Phone.
+ // The WinRT adapter's policy of using mscorlib's assembly references for all the additional
+ // assembly references doesn't work here since mscorlib uses the Silverlight Platform key.
+ else
+ {
+ if (*pcbPublicKeyOrToken == sizeof(g_rbNeutralPublicKeyToken))
+ *ppbPublicKeyOrToken = g_rbNeutralPublicKeyToken;
+ else if (*pcbPublicKeyOrToken == sizeof(g_rbNeutralPublicKey))
+ *ppbPublicKeyOrToken = g_rbNeutralPublicKey;
+ }
+#endif
+ }
+
+ if (pszName != nullptr)
+ *pszName = GetExtraAssemblyRefName(mdar);
+
+ if (pusMajorVersion != nullptr)
+ *pusMajorVersion = VER_ASSEMBLYMAJORVERSION;
+ if (pusMinorVersion != nullptr)
+ *pusMinorVersion = VER_ASSEMBLYMINORVERSION;
+ if (pusBuildNumber != nullptr)
+ *pusBuildNumber = VER_ASSEMBLYBUILD;
+ if (pusRevisionNumber != nullptr)
+ *pusRevisionNumber = VER_ASSEMBLYBUILD_QFE;
+
+ if (ppbHashValue)
+ *ppbHashValue = NULL;
+
+ if (pcbHashValue)
+ *pcbHashValue = 0;
+ }
+ }
+
+ // Modifes the FieldDefProps.
+ HRESULT ModifyFieldDefProps (mdFieldDef tkFielddDef, DWORD *pdwFlags);
+
+ // Modifies FieldProps
+ HRESULT ModifyFieldProps (mdToken tkField, mdToken tkParent, LPCSTR szFieldName, DWORD *pdwFlags);
+
+ // Modifies methodDef flags and RVA
+ HRESULT ModifyMethodProps(mdMethodDef tkMethodDef, /*[in, out]*/ DWORD *pdwAttr, /* [in,out] */ DWORD *pdwImplFlags, /* [in,out] */ ULONG *pulRVA, LPCSTR *pszName);
+
+ // Modifies member flags and RVA
+ HRESULT ModifyMemberProps(mdToken tkMember, /*[in, out]*/ DWORD *pdwAttr, /* [in,out] */ DWORD *pdwImplFlags, /* [in,out] */ ULONG *pulRVA, LPCSTR *pszNewName);
+
+ // Modifies CA's
+ HRESULT GetCustomAttributeByName( // S_OK or error.
+ mdToken tkObj, // [IN] Object with Custom Attribute.
+ LPCUTF8 szName, // [IN] Name of desired Custom Attribute.
+ mdCustomAttribute *ptkCA, // [OUT] Put custom attribute token here
+ const void **ppData, // [OUT] Put pointer to data here.
+ ULONG *pcbData); // [OUT] Put size of data here.
+
+ // Modify CA blobs
+ HRESULT GetCustomAttributeBlob(
+ mdCustomAttribute tkCA,
+ const void **ppData, // [OUT] Put pointer to data here.
+ ULONG *pcbData); // [OUT] Put size of data here.
+
+ // Gets the GUID used for COM interop purposes.
+ HRESULT GetItemGuid(mdToken tkObj, CLSID *pGuid);
+
+ // Gets filtered methodImpl list
+ HRESULT AddMethodImplsToEnum(mdTypeDef tkTypeDef, HENUMInternal *henum);
+
+ //-----------------------------------------------------------------------------------
+ // For each token, we cache the signature that the adapter reports to callers.
+ //-----------------------------------------------------------------------------------
+ struct SigData
+ {
+ ULONG cbSig; // Length of sig in bytes
+ BYTE data[1]; // Signature
+
+ static SigData* Create(ULONG cbSig, PCCOR_SIGNATURE pSig);
+ static void Destroy(SigData *pSigData);
+
+ // Sentinel value meaning we did not need to rewrite the signature; use the underlying importer's signature
+ static SigData* const NOREDIRECT;
+ };
+
+ // Gets a method/field/TypeSpec/MethodSpec signature, with appropriate WinMD changes.
+ HRESULT ReinterpretMethodSignature (ULONG cbOrigSigBlob, PCCOR_SIGNATURE pOrigSig, SigData **ppSigData);
+ HRESULT ReinterpretFieldSignature (ULONG cbOrigSigBlob, PCCOR_SIGNATURE pOrigSig, SigData **ppSigData);
+ HRESULT ReinterpretTypeSpecSignature (ULONG cbOrigSigBlob, PCCOR_SIGNATURE pOrigSig, SigData **ppSigData);
+ HRESULT ReinterpretMethodSpecSignature (ULONG cbOrigSigBlob, PCCOR_SIGNATURE pOrigSig, SigData **ppSigData);
+
+ template<mdToken TOKENTYPE>
+ HRESULT ReinterpretSignature(
+ ULONG cbOrigSigBlob, // [IN] count of bytes in original signature blob
+ PCCOR_SIGNATURE pOrigSig, // [IN] original signature
+ SigData **ppSigData // [OUT] new signature or SigData::NOREDIRECT
+ )
+ {
+ UNREACHABLE_MSG("You should create a specialized version of ReinterpretSignature for this token type");
+ }
+
+ // Explicit specializations of ReinterpretSignature for all supported token types
+ template<> // mdMethodDef
+ HRESULT ReinterpretSignature<mdtMethodDef>(ULONG cbOrigSigBlob, PCCOR_SIGNATURE pOrigSig, SigData **ppSigData)
+ {
+ return ReinterpretMethodSignature(cbOrigSigBlob, pOrigSig, ppSigData);
+ }
+
+ template<> // mdFieldDef
+ HRESULT ReinterpretSignature<mdtFieldDef>(ULONG cbOrigSigBlob, PCCOR_SIGNATURE pOrigSig, SigData **ppSigData)
+ {
+ return ReinterpretFieldSignature(cbOrigSigBlob, pOrigSig, ppSigData);
+ }
+
+ template<> // mdMemberRef
+ HRESULT ReinterpretSignature<mdtMemberRef>(ULONG cbOrigSigBlob, PCCOR_SIGNATURE pOrigSig, SigData **ppSigData)
+ {
+ if (cbOrigSigBlob == 0)
+ {
+ *ppSigData = SigData::NOREDIRECT;
+
+ return META_E_BAD_SIGNATURE;
+ }
+
+ // MemberRef references either a field or a method
+ return (*pOrigSig == IMAGE_CEE_CS_CALLCONV_FIELD) ?
+ ReinterpretFieldSignature(cbOrigSigBlob, pOrigSig, ppSigData) :
+ ReinterpretMethodSignature(cbOrigSigBlob, pOrigSig, ppSigData);
+ }
+
+ template<> // mdProperty
+ HRESULT ReinterpretSignature<mdtProperty>(ULONG cbOrigSigBlob, PCCOR_SIGNATURE pOrigSig, SigData **ppSigData)
+ {
+ // Per ECMA CLI spec, section 23.2.5 PropertySig is just an ordinary method (getter) signature
+ return ReinterpretMethodSignature(cbOrigSigBlob, pOrigSig, ppSigData);
+ }
+
+ template<> // mdTypeSpec
+ HRESULT ReinterpretSignature<mdtTypeSpec>(ULONG cbOrigSigBlob, PCCOR_SIGNATURE pOrigSig, SigData **ppSigData)
+ {
+ return ReinterpretTypeSpecSignature(cbOrigSigBlob, pOrigSig, ppSigData);
+ }
+
+ template<> // mdMethodSpec
+ HRESULT ReinterpretSignature<mdtMethodSpec>(ULONG cbOrigSigBlob, PCCOR_SIGNATURE pOrigSig, SigData **ppSigData)
+ {
+ return ReinterpretMethodSpecSignature(cbOrigSigBlob, pOrigSig, ppSigData);
+ }
+
+ // Note: This method will look in a cache for the reinterpreted signature, but does not add any values to
+ // the cache or do any work on failure. If we can't find it then it returns S_FALSE.
+ static HRESULT GetCachedSigForToken(
+ mdToken token, // [IN] given token
+ MemoTable<SigData*, SigData::Destroy> &memoTable, // [IN] the MemoTable to use
+ ULONG *pcbSigBlob, // [OUT] count of bytes in the signature blob
+ PCCOR_SIGNATURE *ppSig, // [OUT] new signature
+ BOOL *pfPassThrough // [OUT] did the cache say we don't need to reinterpret this sig?
+ );
+
+ static HRESULT InsertCachedSigForToken(
+ mdToken token, // [IN] given token
+ MemoTable<SigData*, SigData::Destroy> &memoTable, // [IN] the MemoTable to use
+ SigData **ppSigData // [IN, OUT] new signature or SigData::NOREDIRECT if the signature didn't need to be reparsed,
+ ); // will be updated with another (but identical) SigData* if this thread lost the race
+
+ template<typename T, mdToken TOKENTYPE>
+ HRESULT GetOriginalSigForToken(
+ T *pImport,
+ mdToken token, // [IN] Token.
+ PCCOR_SIGNATURE *ppvSig, // [OUT] return pointer to signature.
+ ULONG *pcbSig // [OUT] return size of signature.
+ )
+ {
+ UNREACHABLE_MSG("You should create a specialized version of GetOriginalSigForToken for this interface/token type");
+ }
+
+ template<mdToken TOKENTYPE>
+ MemoTable<SigData*, SigData::Destroy> &GetSignatureMemoTable()
+ {
+ UNREACHABLE_MSG("You should create a specialized version of GetSignatureMemoTable for this token type");
+ }
+
+ // Explicit specializations of GetOriginalSigForToken for all supported token types (IMetaDataImport2)
+ template<> // mdMethodDef
+ HRESULT GetOriginalSigForToken<IMetaDataImport2, mdtMethodDef>(IMetaDataImport2 *pImport, mdMethodDef tk, PCCOR_SIGNATURE *ppvSig, ULONG *pcbSig)
+ {
+ return pImport->GetMethodProps(tk, NULL, NULL, 0, NULL, NULL, ppvSig, pcbSig, NULL, NULL);
+ }
+
+ template<> // mdFieldDef
+ HRESULT GetOriginalSigForToken<IMetaDataImport2, mdtFieldDef>(IMetaDataImport2 *pImport, mdFieldDef tk, PCCOR_SIGNATURE *ppvSig, ULONG *pcbSig)
+ {
+ return pImport->GetFieldProps(tk, NULL, NULL, 0, NULL, NULL, ppvSig, pcbSig, NULL, NULL, NULL);
+ }
+
+ template<> // mdMemberRef
+ HRESULT GetOriginalSigForToken<IMetaDataImport2, mdtMemberRef>(IMetaDataImport2 *pImport, mdMemberRef tk, PCCOR_SIGNATURE *ppvSig, ULONG *pcbSig)
+ {
+ return pImport->GetMemberRefProps(tk, NULL, NULL, 0, NULL, ppvSig, pcbSig);
+ }
+
+ template<> // mdProperty
+ HRESULT GetOriginalSigForToken<IMetaDataImport2, mdtProperty>(IMetaDataImport2 *pImport, mdProperty tk, PCCOR_SIGNATURE *ppvSig, ULONG *pcbSig)
+ {
+ return pImport->GetPropertyProps(tk, NULL, NULL, 0, NULL, NULL, ppvSig, pcbSig, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL);
+ }
+
+ template<> // mdTypeSpec
+ HRESULT GetOriginalSigForToken<IMetaDataImport2, mdtTypeSpec>(IMetaDataImport2 *pImport, mdTypeSpec tk, PCCOR_SIGNATURE *ppvSig, ULONG *pcbSig)
+ {
+ return pImport->GetTypeSpecFromToken(tk, ppvSig, pcbSig);
+ }
+
+ template<> // mdMethodSpec
+ HRESULT GetOriginalSigForToken<IMetaDataImport2, mdtMethodSpec>(IMetaDataImport2 *pImport, mdMethodSpec tk, PCCOR_SIGNATURE *ppvSig, ULONG *pcbSig)
+ {
+ return pImport->GetMethodSpecProps(tk, NULL, ppvSig, pcbSig);
+ }
+
+ // Explicit specializations of GetOriginalSigForToken for all supported token types (IMDInternalImport)
+ template<> // mdMethodDef
+ HRESULT GetOriginalSigForToken<IMDInternalImport, mdtMethodDef>(IMDInternalImport *pImport, mdMethodDef tk, PCCOR_SIGNATURE *ppvSig, ULONG *pcbSig)
+ {
+ return pImport->GetSigOfMethodDef(tk, pcbSig, ppvSig);
+ }
+
+ template<> // mdFieldDef
+ HRESULT GetOriginalSigForToken<IMDInternalImport, mdtFieldDef>(IMDInternalImport *pImport, mdFieldDef tk, PCCOR_SIGNATURE *ppvSig, ULONG *pcbSig)
+ {
+ return pImport->GetSigOfFieldDef(tk, pcbSig, ppvSig);
+ }
+
+ template<> // mdMemberRef
+ HRESULT GetOriginalSigForToken<IMDInternalImport, mdtMemberRef>(IMDInternalImport *pImport, mdMemberRef tk, PCCOR_SIGNATURE *ppvSig, ULONG *pcbSig)
+ {
+ LPCSTR szMemberRefName;
+ return pImport->GetNameAndSigOfMemberRef(tk, ppvSig, pcbSig, &szMemberRefName);
+ }
+
+ template<> // mdProperty
+ HRESULT GetOriginalSigForToken<IMDInternalImport, mdtProperty>(IMDInternalImport *pImport, mdProperty tk, PCCOR_SIGNATURE *ppvSig, ULONG *pcbSig)
+ {
+ return pImport->GetPropertyProps(tk, NULL, NULL, ppvSig, pcbSig);
+ }
+
+ template<> // mdTypeSpec
+ HRESULT GetOriginalSigForToken<IMDInternalImport, mdtTypeSpec>(IMDInternalImport *pImport, mdTypeSpec tk, PCCOR_SIGNATURE *ppvSig, ULONG *pcbSig)
+ {
+ return pImport->GetSigFromToken(tk, pcbSig, ppvSig);
+ }
+
+ template<> // mdMethodSpec
+ HRESULT GetOriginalSigForToken<IMDInternalImport, mdtMethodSpec>(IMDInternalImport *pImport, mdMethodSpec tk, PCCOR_SIGNATURE *ppvSig, ULONG *pcbSig)
+ {
+ return pImport->GetMethodSpecProps(tk, NULL, ppvSig, pcbSig);
+ }
+
+
+ // Returns signature for the given MethodDef, FieldDef, MemberRef, standalone Signature, Property, TypeSpec, or MethodSpec token.
+ // Performs cache lookup, computes the new reinterpreted signature if needed, and inserts it into the cache. Be sure to instantiate
+ // the method with right template arguments. T is the underlying metadata interface that should be used to retrieve the original
+ // signature if not passed in ppOrigSig/pcbOrigSigBlob. TOKENTYPE an mdt* constants corresponding to the type of the token.
+ template<typename T, mdToken TOKENTYPE>
+ HRESULT GetSignatureForToken(
+ mdToken token,
+ PCCOR_SIGNATURE *ppOrigSig, // [IN] pointer to count of bytes in the original signature blob, NULL if we need to retrieve from GetOriginalSigForToken
+ ULONG *pcbOrigSigBlob, // [IN] pointer to original signature, NULL if we need to retrieve from GetOriginalSigForToken
+ PCCOR_SIGNATURE *ppSig, // [OUT] new signature
+ ULONG *pcbSigBlob, // [OUT] count of bytes in the signature blob
+ T *pImport)
+ {
+ _ASSERTE(TypeFromToken(token) == TOKENTYPE);
+ if ((ppSig == NULL) && (pcbSigBlob == NULL))
+ {
+ return S_OK;
+ }
+
+ // When loading NGen images we go through code paths that expect no faults and no
+ // throws. We will need to take a look at how we use the winmd metadata with ngen,
+ // potentially storing the post-mangled metadata in the NI because as the adapter grows
+ // we'll see more of these.
+ CONTRACT_VIOLATION(ThrowsViolation | FaultViolation);
+
+ HRESULT hr = S_OK;
+ ULONG cbOrigSigBlob = (ULONG)(-1);
+ PCCOR_SIGNATURE pOrigSig = NULL;
+ BOOL fPassThrough = FALSE;
+
+ MemoTable<SigData*, SigData::Destroy> &memoTable = GetSignatureMemoTable<TOKENTYPE>();
+
+ // Get from cache
+ IfFailRet(GetCachedSigForToken(token, memoTable, pcbSigBlob, ppSig, &fPassThrough));
+ if (hr == S_FALSE)
+ {
+ // We do not want to leak S_FALSE from this function
+ hr = S_OK;
+
+ // Original signature has already been provided?
+ if ((pcbOrigSigBlob == NULL) || (ppOrigSig == NULL))
+ {
+ // Not provided, we need to get one by ourselves
+ IfFailRet((GetOriginalSigForToken<T, TOKENTYPE>(pImport, token, &pOrigSig, &cbOrigSigBlob)));
+ }
+ else
+ {
+ // Provided, use that
+ pOrigSig = *ppOrigSig;
+ cbOrigSigBlob = *pcbOrigSigBlob;
+ }
+
+ if (fPassThrough) // We cached that we don't need to reinterpret anything.
+ {
+ if (ppSig != NULL)
+ *ppSig = pOrigSig;
+ if (pcbSigBlob != NULL)
+ *pcbSigBlob = cbOrigSigBlob;
+ }
+ else
+ {
+ SigData *pSigData;
+ IfFailRet(ReinterpretSignature<TOKENTYPE>(cbOrigSigBlob, pOrigSig, &pSigData));
+ IfFailRet(InsertCachedSigForToken(token, memoTable, &pSigData));
+
+ fPassThrough = (pSigData == SigData::NOREDIRECT);
+
+ if (ppSig != NULL)
+ *ppSig = (fPassThrough ? pOrigSig : (PCCOR_SIGNATURE)pSigData->data);
+ if (pcbSigBlob != NULL)
+ *pcbSigBlob = (fPassThrough ? cbOrigSigBlob : pSigData->cbSig);
+ }
+ }
+ else
+ {
+ _ASSERTE(!fPassThrough);
+ // Already wrote to our output parameters.
+ }
+ // We should return error (via IfFailRet macro) or S_OK here
+ _ASSERTE(hr == S_OK);
+
+ return hr;
+ }
+
+ //
+ // Support for extra assembly refs inserted into this assembly
+ //
+ ULONG GetRawAssemblyRefCount() { return m_rawAssemblyRefCount; }
+
+ mdAssemblyRef GetAssemblyRefMscorlib() { return m_assemblyRefMscorlib; }
+
+ LPCSTR GetExtraAssemblyRefName(mdAssemblyRef mda)
+ {
+ UINT index = RidFromToken(mda) - m_rawAssemblyRefCount - 1;
+ return WinMDAdapter::GetExtraAssemblyRefNameFromIndex((ContractAssemblyIndex)index);
+ }
+
+
+ static LPCSTR GetExtraAssemblyRefNameFromIndex(FrameworkAssemblyIndex index)
+ {
+ _ASSERTE(index >= 0 && index < FrameworkAssembly_Count);
+ _ASSERTE(index != FrameworkAssembly_Mscorlib);
+ switch(index)
+ {
+ case FrameworkAssembly_SystemObjectModel:
+ return "System.ObjectModel";
+ case FrameworkAssembly_SystemRuntime:
+ return "System.Runtime";
+ case FrameworkAssembly_SystemRuntimeWindowsRuntime:
+ return "System.Runtime.WindowsRuntime";
+ 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;
+ }
+ }
+
+ static LPCSTR GetExtraAssemblyRefNameFromIndex(ContractAssemblyIndex index)
+ {
+ _ASSERTE(index >= 0 && index < ContractAssembly_Count);
+ switch(index)
+ {
+ case ContractAssembly_SystemRuntime:
+ return "System.Runtime";
+ case ContractAssembly_SystemRuntimeInteropServicesWindowsRuntime:
+ return "System.Runtime.InteropServices.WindowsRuntime";
+ case ContractAssembly_SystemObjectModel:
+ return "System.ObjectModel";
+ case ContractAssembly_SystemRuntimeWindowsRuntime:
+ return "System.Runtime.WindowsRuntime";
+ case ContractAssembly_SystemRuntimeWindowsRuntimeUIXaml:
+ return "System.Runtime.WindowsRuntime.UI.Xaml";
+ case ContractAssembly_SystemNumericsVectors:
+ return "System.Numerics.Vectors";
+ default:
+ _ASSERTE(!"Invalid AssemblyRef token!");
+ return NULL;
+ }
+ }
+
+ LPCWSTR GetExtraAssemblyRefNameW(mdAssemblyRef mda)
+ {
+ UINT index = RidFromToken(mda) - m_rawAssemblyRefCount - 1;
+ return WinMDAdapter::GetExtraAssemblyRefNameFromIndexW((ContractAssemblyIndex)index);
+ }
+
+ static LPCWSTR GetExtraAssemblyRefNameFromIndexW(ContractAssemblyIndex index)
+ {
+ _ASSERTE(index >= 0 && index < ContractAssembly_Count);
+ switch(index)
+ {
+ case ContractAssembly_SystemRuntime:
+ return W("System.Runtime");
+ case ContractAssembly_SystemRuntimeInteropServicesWindowsRuntime:
+ return W("System.Runtime.InteropServices.WindowsRuntime");
+ case ContractAssembly_SystemObjectModel:
+ return W("System.ObjectModel");
+ case ContractAssembly_SystemRuntimeWindowsRuntime:
+ return W("System.Runtime.WindowsRuntime");
+ case ContractAssembly_SystemRuntimeWindowsRuntimeUIXaml:
+ return W("System.Runtime.WindowsRuntime.UI.Xaml");
+ case ContractAssembly_SystemNumericsVectors:
+ return W("System.Numerics.Vectors");
+ default:
+ _ASSERTE(!"Invalid AssemblyRef token!");
+ return NULL;
+ }
+ }
+
+ BOOL IsValidAssemblyRefToken(mdAssemblyRef tk)
+ {
+ _ASSERTE(TypeFromToken(tk) == mdtAssemblyRef);
+
+ RID rid = RidFromToken(tk);
+ if (rid > 0 &&
+ rid <= m_rawAssemblyRefCount + GetExtraAssemblyRefCount())
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+ static void GetExtraAssemblyRefProps(FrameworkAssemblyIndex index,
+ LPCSTR* ppName,
+ AssemblyMetaDataInternal* pContext,
+ PCBYTE * ppPublicKeytoken,
+ DWORD* pTokenLength,
+ DWORD* pdwFlags);
+
+ BOOL IsScenarioWinMDExp()
+ {
+ return (m_scenario == kWinMDExp);
+ }
+
+ HRESULT IsRuntimeClassImplementation(mdTypeDef tkTypeDef, BOOL *pbResult)
+ {
+ _ASSERTE(pbResult != NULL);
+
+ ULONG typeDefTreatment;
+ HRESULT hr = GetTypeDefTreatment(tkTypeDef, &typeDefTreatment);
+
+ if (SUCCEEDED(hr))
+ {
+ // kTdUnmangleWinRTName treatment means it is a <CLR> implementation class
+ *pbResult = (typeDefTreatment == kTdUnmangleWinRTName);
+ }
+
+ return hr;
+ }
+
+private:
+ struct CABlob;
+
+private:
+
+ WinMDAdapter(IMDCommon * pRawMDCommon);
+
+ // S_OK if this is a CLR implementation type that was mangled and hidden by WinMDExp
+ HRESULT CheckIfClrImplementationType(LPCSTR szName, DWORD dwAttr, LPCSTR *pszUnmangledName);
+
+ // Get TypeRefTreatment value for a typeRef
+ HRESULT GetTypeRefTreatment(mdTypeRef typeRef, ULONG *ppTypeRefTreatment);
+
+ // Get TypeRef's index in array code:g_rgRedirectedTypes or return S_FALSE.
+ HRESULT GetTypeRefRedirectedInfo(
+ mdTypeRef tkTypeRef,
+ RedirectedTypeIndex * pIndex);
+
+ // Get TypeDefTreatment value for a typeDef
+ HRESULT GetTypeDefTreatment(mdTypeDef typeDef, ULONG *ppTypeRefTreatment);
+
+ // Get MethodTreatment value for a methodDef
+ HRESULT GetMethodDefTreatment(mdMethodDef methodDef, ULONG *ppMethodDefTreatment);
+
+ // Compute MethodTreatment value for a methodDef (unlike GetMethodDefTreatment, this
+ // does not cache.)
+ HRESULT ComputeMethodDefTreatment(mdMethodDef tkMethodDef, mdTypeDef tkDeclaringTypeDef, ULONG *ppMethodDefTreatment);
+
+ HRESULT CheckIfMethodImplImplementsARedirectedInterface(mdToken tkDecl, UINT *pIndex);
+
+ HRESULT TranslateWinMDAttributeUsageAttribute(mdTypeDef tkTypeDefOfCA, DWORD *pClrTargetValue, BOOL *pAllowMultiple);
+
+ static HRESULT CreateClrAttributeUsageAttributeCABlob(DWORD clrTargetValue, BOOL allowMultiple, CABlob **ppCABlob);
+
+ // Whether the WinRT type should be hidden from managed code
+ // Example: helper class/interface for projected jupiter structs
+ static BOOL IsHiddenWinRTType(LPCSTR szWinRTNamespace, LPCSTR szWinRTName);
+
+ // Map a WinRT typename to CLR typename
+ static BOOL ConvertWellKnownTypeNameFromWinRTToClr(LPCSTR *pszNamespace, LPCSTR *pszName, UINT *pIndex);
+
+ static HRESULT CreatePrefixedName(LPCSTR szPrefix, LPCSTR szName, LPCSTR *ppOut);
+
+ template <typename T> static void Delete(T* ptr)
+ {
+ delete [] ptr;
+ }
+
+ HRESULT RewriteTypeInSignature(SigParser * pSigParser, SigBuilder * pSigBuilder, BOOL * pfChangedSig);
+
+ private:
+ //-----------------------------------------------------------------------------------
+ // Pointer to the raw view of the metadata.
+ //-----------------------------------------------------------------------------------
+ IMetaModelCommonRO *m_pRawMetaModelCommonRO;
+
+
+ private:
+ //-----------------------------------------------------------------------------------
+ // Stores whether the file is a pure .winmd file or one that combines WinRT and CLR code.
+ //-----------------------------------------------------------------------------------
+ enum WinMDScenario
+ {
+ kWinMDNormal = 1, // File is normal Windows .winmd file (Version string = "Windows Runtime nnn")
+ kWinMDExp = 2, // File is output of winmdexp (Version string = "Windows Runtime nnn;<dotnetVersion>")
+ };
+
+ WinMDScenario m_scenario;
+
+
+ private:
+
+ //-----------------------------------------------------------------------------------
+ // Every WinMD file is required to have an assemblyRef to mscorlib - this field caches that assemblyRef
+ //-----------------------------------------------------------------------------------
+ mdAssemblyRef m_assemblyRefMscorlib;
+ BOOL m_fReferencesMscorlibV4; // m_assemblyRefMscorlib is a version=4.0.0.0 AssemblyRef
+ ULONG m_rawAssemblyRefCount; // the raw assembly ref count not including the extra ones.
+ LONG m_extraAssemblyRefCount; // the assembly ref count to return from IMetaDataAssemblyImport::EnumAssemblyRefs
+
+
+ private:
+ //-----------------------------------------------------------------------------------
+ // For each typeref token, we cache an enum that determines how the adapter treats it.
+ //-----------------------------------------------------------------------------------
+ enum TypeRefTreatment
+ {
+ // The upper 8 bits determine how to interpret the lower 24-bits:
+ kTrClassMask = 0xff000000,
+
+ // Lower 24-bits represent fixed values (defined in rest of enum)
+ kTrClassMisc = 0x00000000,
+
+ // TypeRef is one of a small # of hard-coded Windows.Foundation types that we redirect to mscorlib counterparts.
+ // Lower 24-bits is index into typeref redirection table.
+ kTrClassWellKnownRedirected = 0x01000000,
+
+ kTrNotYetInitialized = kTrClassMisc|0x000000, // Entry has not yet been initialized.
+ kTrNoRewriteNeeded = kTrClassMisc|0x000001, // Do not mangle the name.
+ kTrSystemDelegate = kTrClassMisc|0x000002, // Fast-recognition code for System.Delegate
+ kTrSystemAttribute = kTrClassMisc|0x000003, // Fast-recognition code for System.Attribute
+ kTrSystemEnum = kTrClassMisc|0x000004, // Fast-recognition code for System.Enum
+ kTrSystemValueType = kTrClassMisc|0x000005, // Fast-recognition code for System.ValueType
+ };
+ MemoTable<ULONG, DoNothing<ULONG> > m_typeRefTreatmentMemoTable; // Holds index into typeRef rename array or member of TypeRefTreatment enum
+
+ private:
+ //-----------------------------------------------------------------------------------
+ // For each typedef token, we cache an enum that determines how the adapter treats it.
+ //-----------------------------------------------------------------------------------
+ enum TypeDefTreatment
+ {
+ kTdNotYetInitialized = 0x00,
+
+ kTdTreatmentMask = 0x0f,
+ kTdOther = 0x01, // Anything not covered below, and not affected by the treatment flags
+ kTdNormalNonAttribute = 0x02, // non-attribute TypeDef from non-managed winmd assembly
+ kTdNormalAttribute = 0x03, // Attribute TypeDef from non-managed winmd assembly
+ kTdUnmangleWinRTName = 0x04, // Type in managed winmd that should be renamed from <CLR>Foo to Foo
+ kTdPrefixWinRTName = 0x05, // Type in managed winmd that should be renamed from Foo to <WinRT>Foo
+ kTdRedirectedToCLRType = 0x06, // Type is redirected to a CLR type implementation.
+ kTdRedirectedToCLRAttribute = 0x07, // Type is redirected to a CLR type implementation that is an attribute.
+
+ kTdMarkAbstractFlag = 0x10, // Type should be marked as abstract
+ kTdMarkInternalFlag = 0x20, // Type should be hidden from managed code - examples are struct helpers
+ // for redirected Jupiter structs
+ kTdEnum = 0x40, // Type is an enum from managed\non-managed winmd assembly.
+ };
+ MemoTable<ULONG, DoNothing<ULONG> > m_typeDefTreatmentMemoTable; // Holds member of TypeDefTreatment enum
+
+ private:
+ //-----------------------------------------------------------------------------------
+ // For each methoddef token, we cache an enum that determines how the adapter treats it.
+ //-----------------------------------------------------------------------------------
+ enum MethodDefTreatment
+ {
+ kMdNotYetInitialized = 0x00,
+ kMdTreatmentMask = 0x0f, // Mask of various options
+ kMdOther = 0x01, // Anything not covered below
+ kMdDelegate = 0x02, // Declared by delegate
+ kMdAttribute = 0x03, // Declared by an attribute
+ kMdInterface = 0x04, // Is member of interface
+ kMdImplementation = 0x05, // CLR implementation of RuntimeClass
+ kMdHiddenImpl = 0x06, // Implements a redirected (hidden) interface
+ kMdtUnusedFlag = 0x07, // UnUnsed flag.
+ kMdRenameToDisposeMethod = 0x08, // Rename IClosable.Close to Dispose
+
+ kMdMarkAbstractFlag = 0x10, // Method should be marked as abstract
+ kMdMarkPublicFlag = 0x20, // Method visibility should be marked as public
+ };
+ MemoTable<ULONG, DoNothing<ULONG> > m_methodDefTreatmentMemoTable; // Holds member of MethodDefTreatment enum
+
+ private:
+ //-----------------------------------------------------------------------------------
+ // The version string we report to callers.
+ //-----------------------------------------------------------------------------------
+ LPSTR m_pRedirectedVersionString;
+
+ private:
+ //-----------------------------------------------------------------------------------
+ // For each customattribute token, we cache the blob that the adapter reports to callers.
+ // The special pointer value CABlob::NOREDIRECT indicates that the raw blob is to be
+ // passed unchanged.
+ //-----------------------------------------------------------------------------------
+
+ // Represents a custom attribute blob
+ struct CABlob
+ {
+ ULONG cbBlob; // Length of blob in bytes.
+ BYTE data[1]; // Start of variable-length blob (cbBlob indicates length in bytes.)
+
+ static CABlob* Create(const BYTE *pBlob, ULONG cbBlob);
+ static void Destroy(CABlob *pCABlob);
+
+ // Sentinel value in m_redirectedCABlobsMemoTable table. Means "do no blob rewriting. Return the one from the underlying importer."
+ static CABlob* const NOREDIRECT;
+ };
+
+ MemoTable<CABlob*, CABlob::Destroy> m_redirectedCABlobsMemoTable; // Array of rewritten CA blobs
+
+ private:
+ //-----------------------------------------------------------------------------------
+ // For each token, we cache the signature that the adapter reports to callers.
+ //-----------------------------------------------------------------------------------
+ MemoTable<SigData*, SigData::Destroy> m_redirectedMethodDefSigMemoTable; // Array of rewritten MethodDef signatures
+ MemoTable<SigData*, SigData::Destroy> m_redirectedFieldDefSigMemoTable; // Array of rewritten FieldDef signatures
+ MemoTable<SigData*, SigData::Destroy> m_redirectedMemberRefSigMemoTable; // Array of rewritten MemberRef signatures
+ MemoTable<SigData*, SigData::Destroy> m_redirectedPropertySigMemoTable; // Array of rewritten Property signatures
+ MemoTable<SigData*, SigData::Destroy> m_redirectedTypeSpecSigMemoTable; // Array of rewritten TypeSpec signatures
+ MemoTable<SigData*, SigData::Destroy> m_redirectedMethodSpecSigMemoTable; // Array of rewritten MethodSpec signatures
+
+ // Explicit specializations of GetSignatureMemoTable for all supported token types
+ template<> MemoTable<SigData*, SigData::Destroy> &GetSignatureMemoTable<mdtMethodDef>() { return m_redirectedMethodDefSigMemoTable; }
+ template<> MemoTable<SigData*, SigData::Destroy> &GetSignatureMemoTable<mdtFieldDef>() { return m_redirectedFieldDefSigMemoTable; }
+ template<> MemoTable<SigData*, SigData::Destroy> &GetSignatureMemoTable<mdtMemberRef>() { return m_redirectedMemberRefSigMemoTable; }
+ template<> MemoTable<SigData*, SigData::Destroy> &GetSignatureMemoTable<mdtProperty>() { return m_redirectedPropertySigMemoTable; }
+ template<> MemoTable<SigData*, SigData::Destroy> &GetSignatureMemoTable<mdtTypeSpec>() { return m_redirectedTypeSpecSigMemoTable; }
+ template<> MemoTable<SigData*, SigData::Destroy> &GetSignatureMemoTable<mdtMethodSpec>() { return m_redirectedMethodSpecSigMemoTable; }
+
+ private:
+ //-----------------------------------------------------------------------------------
+ // For each typedef whose name we mangle, we cache the mangled name that we report to callers. (The "name"
+ // is the "name" half of the namespace/name pair. We don't mangle namespaces.)
+ //
+ // Currently, the adapter used the tdAttr value to determine whether a typedef name needs
+ // be mangled at all - thus, we don't have a sentinel for "don't mangle."
+ //-----------------------------------------------------------------------------------
+ MemoTable<LPCSTR, Delete<const char> > m_mangledTypeNameTable; // Array of mangled typedef names
+};
+
+
+#endif // __MDWinMDAdapter__h__
diff --git a/src/md/winmd/inc/memotable.h b/src/md/winmd/inc/memotable.h
new file mode 100644
index 0000000000..df6823d184
--- /dev/null
+++ b/src/md/winmd/inc/memotable.h
@@ -0,0 +1,205 @@
+// 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.
+#ifndef __MDMemoTable__h__
+#define __MDMemoTable__h__
+
+
+//========================================================================================
+// A MemoTable is a 0-based N element array designed for safe multithreaded access
+// and single-initialization rules (e.g. multiple threads can race to initialize an entry
+// but only the first one actually modifies the table.)
+//
+// Template parameters:
+//
+// ELEMTYPE - Type of the data stored in the array. This type must be small enough
+// to be supported by InterlockedCompareExchange.
+//
+// INITVALUE - Sentinel that indicates that InitEntry() has not been called for that entry yet.
+// This is the "initial value" for all elements of the array.
+//
+// ELEMDELETER - (set to NULL if ELEMTYPE does not represent allocated storage.)
+// A function that deallocates the memory referenced by a pointer-typed ELEMTYPE.
+// MemoTable will never pass INITVALUE to this function.
+//
+// Restriction: if ELEMDELETER != NULL, ELEMTYPE must be a C++ pointer type
+// (annoying template weirdness with InterlockedCompareExchangeT that
+// life is too short to disentangle.)
+//========================================================================================
+template <typename ELEMTYPE, void (*ELEMDELETER)(ELEMTYPE)>
+class MemoTable
+{
+public:
+ MemoTable(ULONG numElems, ELEMTYPE initValue);
+ ~MemoTable();
+ HRESULT GetEntry(ULONG index, /* [out] */ ELEMTYPE *pElem);
+ HRESULT InitEntry(ULONG index, /* [in,out] */ ELEMTYPE *pElem);
+
+private:
+ MemoTable(const MemoTable &other);
+ MemoTable& operator=(const MemoTable &other);
+
+ const ULONG m_numElems;
+ const ELEMTYPE m_initValue;
+ ELEMTYPE *m_pTable; // Lazily allocated 0-based array with m_numElems elements.
+};
+
+
+
+
+//==============================================================================
+// MemoTable::MemoTable()
+//==============================================================================
+template <typename ELEMTYPE, void (*ELEMDELETER)(ELEMTYPE)>
+MemoTable<ELEMTYPE, ELEMDELETER>::MemoTable(ULONG numElems, ELEMTYPE initValue) :
+ m_numElems(numElems),
+ m_initValue(initValue)
+{
+ m_pTable = NULL;
+}
+
+
+
+//==============================================================================
+// MemoTable::~MemoTable()
+//==============================================================================
+template <typename ELEMTYPE, void (*ELEMDELETER)(ELEMTYPE)>
+MemoTable<ELEMTYPE, ELEMDELETER>::~MemoTable()
+{
+ if (m_pTable != NULL)
+ {
+ if (ELEMDELETER != NULL)
+ {
+ for (ULONG index = 0; index < m_numElems; index++)
+ {
+ if (m_pTable[index] != m_initValue)
+ {
+ ELEMDELETER(m_pTable[index]);
+ }
+ }
+ }
+ delete [] m_pTable;
+ }
+}
+
+//==============================================================================
+// HRESULT MemoTable::GetEntry(ULONG index, [out] ELEMTYPE *pElem)
+//
+// Retrieves the element at the specified index.
+//
+// Returns:
+// S_OK if returned element is not INITVALUE
+// S_FALSE if returned element is INITVALUE
+// CDLB_E_INDEX_NOT_FOUND if index is out of range.
+//==============================================================================
+template <typename ELEMTYPE, void (*ELEMDELETER)(ELEMTYPE)>
+HRESULT MemoTable<ELEMTYPE, ELEMDELETER>::GetEntry(ULONG index, /* [out] */ ELEMTYPE *pElem)
+{
+ _ASSERTE(pElem);
+ if (index >= m_numElems)
+ {
+ return CLDB_E_INDEX_NOTFOUND;
+ }
+ if (m_pTable == NULL)
+ {
+ *pElem = m_initValue;
+ return S_FALSE;
+ }
+ ELEMTYPE elem = m_pTable[index];
+ *pElem = elem;
+ return (elem == m_initValue) ? S_FALSE : S_OK;
+}
+
+//==============================================================================
+// HRESULT MemoTable::InitEntry(ULONG index, [in, out] ELEMTYPE *pElem)
+//
+// Initalizes the elment at the specified index. It is illegal to attempt
+// to initialize to INITVALUE. For scalar tables, it is illegal to attempt
+// to overwrite a previously initialized entry with a different value.
+// For pointer tables, the entry will be initialized using InterlockedCompareExchangeT
+// and your new value thrown away via ELEMDELETER if you lose the race to initialize.
+//
+// Returns:
+// *pElem overwritten with the actual value written into the table
+// (for pointer tables, this may not be the original pointer you passed
+// due to races.)
+//
+// S_OK is the only success value.
+//==============================================================================
+template <typename ELEMTYPE, void (*ELEMDELETER)(ELEMTYPE)>
+HRESULT MemoTable<ELEMTYPE, ELEMDELETER>::InitEntry(ULONG index, /* [in,out] */ ELEMTYPE *pElem)
+{
+ // This can cause allocations (thus entering the host) during a profiler stackwalk.
+ // But we're ok since we're not supporting SQL/F1 profiling with WinMDs. FUTURE:
+ // Would be nice to eliminate allocations on stack walks regardless.
+ PERMANENT_CONTRACT_VIOLATION(HostViolation, ReasonUnsupportedForSQLF1Profiling);
+
+ HRESULT hr = S_OK;
+ _ASSERTE(pElem);
+ ELEMTYPE incomingElem = *pElem;
+
+ if (index >= m_numElems)
+ {
+ IfFailGo(CLDB_E_INDEX_NOTFOUND);
+ }
+ _ASSERTE(incomingElem != m_initValue);
+
+ // If this is first call to InitEntry(), must initialize the table itself.
+ if (m_pTable == NULL)
+ {
+ NewHolder<ELEMTYPE> pNewTable = NULL;
+
+ if ((((size_t)(-1)) / sizeof(ELEMTYPE)) < m_numElems)
+ {
+ IfFailGo(E_OUTOFMEMORY);
+ }
+
+ // When loading NGen images we go through code paths that expect no faults and no
+ // throws. We will need to take a look at how we use the winmd metadata with ngen,
+ // potentially storing the post-mangled metadata in the NI because as the adapter grows
+ // we'll see more of these.
+ CONTRACT_VIOLATION(FaultViolation);
+ pNewTable = new (nothrow) ELEMTYPE[m_numElems];
+ IfNullGo(pNewTable);
+
+ for (ULONG walk = 0; walk < m_numElems; walk++)
+ {
+ pNewTable[walk] = m_initValue;
+ }
+ if (InterlockedCompareExchangeT<ELEMTYPE *>(&m_pTable, pNewTable, NULL) == NULL)
+ { // We won the initialization race
+ pNewTable.SuppressRelease();
+ }
+ }
+
+
+ //-------------------------------------------------------------------------
+ // Cannot fail after this point, or we may delete *pElem after entering it into table.
+ //-------------------------------------------------------------------------
+ hr = S_OK;
+ if (ELEMDELETER == NULL)
+ {
+ _ASSERTE(m_pTable[index] == m_initValue || m_pTable[index] == incomingElem);
+ m_pTable[index] = incomingElem;
+ }
+ else
+ {
+ ELEMTYPE winner = InterlockedCompareExchangeT((ELEMTYPE volatile *)&m_pTable[index], incomingElem, m_initValue);
+ if (winner != m_initValue)
+ {
+ ELEMDELETER(incomingElem); // Lost the race
+ *pElem = winner;
+ }
+ }
+ _ASSERTE(*pElem != m_initValue);
+
+ErrExit:
+ if (ELEMDELETER != NULL && FAILED(hr))
+ {
+ ELEMDELETER(*pElem);
+ *pElem = m_initValue;
+ }
+ return hr;
+}
+
+#endif // __MDMemoTable__h__
diff --git a/src/md/winmd/stdafx.cpp b/src/md/winmd/stdafx.cpp
new file mode 100644
index 0000000000..ff341e19a7
--- /dev/null
+++ b/src/md/winmd/stdafx.cpp
@@ -0,0 +1,12 @@
+// 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.
+//*****************************************************************************
+// stdafx.cpp
+//
+
+//
+// Precompiled headers.
+//
+//*****************************************************************************
+#include "stdafx.h"
diff --git a/src/md/winmd/stdafx.h b/src/md/winmd/stdafx.h
new file mode 100644
index 0000000000..7b662bcf38
--- /dev/null
+++ b/src/md/winmd/stdafx.h
@@ -0,0 +1,27 @@
+// 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.
+//*****************************************************************************
+// stdafx.h
+//
+
+//
+// Precompiled headers.
+//
+//*****************************************************************************
+#ifndef __STDAFX_H_
+#define __STDAFX_H_
+
+#include <crtwrap.h>
+#include <winwrap.h>
+#include <utilcode.h>
+
+#include <cor.h>
+#include <corpriv.h>
+
+#include <ndpversion.h>
+#include "nsutilpriv.h"
+
+#include "utsem.h"
+
+#endif // __STDAFX_H_
diff --git a/src/md/winmd/winmdimport.cpp b/src/md/winmd/winmdimport.cpp
new file mode 100644
index 0000000000..fe80bf0b04
--- /dev/null
+++ b/src/md/winmd/winmdimport.cpp
@@ -0,0 +1,2132 @@
+// 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.
+
+
+
+#include "stdafx.h"
+#include "winmdinterfaces.h"
+#include "metadataexports.h"
+#include "inc/adapter.h"
+#include "strsafe.h"
+
+//========================================================================================
+// This metadata importer is exposed publically via CoCreateInstance(CLSID_CorMetaDataDispenser...).
+// when the target is a .winmd file. It applies a small number of on-the-fly
+// conversions to make the .winmd file look like a regular .NET assembly.
+//
+// Despite what the MSDN docs say, this importer only supports the reader interfaces and
+// a subset of them at that. Supporting the whole set would not be practical with an
+// on-the-fly translation strategy.
+//========================================================================================
+class WinMDImport : public IMetaDataImport2
+ , IMetaDataAssemblyImport
+ , IMetaDataWinMDImport
+ , IMetaDataValidate
+ , IMDCommon
+ , IMetaModelCommon
+ , IWinMDImport
+#ifdef FEATURE_METADATA_INTERNAL_APIS
+ , IGetIMDInternalImport
+#endif //FEATURE_METADATA_INTERNAL_APIS
+{
+ public:
+ //=========================================================
+ // Factory
+ //=========================================================
+ static HRESULT Create(IMDCommon *pRawMDCommon, WinMDImport **ppWinMDImport)
+ {
+ HRESULT hr;
+ *ppWinMDImport = NULL;
+
+ WinMDImport *pNewWinMDImport = new (nothrow) WinMDImport(pRawMDCommon);
+
+ IfFailGo(pNewWinMDImport->m_pRawMDCommon->QueryInterface(IID_IMetaDataImport2, (void**)&pNewWinMDImport->m_pRawImport));
+ IfFailGo(pNewWinMDImport->m_pRawImport->QueryInterface(IID_IMetaDataAssemblyImport, (void**)&pNewWinMDImport->m_pRawAssemblyImport));
+
+ if (FAILED(pNewWinMDImport->m_pRawImport->QueryInterface(IID_IMetaDataValidate, (void**)&pNewWinMDImport->m_pRawValidate)))
+ {
+ pNewWinMDImport->m_pRawValidate = nullptr;
+ }
+
+ pNewWinMDImport->m_pRawMetaModelCommonRO = pRawMDCommon->GetMetaModelCommonRO();
+
+ IfFailGo(WinMDAdapter::Create(pRawMDCommon, &pNewWinMDImport->m_pWinMDAdapter));
+
+ (*ppWinMDImport = pNewWinMDImport)->AddRef();
+ hr = S_OK;
+
+ ErrExit:
+ if (pNewWinMDImport)
+ pNewWinMDImport->Release();
+ return hr;
+ }
+
+
+ private:
+ //=========================================================
+ // Ctors, Dtors
+ //=========================================================
+ WinMDImport(IMDCommon * pRawMDCommon)
+ {
+ m_cRef = 1;
+ m_pRawImport = NULL;
+ m_pWinMDAdapter = NULL;
+ m_pRawAssemblyImport = NULL;
+ m_pFreeThreadedMarshaler = NULL;
+ (m_pRawMDCommon = pRawMDCommon)->AddRef();
+ }
+
+ //---------------------------------------------------------
+ ~WinMDImport()
+ {
+ if (m_pRawMDCommon)
+ m_pRawMDCommon->Release();
+ if (m_pRawImport)
+ m_pRawImport->Release();
+ if (m_pRawAssemblyImport)
+ m_pRawAssemblyImport->Release();
+ if (m_pRawValidate)
+ m_pRawValidate->Release();
+ if (m_pFreeThreadedMarshaler)
+ m_pFreeThreadedMarshaler->Release();
+ delete m_pWinMDAdapter;
+ }
+
+ //---------------------------------------------------------
+ BOOL IsValidNonNilToken(mdToken token, DWORD tkKind)
+ {
+ DWORD tkKindActual = TypeFromToken(token);
+ DWORD rid = RidFromToken(token);
+
+ if (tkKindActual != tkKind)
+ return FALSE;
+
+ if (rid == 0)
+ return FALSE;
+
+ ULONG ulRowCount = m_pRawMetaModelCommonRO->CommonGetRowCount(tkKind);
+ if (tkKind == mdtAssemblyRef)
+ return rid <= ulRowCount + m_pWinMDAdapter->GetExtraAssemblyRefCount();
+ else
+ return rid <= ulRowCount;
+ }
+
+ public:
+ //=========================================================
+ // IUnknown methods
+ //=========================================================
+ STDMETHODIMP QueryInterface(REFIID riid, void** ppUnk)
+ {
+ HRESULT hr;
+
+ *ppUnk = 0;
+ if (riid == IID_IUnknown || riid == IID_IWinMDImport)
+ *ppUnk = (IWinMDImport*)this;
+ else if (riid == IID_IMetaDataImport || riid == IID_IMetaDataImport2)
+ *ppUnk = (IMetaDataImport*)this;
+ else if (riid == IID_IMetaDataWinMDImport)
+ *ppUnk = (IMetaDataWinMDImport*)this;
+ else if (riid == IID_IMetaDataAssemblyImport)
+ *ppUnk = (IMetaDataAssemblyImport*)this;
+ else if (riid == IID_IMDCommon)
+ *ppUnk = (IMDCommon*)this;
+ else if (riid == IID_IMetaDataValidate)
+ {
+ if (m_pRawValidate == NULL)
+ {
+ return E_NOINTERFACE;
+ }
+
+ *ppUnk = (IMetaDataValidate*)this;
+ }
+#ifdef FEATURE_METADATA_INTERNAL_APIS
+ else if (riid == IID_IGetIMDInternalImport)
+ *ppUnk = (IGetIMDInternalImport*)this;
+#endif // FEATURE_METADATA_INTERNAL_APIS
+ else if (riid == IID_IMarshal)
+ {
+ if (m_pFreeThreadedMarshaler == NULL)
+ {
+ ReleaseHolder<IUnknown> pFreeThreadedMarshaler = NULL;
+ IfFailRet(CoCreateFreeThreadedMarshaler((IUnknown *)(IMetaDataImport *)this, &pFreeThreadedMarshaler));
+ if (InterlockedCompareExchangeT<IUnknown *>(&m_pFreeThreadedMarshaler, pFreeThreadedMarshaler, NULL) == NULL)
+ { // We won the initialization race
+ pFreeThreadedMarshaler.SuppressRelease();
+ }
+ }
+ return m_pFreeThreadedMarshaler->QueryInterface(riid, ppUnk);
+ }
+ else
+ {
+#ifndef DACCESS_COMPILE
+#ifdef _DEBUG
+ if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_MD_WinMD_AssertOnIllegalUsage))
+ {
+ if (riid == IID_IMetaDataTables)
+ _ASSERTE(!"WinMDImport::QueryInterface(IID_IMetaDataTables) returning E_NOINTERFACE");
+ else if (riid == IID_IMetaDataTables2)
+ _ASSERTE(!"WinMDImport::QueryInterface(IID_IMetaDataTables2) returning E_NOINTERFACE");
+ else if (riid == IID_IMetaDataInfo)
+ _ASSERTE(!"WinMDImport::QueryInterface(IID_IMetaDataInfo) returning E_NOINTERFACE");
+ else if (riid == IID_IMetaDataEmit)
+ _ASSERTE(!"WinMDImport::QueryInterface(IID_IMetaDataEmit) returning E_NOINTERFACE");
+ else if (riid == IID_IMetaDataEmit2)
+ _ASSERTE(!"WinMDImport::QueryInterface(IID_IMetaDataEmit2) returning E_NOINTERFACE");
+ else if (riid == IID_IMetaDataAssemblyEmit)
+ _ASSERTE(!"WinMDImport::QueryInterface(IID_IMetaDataAssemblyEmit) returning E_NOINTERFACE");
+ else if (riid == IID_IMetaDataValidate)
+ _ASSERTE(!"WinMDImport::QueryInterface(IID_IMetaDataValidate) returning E_NOINTERFACE");
+ else if (riid == IID_IMetaDataFilter)
+ _ASSERTE(!"WinMDImport::QueryInterface(IID_IMetaDataFilter) returning E_NOINTERFACE");
+ else if (riid == IID_IMetaDataHelper)
+ _ASSERTE(!"WinMDImport::QueryInterface(IID_IMetaDataHelper) returning E_NOINTERFACE");
+ else if (riid == IID_IMDInternalEmit)
+ _ASSERTE(!"WinMDImport::QueryInterface(IID_IMDInternalEmit) returning E_NOINTERFACE");
+ else if (riid == IID_IMetaDataEmitHelper)
+ _ASSERTE(!"WinMDImport::QueryInterface(IID_IMetaDataEmitHelper) returning E_NOINTERFACE");
+ else if (riid == IID_IMetaDataCorProfileData)
+ _ASSERTE(!"WinMDImport::QueryInterface(IID_IMetaDataCorProfileData) returning E_NOINTERFACE");
+ else if (riid == IID_IMDInternalMetadataReorderingOptions)
+ _ASSERTE(!"WinMDImport::QueryInterface(IID_IMDInternalMetadataReorderingOptions) returning E_NOINTERFACE");
+ else
+ _ASSERTE(!"WinMDImport::QueryInterface() returning E_NOINTERFACE");
+ }
+#endif //_DEBUG
+#endif
+ return E_NOINTERFACE;
+ }
+ AddRef();
+ return S_OK;
+ }
+ //---------------------------------------------------------
+ STDMETHODIMP_(ULONG) AddRef(void)
+ {
+ return InterlockedIncrement(&m_cRef);
+ }
+ //---------------------------------------------------------
+ STDMETHODIMP_(ULONG) Release(void)
+ {
+ ULONG cRef = InterlockedDecrement(&m_cRef);
+ if (!cRef)
+ delete this;
+ return cRef;
+ }
+
+ public:
+ //=========================================================
+ // IWinMDImport methods
+ //=========================================================
+ STDMETHODIMP IsScenarioWinMDExp(BOOL *pbResult)
+ {
+ if (pbResult == NULL)
+ return E_POINTER;
+
+ *pbResult = m_pWinMDAdapter->IsScenarioWinMDExp();
+ return S_OK;
+ }
+
+ STDMETHODIMP IsRuntimeClassImplementation(mdTypeDef tkTypeDef, BOOL *pbResult)
+ {
+ if (pbResult == NULL)
+ return E_POINTER;
+
+ return m_pWinMDAdapter->IsRuntimeClassImplementation(tkTypeDef, pbResult);
+ }
+
+ //=========================================================
+ // IMetaDataImport methods
+ //=========================================================
+ STDMETHODIMP_(void) CloseEnum(HCORENUM hEnum)
+ {
+ m_pRawImport->CloseEnum(hEnum);
+ }
+
+ STDMETHODIMP CountEnum(HCORENUM hEnum, ULONG *pulCount)
+ {
+ _ASSERTE(pulCount != NULL); // Crash on NULL pulCount (just like real RegMeta)
+ if (hEnum != NULL)
+ {
+ HENUMInternal *henuminternal = static_cast<HENUMInternal*>(hEnum);
+ // Special case: We hijack MethodImpl enum's
+ if (henuminternal->m_tkKind == (TBL_MethodImpl << 24))
+ {
+ *pulCount = henuminternal->m_ulCount / 2; // MethodImpl enum's are weird - their entries are body/decl pairs so the internal count is twice the number the caller wants to see.
+ return S_OK;
+ }
+ }
+
+ return m_pRawImport->CountEnum(hEnum, pulCount);
+ }
+
+ STDMETHODIMP ResetEnum(HCORENUM hEnum, ULONG ulPos)
+ {
+ return m_pRawImport->ResetEnum(hEnum, ulPos);
+ }
+
+ STDMETHODIMP EnumTypeDefs(HCORENUM *phEnum, mdTypeDef rTypeDefs[],
+ ULONG cMax, ULONG *pcTypeDefs)
+ {
+ return m_pRawImport->EnumTypeDefs(phEnum, rTypeDefs, cMax, pcTypeDefs);
+ }
+
+ STDMETHODIMP EnumInterfaceImpls(HCORENUM *phEnum, mdTypeDef td,
+ mdInterfaceImpl rImpls[], ULONG cMax,
+ ULONG* pcImpls)
+ {
+ return m_pRawImport->EnumInterfaceImpls(phEnum, td, rImpls, cMax, pcImpls);
+ }
+
+ STDMETHODIMP EnumTypeRefs(HCORENUM *phEnum, mdTypeRef rTypeRefs[],
+ ULONG cMax, ULONG* pcTypeRefs)
+ {
+ // No trick needed: a previous call to EnumTypeRefs must have already taken care of the
+ // extra type refs.
+ return m_pRawImport->EnumTypeRefs(phEnum, rTypeRefs, cMax, pcTypeRefs);
+ }
+
+ STDMETHODIMP FindTypeDefByName( // S_OK or error.
+ LPCWSTR wszTypeDef, // [IN] Name of the Type.
+ mdToken tkEnclosingClass, // [IN] TypeDef/TypeRef for Enclosing class.
+ mdTypeDef *ptd) // [OUT] Put the TypeDef token here.
+ {
+ if (wszTypeDef == NULL) // E_INVALIDARG on NULL szTypeDef (just like real RegMeta)
+ return E_INVALIDARG;
+ _ASSERTE(ptd != NULL); // AV on NULL ptd (just like real RegMeta)
+ *ptd = mdTypeDefNil;
+
+ LPUTF8 szFullName;
+ LPCUTF8 szNamespace;
+ LPCUTF8 szName;
+ // Convert the name to UTF8.
+ UTF8STR(wszTypeDef, szFullName);
+ ns::SplitInline(szFullName, szNamespace, szName);
+
+ return m_pWinMDAdapter->FindTypeDef(szNamespace, szName, tkEnclosingClass, ptd);
+ }
+
+
+ STDMETHODIMP GetScopeProps( // S_OK or error.
+ __out_ecount_part_opt(cchName, *pchName)
+ 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.
+ {
+ // Returns error code from name filling (may be CLDB_S_TRUNCTATION)
+ return m_pRawImport->GetScopeProps(szName, cchName, pchName, pmvid);
+ }
+
+
+ STDMETHODIMP GetModuleFromScope( // S_OK.
+ mdModule *pmd) // [OUT] Put mdModule token here.
+ {
+ return m_pRawImport->GetModuleFromScope(pmd);
+ }
+
+
+ STDMETHODIMP GetTypeDefProps( // S_OK or error.
+ mdTypeDef td, // [IN] TypeDef token for inquiry.
+ __out_ecount_part_opt(cchTypeDef, *pchTypeDef)
+ 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.
+ {
+ HRESULT hr;
+ LPCSTR szNamespace;
+ LPCSTR szName;
+ if (!IsValidNonNilToken(td, mdtTypeDef))
+ {
+ // Idiosyncractic edge cases - delegate straight through to inherit the correct idiosyncractic edge results
+ return m_pRawImport->GetTypeDefProps(td, szTypeDef, cchTypeDef, pchTypeDef, pdwTypeDefFlags, ptkExtends);
+ }
+ IfFailRet(m_pWinMDAdapter->GetTypeDefProps(td, &szNamespace, &szName, pdwTypeDefFlags, ptkExtends));
+ // Returns error code from name filling (may be CLDB_S_TRUNCTATION)
+ return DeliverUtf8NamespaceAndName(szNamespace, szName, szTypeDef, cchTypeDef, pchTypeDef);
+ }
+
+
+ STDMETHODIMP 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.
+ {
+ return m_pRawImport->GetInterfaceImplProps(iiImpl, pClass, ptkIface);
+ }
+
+
+ STDMETHODIMP GetTypeRefProps( // S_OK or error.
+ mdTypeRef tr, // [IN] TypeRef token.
+ mdToken *ptkResolutionScope, // [OUT] Resolution scope, ModuleRef or AssemblyRef.
+ __out_ecount_part_opt(cchName, *pchName)
+ LPWSTR szName, // [OUT] Name of the TypeRef.
+ ULONG cchName, // [IN] Size of buffer.
+ ULONG *pchName) // [OUT] Size of Name.
+ {
+ HRESULT hr;
+ if (!IsValidNonNilToken(tr, mdtTypeRef))
+ {
+ // Idiosyncratic edge cases - delegate straight through to inherit the correct idiosyncratic edge result
+ return m_pRawImport->GetTypeRefProps(tr, ptkResolutionScope, szName, cchName, pchName);
+ }
+
+ LPCUTF8 szUtf8Namespace;
+ LPCUTF8 szUtf8Name;
+ mdToken tkResolutionScope;
+ IfFailRet(CommonGetTypeRefProps(tr, &szUtf8Namespace, &szUtf8Name, &tkResolutionScope));
+ if (ptkResolutionScope != NULL)
+ {
+ *ptkResolutionScope = tkResolutionScope;
+ }
+ // Returns error code from name filling (may be CLDB_S_TRUNCTATION)
+ return DeliverUtf8NamespaceAndName(szUtf8Namespace, szUtf8Name, szName, cchName, pchName);
+ }
+
+
+ STDMETHODIMP ResolveTypeRef(mdTypeRef tr, REFIID riid, IUnknown **ppIScope, mdTypeDef *ptd)
+ {
+ WINMD_COMPAT_ASSERT("IMetaDataImport::ResolveTypeRef() not supported on .winmd files.");
+ return E_NOTIMPL;
+ }
+
+
+ STDMETHODIMP 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.
+ {
+ return m_pRawImport->EnumMembers(phEnum, cl, rMembers, cMax, pcTokens);
+ }
+
+
+ STDMETHODIMP 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.
+ {
+ return m_pRawImport->EnumMembersWithName(phEnum, cl, szName, rMembers, cMax, pcTokens);
+ }
+
+
+ STDMETHODIMP 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.
+ {
+ return m_pRawImport->EnumMethods(phEnum, cl, rMethods, cMax, pcTokens);
+ }
+
+
+ STDMETHODIMP 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.
+ {
+ return m_pRawImport->EnumMethodsWithName(phEnum, cl, szName, rMethods, cMax, pcTokens);
+ }
+
+
+ STDMETHODIMP 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.
+ {
+ return m_pRawImport->EnumFields(phEnum, cl, rFields, cMax, pcTokens);
+ }
+
+
+ STDMETHODIMP 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.
+ {
+ return m_pRawImport->EnumFieldsWithName(phEnum, cl, szName, rFields, cMax, pcTokens);
+ }
+
+
+
+ STDMETHODIMP 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.
+ {
+ return m_pRawImport->EnumParams(phEnum, mb, rParams, cMax, pcTokens);
+ }
+
+
+ STDMETHODIMP 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.
+ {
+ return m_pRawImport->EnumMemberRefs(phEnum, tkParent, rMemberRefs, cMax, pcTokens);
+ }
+
+
+ STDMETHODIMP 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.
+ {
+ // Note: This wrapper emulates the underlying RegMeta's parameter validation semantics:
+ // Pass a bad phEnum: Instant AV
+ // Pass out of range typedef: returns S_FALSE (i.e. generates empty list)
+ // Pass non-typedef: returns S_FALSE with assert
+ // Pass bad output ptr for bodies or decls, AV
+ // Pass bad output ptr for pcTokens, AV (but NULL is allowed.)
+
+ HRESULT hr;
+ HENUMInternal **ppmdEnum = reinterpret_cast<HENUMInternal **> (phEnum);
+ HENUMInternal *pEnum = *ppmdEnum;
+
+ if ( pEnum == 0 )
+ {
+ // Create the enumerator, DynamicArrayEnum does not use the token type.
+ IfFailGo( HENUMInternal::CreateDynamicArrayEnum( (TBL_MethodImpl << 24), &pEnum) );
+ IfFailGo( m_pWinMDAdapter->AddMethodImplsToEnum(td, pEnum));
+ // set the output parameter
+ *ppmdEnum = pEnum;
+ }
+
+ // fill the output token buffer
+ hr = HENUMInternal::EnumWithCount(pEnum, cMax, rMethodBody, rMethodDecl, pcTokens);
+
+ ErrExit:
+ HENUMInternal::DestroyEnumIfEmpty(ppmdEnum);
+ return hr;
+ }
+
+
+ STDMETHODIMP 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.
+ {
+ return m_pRawImport->EnumPermissionSets(phEnum, tk, dwActions, rPermission, cMax, pcTokens);
+ }
+
+
+ STDMETHODIMP FindMember(
+ mdTypeDef td, // [IN] given typedef
+ LPCWSTR szName, // [IN] member name
+ PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature
+ ULONG cbSigBlob, // [IN] count of bytes in the signature blob
+ mdToken *pmb) // [OUT] matching memberdef
+ {
+ HRESULT hr = FindMethod(
+ td,
+ szName,
+ pvSigBlob,
+ cbSigBlob,
+ pmb);
+
+ if (hr == CLDB_E_RECORD_NOTFOUND)
+ {
+ // now try field table
+ hr = FindField(
+ td,
+ szName,
+ pvSigBlob,
+ cbSigBlob,
+ pmb);
+ }
+
+ return hr;
+ }
+
+
+ STDMETHODIMP FindMethod(
+ mdTypeDef td, // [IN] given typedef
+ LPCWSTR szName, // [IN] member name
+ PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature
+ ULONG cbSigBlob, // [IN] count of bytes in the signature blob
+ mdMethodDef *pmb) // [OUT] matching memberdef
+ {
+ if (pvSigBlob == NULL || cbSigBlob == 0)
+ {
+ // if signature matching is not needed, we can delegate to the underlying implementation
+ return m_pRawImport->FindMethod(td, szName, pvSigBlob, cbSigBlob, pmb);
+ }
+
+ // The following code emulates RegMeta::FindMethod. We cannot call the underlying
+ // implementation because we need to compare pvSigBlob to reinterpreted signatures.
+ HRESULT hr = S_OK;
+ HCORENUM hEnum = NULL;
+
+ CQuickBytes qbSig; // holds non-varargs signature
+ CQuickArray<WCHAR> rName;
+
+ if (szName == NULL || pmb == NULL)
+ IfFailGo(E_INVALIDARG);
+
+ *pmb = mdMethodDefNil;
+
+ // check to see if this is a vararg signature
+ PCCOR_SIGNATURE pvSigTemp = pvSigBlob;
+ if (isCallConv(CorSigUncompressCallingConv(pvSigTemp), IMAGE_CEE_CS_CALLCONV_VARARG))
+ {
+ // Get the fixed part of VARARG signature
+ IfFailGo(_GetFixedSigOfVarArg(pvSigBlob, cbSigBlob, &qbSig, &cbSigBlob));
+ pvSigBlob = (PCCOR_SIGNATURE) qbSig.Ptr();
+ }
+
+ // now iterate all methods in td and compare name and signature
+ IfNullGo(rName.AllocNoThrow(wcslen(szName) + 1));
+
+ mdMethodDef md;
+ ULONG count;
+ while ((hr = EnumMethods(&hEnum, td, &md, 1, &count)) == S_OK)
+ {
+ PCCOR_SIGNATURE pvMethodSigBlob;
+ ULONG cbMethodSigBlob;
+ ULONG chMethodName;
+ DWORD dwMethodAttr;
+
+ IfFailGo(GetMethodProps(md, NULL, rName.Ptr(), (ULONG)rName.Size(), &chMethodName, &dwMethodAttr, &pvMethodSigBlob, &cbMethodSigBlob, NULL, NULL));
+
+ if (chMethodName == rName.Size() && wcscmp(szName, rName.Ptr()) == 0)
+ {
+ // we have a name match, check signature
+ if (cbSigBlob != cbMethodSigBlob || memcmp(pvSigBlob, pvMethodSigBlob, cbSigBlob) != 0)
+ continue;
+
+ // ignore PrivateScope methods
+ if (IsMdPrivateScope(dwMethodAttr))
+ continue;
+
+ // we found the method
+ *pmb = md;
+ goto ErrExit;
+ }
+ }
+ IfFailGo(hr);
+ hr = CLDB_E_RECORD_NOTFOUND;
+
+ ErrExit:
+ if (hEnum != NULL)
+ CloseEnum(hEnum);
+
+ return hr;
+ }
+
+
+ STDMETHODIMP FindField(
+ mdTypeDef td, // [IN] given typedef
+ LPCWSTR szName, // [IN] member name
+ PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature
+ ULONG cbSigBlob, // [IN] count of bytes in the signature blob
+ mdFieldDef *pmb) // [OUT] matching memberdef
+ {
+ if (pvSigBlob == NULL || cbSigBlob == 0)
+ {
+ // if signature matching is not needed, we can delegate to the underlying implementation
+ return m_pRawImport->FindField(td, szName, pvSigBlob, cbSigBlob, pmb);
+ }
+
+ // The following code emulates RegMeta::FindField. We cannot call the underlying
+ // implementation because we need to compare pvSigBlob to reinterpreted signatures.
+ HRESULT hr = S_OK;
+ HCORENUM hEnum = NULL;
+
+ CQuickArray<WCHAR> rName;
+
+ if (szName == NULL || pmb == NULL)
+ IfFailGo(E_INVALIDARG);
+
+ *pmb = mdFieldDefNil;
+
+ // now iterate all fields in td and compare name and signature
+ IfNullGo(rName.AllocNoThrow(wcslen(szName) + 1));
+
+ mdFieldDef fd;
+ ULONG count;
+ while ((hr = EnumFields(&hEnum, td, &fd, 1, &count)) == S_OK)
+ {
+ PCCOR_SIGNATURE pvFieldSigBlob;
+ ULONG cbFieldSigBlob;
+ ULONG chFieldName;
+ DWORD dwFieldAttr;
+
+ IfFailGo(GetFieldProps(fd, NULL, rName.Ptr(), (ULONG)rName.Size(), &chFieldName, &dwFieldAttr, &pvFieldSigBlob, &cbFieldSigBlob, NULL, NULL, NULL));
+
+ if (chFieldName == rName.Size() && wcscmp(szName, rName.Ptr()) == 0)
+ {
+ // we have a name match, check signature
+ if (cbSigBlob != cbFieldSigBlob || memcmp(pvSigBlob, pvFieldSigBlob, cbSigBlob) != 0)
+ continue;
+
+ // ignore PrivateScope fields
+ if (IsFdPrivateScope(dwFieldAttr))
+ continue;
+
+ // we found the field
+ *pmb = fd;
+ goto ErrExit;
+ }
+ }
+ IfFailGo(hr);
+ hr = CLDB_E_RECORD_NOTFOUND;
+
+ ErrExit:
+ if (hEnum != NULL)
+ CloseEnum(hEnum);
+
+ return hr;
+ }
+
+
+ STDMETHODIMP FindMemberRef(
+ mdTypeRef td, // [IN] given typeRef
+ LPCWSTR szName, // [IN] member name
+ PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature
+ ULONG cbSigBlob, // [IN] count of bytes in the signature blob
+ mdMemberRef *pmr) // [OUT] matching memberref
+ {
+ if (pvSigBlob == NULL || cbSigBlob == 0)
+ {
+ // if signature matching is not needed, we can delegate to the underlying implementation
+ return m_pRawImport->FindMemberRef(td, szName, pvSigBlob, cbSigBlob, pmr);
+ }
+
+ // The following code emulates RegMeta::FindMemberRef. We cannot call the underlying
+ // implementation because we need to compare pvSigBlob to reinterpreted signatures.
+ HRESULT hr = S_OK;
+ HCORENUM hEnum = NULL;
+
+ CQuickArray<WCHAR> rName;
+
+ if (szName == NULL || pmr == NULL)
+ IfFailGo(CLDB_E_RECORD_NOTFOUND);
+
+ *pmr = mdMemberRefNil;
+
+ // now iterate all members in td and compare name and signature
+ IfNullGo(rName.AllocNoThrow(wcslen(szName) + 1));
+
+ mdMemberRef rd;
+ ULONG count;
+ while ((hr = EnumMemberRefs(&hEnum, td, &rd, 1, &count)) == S_OK)
+ {
+ PCCOR_SIGNATURE pvMemberSigBlob;
+ ULONG cbMemberSigBlob;
+ ULONG chMemberName;
+
+ IfFailGo(GetMemberRefProps(rd, NULL, rName.Ptr(), (ULONG)rName.Size(), &chMemberName, &pvMemberSigBlob, &cbMemberSigBlob));
+
+ if (chMemberName == rName.Size() && wcscmp(szName, rName.Ptr()) == 0)
+ {
+ // we have a name match, check signature
+ if (cbSigBlob != cbMemberSigBlob || memcmp(pvSigBlob, pvMemberSigBlob, cbSigBlob) != 0)
+ continue;
+
+ // we found the member
+ *pmr = rd;
+ goto ErrExit;
+ }
+ }
+ IfFailGo(hr);
+ hr = CLDB_E_RECORD_NOTFOUND;
+
+ ErrExit:
+ if (hEnum != NULL)
+ CloseEnum(hEnum);
+
+ return hr;
+ }
+
+
+ STDMETHODIMP GetMethodProps(
+ mdMethodDef mb, // The method for which to get props.
+ mdTypeDef *pClass, // Put method's class here.
+ __out_ecount_part_opt(cchMethod, *pchMethod)
+ 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
+ {
+ HRESULT hr;
+ HRESULT hrNameTruncation;
+ if (!IsValidNonNilToken(mb, mdtMethodDef))
+ {
+ // Idiosyncratic edge cases - delegate straight through to inherit the correct idiosyncratic edge result
+ return m_pRawImport->GetMethodProps(mb, pClass, szMethod, cchMethod, pchMethod, pdwAttr, ppvSigBlob, pcbSigBlob, pulCodeRVA, pdwImplFlags);
+ }
+
+ ULONG cbOrigSigBlob = (ULONG)(-1);
+ PCCOR_SIGNATURE pOrigSig = NULL;
+ IfFailRet(hrNameTruncation = m_pRawImport->GetMethodProps(mb, pClass, szMethod, cchMethod, pchMethod, pdwAttr, &pOrigSig, &cbOrigSigBlob, pulCodeRVA, pdwImplFlags));
+
+ IfFailRet((m_pWinMDAdapter->GetSignatureForToken<IMetaDataImport2, mdtMethodDef>(
+ mb,
+ &pOrigSig, // ppOrigSig
+ &cbOrigSigBlob, // pcbOrigSig
+ ppvSigBlob,
+ pcbSigBlob,
+ m_pRawImport)));
+
+ LPCSTR szNewName = NULL;
+ IfFailRet(m_pWinMDAdapter->ModifyMethodProps(mb, pdwAttr, pdwImplFlags, pulCodeRVA, &szNewName));
+ if (szNewName != NULL)
+ {
+ // We want to return name truncation status from the method that really fills the output buffer, rewrite the previous value
+ IfFailRet(hrNameTruncation = DeliverUtf8String(szNewName, szMethod, cchMethod, pchMethod));
+ }
+
+ // Return the success code from name filling (S_OK or CLDB_S_TRUNCATION)
+ return hrNameTruncation;
+ }
+
+
+ STDMETHODIMP GetMemberRefProps( // S_OK or error.
+ mdMemberRef mr, // [IN] given memberref
+ mdToken *ptk, // [OUT] Put classref or classdef here.
+ __out_ecount_part_opt(cchMember, *pchMember)
+ 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
+ {
+ HRESULT hr = S_OK;
+ HRESULT hrNameTruncation;
+
+ ULONG cbOrigSigBlob = (ULONG)(-1);
+ PCCOR_SIGNATURE pOrigSig = NULL;
+ IfFailRet(hrNameTruncation = m_pRawImport->GetMemberRefProps(mr, ptk, szMember, cchMember, pchMember, &pOrigSig, &cbOrigSigBlob));
+ LPCSTR szNewName = NULL;
+ IfFailRet(m_pWinMDAdapter->ModifyMemberProps(mr, NULL, NULL, NULL, &szNewName));
+ IfFailRet((m_pWinMDAdapter->GetSignatureForToken<IMetaDataImport2, mdtMemberRef>(
+ mr,
+ &pOrigSig, // ppOrigSig
+ &cbOrigSigBlob, // pcbOrigSig
+ ppvSigBlob,
+ pbSig,
+ m_pRawImport)));
+ if (szNewName != NULL)
+ {
+ // We want to return name truncation status from the method that really fills the output buffer, rewrite the previous value
+ IfFailRet(hrNameTruncation = DeliverUtf8String(szNewName, szMember, cchMember, pchMember));
+ }
+ // Return the success code from name filling (S_OK or CLDB_S_TRUNCATION)
+ return hrNameTruncation;
+ }
+
+
+ STDMETHODIMP 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.
+ {
+ return m_pRawImport->EnumProperties(phEnum, td, rProperties, cMax, pcProperties);
+ }
+
+
+ STDMETHODIMP 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.
+ {
+ return m_pRawImport->EnumEvents(phEnum, td, rEvents, cMax, pcEvents);
+ }
+
+
+ STDMETHODIMP 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
+ {
+ // Returns error code from name filling (may be CLDB_S_TRUNCTATION)
+ return m_pRawImport->GetEventProps(ev, pClass, szEvent, cchEvent, pchEvent, pdwEventFlags, ptkEventType, pmdAddOn, pmdRemoveOn, pmdFire, rmdOtherMethod, cMax, pcOtherMethod);
+ }
+
+
+ STDMETHODIMP 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.
+ {
+ return m_pRawImport->EnumMethodSemantics(phEnum, mb, rEventProp, cMax, pcEventProp);
+ }
+
+ STDMETHODIMP 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
+ {
+ return m_pRawImport->GetMethodSemantics(mb, tkEventProp, pdwSemanticsFlags);
+ }
+
+
+ STDMETHODIMP 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
+ {
+ return m_pRawImport->GetClassLayout(td, pdwPackSize, rFieldOffset, cMax, pcFieldOffset, pulClassSize);
+ }
+
+
+ STDMETHODIMP 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
+ {
+ return m_pRawImport->GetFieldMarshal(tk, ppvNativeType, pcbNativeType);
+ }
+
+
+ STDMETHODIMP GetRVA( // S_OK or error.
+ mdToken tk, // Member for which to set offset
+ ULONG *pulCodeRVA, // The offset
+ DWORD *pdwImplFlags) // the implementation flags
+ {
+ HRESULT hr;
+ if (!IsValidNonNilToken(tk, mdtMethodDef))
+ {
+ // Idiosyncratic edge cases - delegate straight through to inherit the correct idiosyncratic edge result
+ return m_pRawImport->GetRVA(tk, pulCodeRVA, pdwImplFlags);
+ }
+
+ IfFailRet(m_pRawImport->GetRVA(tk, pulCodeRVA, pdwImplFlags));
+ IfFailRet(m_pWinMDAdapter->ModifyMethodProps(tk, NULL, pdwImplFlags, pulCodeRVA, NULL));
+ return hr;
+ }
+
+
+ STDMETHODIMP 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.
+ {
+ return m_pRawImport->GetPermissionSetProps(pm, pdwAction, ppvPermission, pcbPermission);
+ }
+
+
+ STDMETHODIMP 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.
+ {
+ // mdSignature is not part of public WinMD surface, so it does not need signature rewriting
+ return m_pRawImport->GetSigFromToken(mdSig, ppvSig, pcbSig);
+ }
+
+ STDMETHODIMP GetModuleRefProps( // S_OK or error.
+ mdModuleRef mur, // [IN] moduleref token.
+ __out_ecount_part_opt(cchName, *pchName)
+ 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.
+ {
+ // Returns error code from name filling (may be CLDB_S_TRUNCTATION)
+ return m_pRawImport->GetModuleRefProps(mur, szName, cchName, pchName);
+ }
+
+
+ STDMETHODIMP 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.
+ {
+ return m_pRawImport->EnumModuleRefs(phEnum, rModuleRefs, cmax, pcModuleRefs);
+ }
+
+
+ STDMETHODIMP 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.
+ {
+ return m_pWinMDAdapter->GetSignatureForToken<IMetaDataImport2, mdtTypeSpec>(
+ typespec,
+ NULL, // ppOrigSig
+ NULL, // pcbOrigSig
+ ppvSig,
+ pcbSig,
+ m_pRawImport);
+ }
+
+
+ STDMETHODIMP 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.
+ {
+ HRESULT hr;
+
+ if (!IsValidNonNilToken(tk, mdtTypeRef))
+ {
+ // Handle corner error case
+ IfFailGo(m_pRawImport->GetNameFromToken(tk, pszUtf8NamePtr));
+ }
+ else
+ {
+ IfFailGo(m_pWinMDAdapter->GetTypeRefProps(tk, NULL, pszUtf8NamePtr, NULL));
+ }
+
+ ErrExit:
+ return hr;
+ }
+
+
+ STDMETHODIMP 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.
+ {
+ return m_pRawImport->EnumUnresolvedMethods(phEnum, rMethods, cMax, pcTokens);
+ }
+
+
+ STDMETHODIMP GetUserString( // S_OK or error.
+ mdString stk, // [IN] String token.
+ __out_ecount_part_opt(cchString, *pchString)
+ LPWSTR szString, // [OUT] Copy of string.
+ ULONG cchString, // [IN] Max chars of room in szString.
+ ULONG *pchString) // [OUT] How many chars in actual string.
+ {
+ // Returns error code from name filling (may be CLDB_S_TRUNCTATION)
+ return m_pRawImport->GetUserString(stk, szString, cchString, pchString);
+ }
+
+
+ STDMETHODIMP GetPinvokeMap( // S_OK or error.
+ mdToken tk, // [IN] FieldDef or MethodDef.
+ DWORD *pdwMappingFlags, // [OUT] Flags used for mapping.
+ __out_ecount_part_opt(cchImportName, *pchImportName)
+ 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.
+ {
+ // Returns error code from name filling (may be CLDB_S_TRUNCTATION)
+ return m_pRawImport->GetPinvokeMap(tk, pdwMappingFlags, szImportName, cchImportName, pchImportName, pmrImportDLL);
+ }
+
+
+ STDMETHODIMP 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.
+ {
+ return m_pRawImport->EnumSignatures(phEnum, rSignatures, cmax, pcSignatures);
+ }
+
+
+ STDMETHODIMP 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.
+ {
+ return m_pRawImport->EnumTypeSpecs(phEnum, rTypeSpecs, cmax, pcTypeSpecs);
+ }
+
+
+ STDMETHODIMP 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.
+ {
+ return m_pRawImport->EnumUserStrings(phEnum, rStrings, cmax, pcStrings);
+ }
+
+
+ STDMETHODIMP GetParamForMethodIndex( // S_OK or error.
+ mdMethodDef md, // [IN] Method token.
+ ULONG ulParamSeq, // [IN] Parameter sequence.
+ mdParamDef *ppd) // [IN] Put Param token here.
+ {
+ return m_pRawImport->GetParamForMethodIndex(md, ulParamSeq, ppd);
+ }
+
+
+ STDMETHODIMP 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.
+ {
+ return m_pRawImport->EnumCustomAttributes(phEnum, tk, tkType, rCustomAttributes, cMax, pcCustomAttributes);
+ }
+
+
+ STDMETHODIMP 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.
+ {
+ HRESULT hr;
+ if (!IsValidNonNilToken(cv, mdtCustomAttribute))
+ {
+ // Idiosyncratic edge cases - delegate straight through to inherit the correct idiosyncratic edge result
+ return m_pRawImport->GetCustomAttributeProps(cv, ptkObj, ptkType, ppBlob, pcbSize);
+ }
+ IfFailRet(m_pRawImport->GetCustomAttributeProps(cv, ptkObj, ptkType, NULL, NULL));
+ IfFailRet(m_pWinMDAdapter->GetCustomAttributeBlob(cv, ppBlob, pcbSize));
+ return hr;
+ }
+
+
+ STDMETHODIMP FindTypeRef(
+ mdToken tkResolutionScope, // [IN] ModuleRef, AssemblyRef or TypeRef.
+ LPCWSTR wzTypeName, // [IN] TypeRef Name.
+ mdTypeRef *ptr) // [OUT] matching TypeRef.
+ {
+
+ HRESULT hr;
+ LPUTF8 szFullName;
+ LPCUTF8 szNamespace;
+ LPCUTF8 szName;
+
+ _ASSERTE(wzTypeName && ptr);
+ *ptr = mdTypeRefNil; // AV if caller passes NULL: just like the real RegMeta.
+
+ // Convert the name to UTF8.
+ PREFIX_ASSUME(wzTypeName != NULL); // caller might pass NULL, but they'll AV (just like the real RegMeta)
+ UTF8STR(wzTypeName, szFullName);
+ ns::SplitInline(szFullName, szNamespace, szName);
+ hr = m_pWinMDAdapter->FindTypeRef(szNamespace, szName, tkResolutionScope, ptr);
+
+ return hr;
+ }
+
+
+ STDMETHODIMP GetMemberProps(
+ mdToken mb, // The member for which to get props.
+ mdTypeDef *pClass, // Put member's class here.
+ __out_ecount_part_opt(cchMember, *pchMember)
+ 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.
+ {
+ HRESULT hr;
+ HRESULT hrNameTruncation;
+ if (!IsValidNonNilToken(mb, mdtMethodDef) && !IsValidNonNilToken(mb, mdtFieldDef))
+ {
+ // Idiosyncratic edge cases - delegate straight through to inherit the correct idiosyncratic edge result
+ return m_pRawImport->GetMemberProps(mb, pClass, szMember, cchMember, pchMember, pdwAttr, ppvSigBlob, pcbSigBlob, pulCodeRVA, pdwImplFlags, pdwCPlusTypeFlag, ppValue, pcchValue);
+ }
+
+ PCCOR_SIGNATURE pOrigSig;
+ ULONG cbOrigSig;
+
+ IfFailRet(hrNameTruncation = m_pRawImport->GetMemberProps(mb, pClass, szMember, cchMember, pchMember, pdwAttr, &pOrigSig, &cbOrigSig, pulCodeRVA, pdwImplFlags, pdwCPlusTypeFlag, ppValue, pcchValue));
+
+ LPCSTR szNewName = NULL;
+ IfFailRet(m_pWinMDAdapter->ModifyMemberProps(mb, pdwAttr, pdwImplFlags, pulCodeRVA, &szNewName));
+
+ if (IsValidNonNilToken(mb, mdtMethodDef))
+ {
+ IfFailRet((m_pWinMDAdapter->GetSignatureForToken<IMetaDataImport2, mdtMethodDef>(
+ mb,
+ &pOrigSig, // ppOrigSig
+ &cbOrigSig, // pcbOrigSig
+ ppvSigBlob,
+ pcbSigBlob,
+ m_pRawImport)));
+ }
+ else if (IsValidNonNilToken(mb, mdtFieldDef))
+ {
+ IfFailRet((m_pWinMDAdapter->GetSignatureForToken<IMetaDataImport2, mdtFieldDef>(
+ mb,
+ &pOrigSig, // ppOrigSig
+ &cbOrigSig, // pcbOrigSig
+ ppvSigBlob,
+ pcbSigBlob,
+ m_pRawImport)));
+ }
+ else
+ {
+ if (ppvSigBlob != NULL)
+ *ppvSigBlob = pOrigSig;
+
+ if (pcbSigBlob != NULL)
+ *pcbSigBlob = cbOrigSig;
+ }
+
+ if (szNewName != NULL)
+ {
+ // We want to return name truncation status from the method that really fills the output buffer, rewrite the previous value
+ IfFailRet(hrNameTruncation = DeliverUtf8String(szNewName, szMember, cchMember, pchMember));
+ }
+
+ // Return the success code from name filling (S_OK or CLDB_S_TRUNCATION)
+ return hrNameTruncation;
+ }
+
+
+ STDMETHODIMP 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.
+ {
+ HRESULT hr;
+ HRESULT hrNameTruncation;
+
+ PCCOR_SIGNATURE pOrigSig;
+ ULONG cbOrigSig;
+ IfFailRet(hrNameTruncation = m_pRawImport->GetFieldProps(mb, pClass, szField, cchField, pchField, pdwAttr, &pOrigSig, &cbOrigSig, pdwCPlusTypeFlag, ppValue, pcchValue));
+
+ IfFailRet(m_pWinMDAdapter->ModifyFieldDefProps(mb, pdwAttr));
+ IfFailRet((m_pWinMDAdapter->GetSignatureForToken<IMetaDataImport2, mdtFieldDef>(
+ mb,
+ &pOrigSig,
+ &cbOrigSig,
+ ppvSigBlob,
+ pcbSigBlob,
+ m_pRawImport)));
+
+ // Return the success code from name filling (S_OK or CLDB_S_TRUNCATION)
+ return hrNameTruncation;
+ }
+
+
+ STDMETHODIMP 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
+ {
+ HRESULT hr = S_OK;
+ HRESULT hrNameTruncation;
+
+ ULONG cbOrigSigBlob = (ULONG)(-1);
+ PCCOR_SIGNATURE pOrigSig = NULL;
+ IfFailRet(hrNameTruncation = m_pRawImport->GetPropertyProps(prop, pClass, szProperty, cchProperty, pchProperty, pdwPropFlags, &pOrigSig, &cbOrigSigBlob, pdwCPlusTypeFlag, ppDefaultValue, pcchDefaultValue, pmdSetter, pmdGetter, rmdOtherMethod, cMax, pcOtherMethod));
+
+ IfFailRet((m_pWinMDAdapter->GetSignatureForToken<IMetaDataImport2, mdtProperty>(
+ prop,
+ &pOrigSig, // ppOrigSig
+ &cbOrigSigBlob, // pcbOrigSig
+ ppvSig,
+ pbSig,
+ m_pRawImport)));
+ // Return the success code from name filling (S_OK or CLDB_S_TRUNCATION)
+ return hrNameTruncation;
+ }
+
+
+ STDMETHODIMP GetParamProps( // S_OK or error.
+ mdParamDef tk, // [IN]The Parameter.
+ mdMethodDef *pmd, // [OUT] Parent Method token.
+ ULONG *pulSequence, // [OUT] Parameter sequence.
+ __out_ecount_part_opt(cchName, *pchName)
+ 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.
+ {
+ // Returns error code from name filling (may be CLDB_S_TRUNCTATION)
+ return m_pRawImport->GetParamProps(tk, pmd, pulSequence, szName, cchName, pchName, pdwAttr, pdwCPlusTypeFlag, ppValue, pcchValue);
+ }
+
+
+ STDMETHODIMP GetCustomAttributeByName( // S_OK or error.
+ mdToken tkObj, // [IN] Object with Custom Attribute.
+ LPCWSTR wszName, // [IN] Name of desired Custom Attribute.
+ const void **ppData, // [OUT] Put pointer to data here.
+ ULONG *pcbData) // [OUT] Put size of data here.
+ {
+ HRESULT hr;
+ if (wszName == NULL)
+ {
+ hr = S_FALSE; // Questionable response but maintains compatibility with RegMeta
+ }
+ else
+ {
+ MAKE_UTF8PTR_FROMWIDE_NOTHROW(szName, wszName);
+ IfNullGo(szName);
+ IfFailGo(CommonGetCustomAttributeByName(tkObj, szName, ppData, pcbData));
+ }
+ ErrExit:
+ return hr;
+ }
+
+
+ STDMETHODIMP_(BOOL) IsValidToken( // True or False.
+ mdToken tk) // [IN] Given token.
+ {
+ mdToken tokenType = TypeFromToken(tk);
+ if (tokenType == mdtAssemblyRef)
+ return m_pWinMDAdapter->IsValidAssemblyRefToken(tk);
+
+ return m_pRawImport->IsValidToken(tk);
+ }
+
+
+ STDMETHODIMP GetNestedClassProps( // S_OK or error.
+ mdTypeDef tdNestedClass, // [IN] NestedClass token.
+ mdTypeDef *ptdEnclosingClass) // [OUT] EnclosingClass token.
+ {
+ return m_pRawImport->GetNestedClassProps(tdNestedClass, ptdEnclosingClass);
+ }
+
+
+ STDMETHODIMP 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).
+ {
+ return m_pRawImport->GetNativeCallConvFromSig(pvSig, cbSig, pCallConv);
+ }
+
+
+ STDMETHODIMP IsGlobal( // S_OK or error.
+ mdToken pd, // [IN] Type, Field, or Method token.
+ int *pbGlobal) // [OUT] Put 1 if global, 0 otherwise.
+ {
+ return m_pRawImport->IsGlobal(pd, pbGlobal);
+ }
+
+ public:
+
+ // ========================================================
+ // IMetaDataWinMDImport methods
+ // ========================================================
+
+ // This method returns the RAW view of the metadata. Essentially removing the Adapter's projection support for the typeRef.
+ STDMETHODIMP GetUntransformedTypeRefProps(
+ mdTypeRef tr, // [IN] TypeRef token.
+ mdToken *ptkResolutionScope, // [OUT] Resolution scope, ModuleRef or AssemblyRef.
+ __out_ecount_part_opt(cchName, *pchName)
+ LPWSTR szName, // [OUT] Unprojected name of the TypeRef.
+ ULONG cchName, // [IN] Size of buffer.
+ ULONG *pchName) // [OUT] Size of Name.
+ {
+ // By-pass the call to the raw importer, removing the adapter layer.
+ return m_pRawImport->GetTypeRefProps(tr, ptkResolutionScope, szName, cchName, pchName);
+ }
+
+ //=========================================================
+ // IMetaDataImport2 methods
+ //=========================================================
+ STDMETHODIMP EnumGenericParams(
+ 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.
+ {
+ return m_pRawImport->EnumGenericParams(phEnum, tk, rGenericParams, cMax, pcGenericParams);
+ }
+
+
+ STDMETHODIMP 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_part_opt(cchName, *pchName)
+ LPWSTR wzname, // [OUT] Put name here
+ ULONG cchName, // [IN] Size of buffer
+ ULONG *pchName) // [OUT] Put size of name (wide chars) here.
+ {
+ // Returns error code from name filling (may be CLDB_S_TRUNCTATION)
+ return m_pRawImport->GetGenericParamProps(gp, pulParamSeq, pdwParamFlags, ptOwner, reserved, wzname, cchName, pchName);
+ }
+
+
+ STDMETHODIMP 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
+ {
+ HRESULT hr = S_OK;
+
+ ULONG cbOrigSigBlob = (ULONG)(-1);
+ PCCOR_SIGNATURE pOrigSig = NULL;
+ IfFailRet(m_pRawImport->GetMethodSpecProps(mi, tkParent, &pOrigSig, &cbOrigSigBlob));
+
+ return m_pWinMDAdapter->GetSignatureForToken<IMetaDataImport2, mdtMethodSpec>(
+ mi,
+ &pOrigSig, // ppOrigSig
+ &cbOrigSigBlob, // pcbOrigSig
+ ppvSigBlob,
+ pcbSigBlob,
+ m_pRawImport);
+ }
+
+
+ STDMETHODIMP EnumGenericParamConstraints(
+ 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.
+ {
+ return m_pRawImport->EnumGenericParamConstraints(phEnum, tk, rGenericParamConstraints, cMax, pcGenericParamConstraints);
+ }
+
+
+ STDMETHODIMP GetGenericParamConstraintProps( // S_OK or error.
+ mdGenericParamConstraint gpc, // [IN] GenericParamConstraint
+ mdGenericParam *ptGenericParam, // [OUT] GenericParam that is constrained
+ mdToken *ptkConstraintType) // [OUT] TypeDef/Ref/Spec constraint
+ {
+ return m_pRawImport->GetGenericParamConstraintProps(gpc, ptGenericParam, ptkConstraintType);
+ }
+
+
+ STDMETHODIMP 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
+ {
+ return m_pRawImport->GetPEKind(pdwPEKind, pdwMachine);
+ }
+
+
+ STDMETHODIMP GetVersionString( // S_OK or error.
+ __out_ecount_part_opt(ccBufSize, *pccBufSize)
+ LPWSTR pwzBuf, // [OUT] 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;
+ LPCSTR szVersion;
+ IfFailRet(GetVersionString(&szVersion));
+ // Returns error code from name filling (may be CLDB_S_TRUNCTATION)
+ return DeliverUtf8String(szVersion, pwzBuf, ccBufSize, pccBufSize);
+ }
+
+
+ STDMETHODIMP 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.
+ {
+ return m_pRawImport->EnumMethodSpecs(phEnum, tk, rMethodSpecs, cMax, pcMethodSpecs);
+ }
+
+
+ public:
+ //=========================================================
+ // 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_part_opt(cchName, *pchName) LPWSTR szName, // [OUT] Buffer to fill with assembly's simply 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.
+ {
+ return m_pRawAssemblyImport->GetAssemblyProps(mda, ppbPublicKey, pcbPublicKey, pulHashAlgId, szName, cchName, pchName, pMetaData, pdwAssemblyFlags);
+ }
+
+
+ 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_part_opt(cchName, *pchName)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;
+ HRESULT hrNameTruncation;
+
+ if (!IsValidNonNilToken(mdar, mdtAssemblyRef))
+ {
+ // Idiosyncratic edge cases - delegate straight through to inherit the correct idiosyncratic edge result
+ return m_pRawAssemblyImport->GetAssemblyRefProps(mdar, ppbPublicKeyOrToken, pcbPublicKeyOrToken, szName, cchName, pchName, pMetaData, ppbHashValue, pcbHashValue, pdwAssemblyRefFlags);
+ }
+
+ mdAssemblyRef md = mdar;
+ if (RidFromToken(md) > m_pWinMDAdapter->GetRawAssemblyRefCount())
+ {
+ // The extra framework assemblies we add references to should all have the
+ // same verion, key, culture, etc as those of mscorlib.
+ // So we retrieve the mscorlib properties and change the name.
+ md = m_pWinMDAdapter->GetAssemblyRefMscorlib();
+ }
+
+ IfFailRet(hrNameTruncation = m_pRawAssemblyImport->GetAssemblyRefProps(md, ppbPublicKeyOrToken, pcbPublicKeyOrToken, szName, cchName, pchName, pMetaData, ppbHashValue, pcbHashValue, pdwAssemblyRefFlags));
+
+ LPCSTR szNewName = nullptr;
+ USHORT *pusMajorVersion = nullptr;
+ USHORT *pusMinorVersion = nullptr;
+ USHORT *pusBuildNumber = nullptr;
+ USHORT *pusRevisionNumber = nullptr;
+
+ if (pMetaData != nullptr)
+ {
+ pusMajorVersion = &pMetaData->usMajorVersion;
+ pusMinorVersion = &pMetaData->usMinorVersion;
+ pusBuildNumber = &pMetaData->usBuildNumber;
+ pusRevisionNumber = &pMetaData->usRevisionNumber;
+ }
+
+ m_pWinMDAdapter->ModifyAssemblyRefProps(
+ mdar,
+ ppbPublicKeyOrToken,
+ pcbPublicKeyOrToken,
+ &szNewName,
+ pusMajorVersion,
+ pusMinorVersion,
+ pusBuildNumber,
+ pusRevisionNumber,
+ ppbHashValue,
+ pcbHashValue);
+
+ if (szNewName != nullptr)
+ {
+ IfFailRet(hrNameTruncation = DeliverUtf8String(szNewName, szName, cchName, pchName));
+ }
+
+ // Return the success code from name filling (S_OK or CLDB_S_TRUNCATION)
+ return hrNameTruncation;
+ }
+
+
+ STDMETHODIMP GetFileProps( // S_OK or error.
+ mdFile mdf, // [IN] The File for which to get the properties.
+ __out_ecount_part_opt(cchName, *pchName) 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.
+ {
+ // Returns error code from name filling (may be CLDB_S_TRUNCTATION)
+ return m_pRawAssemblyImport->GetFileProps(mdf, szName, cchName, pchName, ppbHashValue, pcbHashValue, pdwFileFlags);
+ }
+
+
+ STDMETHODIMP GetExportedTypeProps( // S_OK or error.
+ mdExportedType mdct, // [IN] The ExportedType for which to get the properties.
+ __out_ecount_part_opt(cchName, *pchName) 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.
+ {
+ HRESULT hr;
+ LPCSTR szUtf8Namespace;
+ LPCSTR szUtf8Name;
+ if (!IsValidNonNilToken(mdct, mdtExportedType))
+ {
+ // Idiosyncractic edge cases - delegate straight through to inherit the correct idiosyncractic edge results
+ return m_pRawAssemblyImport->GetExportedTypeProps(mdct, szName, cchName, pchName, ptkImplementation, ptkTypeDef, pdwExportedTypeFlags);
+ }
+ IfFailRet(m_pRawAssemblyImport->GetExportedTypeProps(mdct, NULL, 0, NULL, NULL, ptkTypeDef, pdwExportedTypeFlags));
+ IfFailRet(this->CommonGetExportedTypeProps(mdct, &szUtf8Namespace, &szUtf8Name, ptkImplementation));
+ // Returns error code from name filling (may be CLDB_S_TRUNCTATION)
+ return DeliverUtf8NamespaceAndName(szUtf8Namespace, szUtf8Name, szName, cchName, pchName);
+ }
+
+
+ STDMETHODIMP GetManifestResourceProps( // S_OK or error.
+ mdManifestResource mdmr, // [IN] The ManifestResource for which to get the properties.
+ __out_ecount_part_opt(cchName, *pchName)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.
+ {
+ // Returns error code from name filling (may be CLDB_S_TRUNCTATION)
+ return m_pRawAssemblyImport->GetManifestResourceProps(mdmr, szName, cchName, pchName, ptkImplementation, pdwOffset, pdwResourceFlags);
+ }
+
+
+ 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.
+ {
+ if (*phEnum != NULL)
+ {
+ // No trick needed: a previous call to EnumAssemblyRefs must have already taken care of the
+ // extra assembly refs.
+ return m_pRawAssemblyImport->EnumAssemblyRefs(phEnum, rAssemblyRefs, cMax, pcTokens);
+ }
+ else
+ {
+ // if *phEnum is NULL, we need create the HENUMInternal, adjust the assembly ref count,
+ // and enumerate the number of assembly refs requested. This is done in three steps:
+ HRESULT hr;
+
+ // Step 1: Call EnumAssemblyRefs with an empty buffer to create the HENUMInternal
+ IfFailGo(m_pRawAssemblyImport->EnumAssemblyRefs(phEnum, NULL, 0, NULL));
+
+ // Step 2: Increment the cound to include the extra assembly refs
+ HENUMInternal *phInternalEnum = static_cast<HENUMInternal*>(*phEnum);
+
+ _ASSERTE(phInternalEnum->m_EnumType == MDSimpleEnum);
+
+ _ASSERTE( phInternalEnum->m_ulCount == m_pWinMDAdapter->GetRawAssemblyRefCount());
+ int n = m_pWinMDAdapter->GetExtraAssemblyRefCount();
+ phInternalEnum->m_ulCount += n;
+ phInternalEnum->u.m_ulEnd += n;
+
+ // Step 3: Call EnumAssemblyRefs again and pass in the modifed HENUMInternal and the real buffer
+ IfFailGo(m_pRawAssemblyImport->EnumAssemblyRefs(phEnum, rAssemblyRefs, cMax, pcTokens));
+
+ErrExit:
+ return hr;
+ }
+ }
+
+
+ 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.
+ {
+ return m_pRawAssemblyImport->EnumFiles(phEnum, rFiles, cMax, pcTokens);
+ }
+
+
+ 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.
+ {
+ return m_pRawAssemblyImport->EnumExportedTypes(phEnum, rExportedTypes, cMax, pcTokens);
+ }
+
+
+ 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.
+ {
+ return m_pRawAssemblyImport->EnumManifestResources(phEnum, rManifestResources, cMax, pcTokens);
+ }
+
+
+ STDMETHODIMP GetAssemblyFromScope( // S_OK or error
+ mdAssembly *ptkAssembly) // [OUT] Put token here.
+ {
+ return m_pRawAssemblyImport->GetAssemblyFromScope(ptkAssembly);
+ }
+
+
+ STDMETHODIMP FindExportedTypeByName( // S_OK or error
+ LPCWSTR wszName, // [IN] Name of the ExportedType.
+ mdToken mdtExportedType, // [IN] ExportedType for the enclosing class.
+ mdExportedType *ptkExportedType) // [OUT] Put the ExportedType token here.
+ {
+ if (wszName == NULL)
+ return E_INVALIDARG;
+
+ LPUTF8 szFullName;
+ LPCUTF8 szNamespace;
+ LPCUTF8 szName;
+ // Convert the name to UTF8.
+ UTF8STR(wszName, szFullName);
+ ns::SplitInline(szFullName, szNamespace, szName);
+ return this->CommonFindExportedType(szNamespace, szName, mdtExportedType, ptkExportedType);
+ }
+
+
+ STDMETHODIMP FindManifestResourceByName( // S_OK or error
+ LPCWSTR szName, // [IN] Name of the ManifestResource.
+ mdManifestResource *ptkManifestResource) // [OUT] Put the ManifestResource token here.
+ {
+ return m_pRawAssemblyImport->FindManifestResourceByName(szName, ptkManifestResource);
+ }
+
+
+
+ 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.
+ {
+ return m_pRawAssemblyImport->FindAssembliesByName(szAppBase, szPrivateBin, szAssemblyName, ppIUnk, cMax, pcAssemblies);
+ }
+
+ //=========================================================
+ // IMetaDataValidate
+ //=========================================================
+ STDMETHODIMP ValidatorInit( // S_OK or error.
+ DWORD dwModuleType, // [IN] Specifies the type of the module.
+ IUnknown *pUnk) // [IN] Validation error handler.
+ {
+ if (m_pRawValidate == nullptr)
+ return E_NOTIMPL;
+
+ return m_pRawValidate->ValidatorInit(dwModuleType, pUnk);
+ }
+
+ STDMETHODIMP ValidateMetaData() // S_OK or error.
+ {
+ if (m_pRawValidate == nullptr)
+ return E_NOTIMPL;
+
+ return m_pRawValidate->ValidateMetaData();
+ }
+
+ //=========================================================
+ // IMDCommon methods
+ //=========================================================
+ STDMETHODIMP_(IMetaModelCommon*) GetMetaModelCommon()
+ {
+ return this;
+ }
+
+ STDMETHODIMP_(IMetaModelCommonRO*) GetMetaModelCommonRO()
+ {
+ _ASSERTE(!"WinMDImport does not support GetMetaModelCommonRO(). The most likely cause of this assert is that you're trying to wrap a WinMD adapter around another WinMD adapter.");
+ return NULL;
+ }
+
+ STDMETHODIMP GetVersionString(LPCSTR *pszVersionString)
+ {
+ return m_pWinMDAdapter->GetVersionString(pszVersionString);
+ }
+
+
+ //=========================================================
+ // IMetaModelCommon methods
+ //=========================================================
+ __checkReturn
+ virtual HRESULT CommonGetScopeProps(
+ LPCUTF8 *pszName,
+ GUID *pMvid)
+ {
+ return m_pRawMetaModelCommonRO->CommonGetScopeProps(pszName, pMvid);
+ }
+
+ __checkReturn
+ virtual HRESULT CommonGetTypeRefProps(
+ mdTypeRef tr,
+ LPCUTF8 *pszNamespace,
+ LPCUTF8 *pszName,
+ mdToken *ptkResolution)
+ {
+ return m_pWinMDAdapter->GetTypeRefProps(tr, pszNamespace, pszName, ptkResolution);
+ }
+
+
+ __checkReturn
+ virtual HRESULT CommonGetTypeDefProps(
+ mdTypeDef td,
+ LPCUTF8 *pszNameSpace,
+ LPCUTF8 *pszName,
+ DWORD *pdwFlags,
+ mdToken *pdwExtends,
+ ULONG *pMethodList)
+ {
+ HRESULT hr;
+ IfFailGo(m_pRawMetaModelCommonRO->CommonGetTypeDefProps(td, NULL, NULL, NULL, NULL, pMethodList));
+ IfFailGo(m_pWinMDAdapter->GetTypeDefProps(td, pszNameSpace, pszName, pdwFlags, pdwExtends));
+ ErrExit:
+ return hr;
+ }
+
+
+ __checkReturn
+ virtual HRESULT CommonGetTypeSpecProps(
+ mdTypeSpec ts,
+ PCCOR_SIGNATURE *ppvSig,
+ ULONG *pcbSig)
+ {
+ return m_pWinMDAdapter->GetSignatureForToken<IMetaDataImport2, mdtTypeSpec>(
+ ts,
+ NULL, // ppOrigSig
+ NULL, // pcbOrigSig
+ ppvSig,
+ pcbSig,
+ m_pRawImport);
+ }
+
+
+ __checkReturn
+ virtual HRESULT CommonGetEnclosingClassOfTypeDef(
+ mdTypeDef td,
+ mdTypeDef *ptkEnclosingTypeDef)
+ {
+ return m_pRawMetaModelCommonRO->CommonGetEnclosingClassOfTypeDef(td, ptkEnclosingTypeDef);
+ }
+
+
+ __checkReturn
+ virtual HRESULT CommonGetAssemblyProps(
+ USHORT *pusMajorVersion,
+ USHORT *pusMinorVersion,
+ USHORT *pusBuildNumber,
+ USHORT *pusRevisionNumber,
+ DWORD *pdwFlags,
+ const void **ppbPublicKey,
+ ULONG *pcbPublicKey,
+ LPCUTF8 *pszName,
+ LPCUTF8 *pszLocale)
+ {
+ return m_pRawMetaModelCommonRO->CommonGetAssemblyProps(pusMajorVersion, pusMinorVersion, pusBuildNumber, pusRevisionNumber, pdwFlags, ppbPublicKey, pcbPublicKey, pszName, pszLocale);
+ }
+
+
+ __checkReturn
+ virtual HRESULT CommonGetAssemblyRefProps(
+ mdAssemblyRef tkAssemRef,
+ USHORT *pusMajorVersion,
+ USHORT *pusMinorVersion,
+ USHORT *pusBuildNumber,
+ USHORT *pusRevisionNumber,
+ DWORD *pdwFlags,
+ const void **ppbPublicKeyOrToken,
+ ULONG *pcbPublicKeyOrToken,
+ LPCUTF8 *pszName,
+ LPCUTF8 *pszLocale,
+ const void **ppbHashValue,
+ ULONG *pcbHashValue)
+ {
+ HRESULT hr;
+
+ mdAssemblyRef md = tkAssemRef;
+ if (RidFromToken(md) > m_pWinMDAdapter->GetRawAssemblyRefCount())
+ {
+ // The extra framework assemblies we add references to should all have the
+ // same verion, key, culture, etc as those of mscorlib.
+ // So we retrieve the mscorlib properties and change the name.
+ md = m_pWinMDAdapter->GetAssemblyRefMscorlib();
+ }
+
+ IfFailRet(m_pRawMetaModelCommonRO->CommonGetAssemblyRefProps(
+ md,
+ pusMajorVersion,
+ pusMinorVersion,
+ pusBuildNumber,
+ pusRevisionNumber,
+ pdwFlags,
+ ppbPublicKeyOrToken,
+ pcbPublicKeyOrToken,
+ pszName,
+ pszLocale,
+ ppbHashValue,
+ pcbHashValue));
+
+ m_pWinMDAdapter->ModifyAssemblyRefProps(
+ tkAssemRef,
+ ppbPublicKeyOrToken,
+ pcbPublicKeyOrToken,
+ pszName,
+ pusMajorVersion,
+ pusMinorVersion,
+ pusBuildNumber,
+ pusRevisionNumber,
+ ppbHashValue,
+ pcbHashValue);
+
+ return hr;
+ }
+
+
+ __checkReturn
+ virtual HRESULT CommonGetModuleRefProps(
+ mdModuleRef tkModuleRef,
+ LPCUTF8 *pszName)
+ {
+ return m_pRawMetaModelCommonRO->CommonGetModuleRefProps(tkModuleRef, pszName);
+ }
+
+
+ __checkReturn
+ virtual HRESULT CommonFindExportedType(
+ LPCUTF8 szNamespace,
+ LPCUTF8 szName,
+ mdToken tkEnclosingType,
+ mdExportedType *ptkExportedType)
+ {
+ return m_pWinMDAdapter->FindExportedType(szNamespace, szName, tkEnclosingType, ptkExportedType);
+ }
+
+
+ __checkReturn
+ virtual HRESULT CommonGetExportedTypeProps(
+ mdToken tkExportedType,
+ LPCUTF8 *pszNamespace,
+ LPCUTF8 *pszName,
+ mdToken *ptkImpl)
+ {
+ HRESULT hr;
+ IfFailRet(m_pRawMetaModelCommonRO->CommonGetExportedTypeProps(tkExportedType, pszNamespace, pszName, ptkImpl));
+ IfFailRet(m_pWinMDAdapter->ModifyExportedTypeName(tkExportedType, pszNamespace, pszName));
+ return hr;
+ }
+
+
+ virtual int CommonIsRo()
+ {
+ return m_pRawMetaModelCommonRO->CommonIsRo();
+ }
+
+
+ __checkReturn
+ virtual HRESULT CommonGetCustomAttributeByNameEx( // S_OK or error.
+ mdToken tkObj, // [IN] Object with Custom Attribute.
+ LPCUTF8 szName, // [IN] Name of desired Custom Attribute.
+ mdCustomAttribute *ptkCA, // [OUT] put custom attribute token here
+ const void **ppData, // [OUT] Put pointer to data here.
+ ULONG *pcbData) // [OUT] Put size of data here.
+ {
+ return m_pWinMDAdapter->GetCustomAttributeByName(tkObj, szName, ptkCA, ppData, pcbData);
+ }
+
+
+ __checkReturn
+ virtual HRESULT FindParentOfMethodHelper(mdMethodDef md, mdTypeDef *ptd)
+ {
+ return m_pRawMetaModelCommonRO->FindParentOfMethodHelper(md, ptd);
+ }
+
+
+
+ public:
+ //=========================================================
+ // IGetIMDInternalImport methods
+ //=========================================================
+ STDMETHODIMP GetIMDInternalImport(IMDInternalImport ** ppIMDInternalImport)
+ {
+ HRESULT hr = S_OK;
+ ReleaseHolder<IMDCommon> pMDCommon;
+ ReleaseHolder<IUnknown> pRawMDInternalImport;
+
+ *ppIMDInternalImport = NULL;
+ // Get the raw IMDInternalImport
+ IfFailGo(GetMDInternalInterfaceFromPublic(m_pRawImport, IID_IMDInternalImport, (LPVOID*)(&pRawMDInternalImport)));
+
+ // Create an adapter around the internal raw interface
+ IfFailGo(pRawMDInternalImport->QueryInterface(IID_IMDCommon, (LPVOID*)(&pMDCommon)));
+ IfFailGo(CreateWinMDInternalImportRO(pMDCommon, IID_IMDInternalImport, (void**)ppIMDInternalImport));
+
+ ErrExit:
+ return hr;
+ }
+
+
+ //=========================================================
+ // Private methods
+ //=========================================================
+
+ //------------------------------------------------------------------------------------------------------
+ // Deliver a result string (Unicode) to a caller's sized output buffer using the standard convention
+ // followed by all metadata api.
+ //------------------------------------------------------------------------------------------------------
+ static HRESULT DeliverUnicodeString(LPCWSTR wszResult, __out_ecount_part(cchCallerBuffer, *pchSizeNeeded) LPWSTR wszCallerBuffer, ULONG cchCallerBuffer, ULONG *pchSizeNeeded)
+ {
+ ULONG cchActual = (ULONG)(wcslen(wszResult) + 1);
+ if (pchSizeNeeded)
+ {
+ *pchSizeNeeded = cchActual;
+ }
+ if (wszCallerBuffer == NULL || cchCallerBuffer < cchActual)
+ {
+ if (wszCallerBuffer != NULL)
+ {
+ memcpy(wszCallerBuffer, wszResult, cchCallerBuffer * sizeof(WCHAR)); // If buffer too small, return truncated result to be compatible with metadata api conventions
+ if (cchCallerBuffer > 0)
+ { // null-terminate the truncated output string
+ wszCallerBuffer[cchCallerBuffer - 1] = W('\0');
+ }
+ }
+ return CLDB_S_TRUNCATION;
+ }
+ else
+ {
+ memcpy(wszCallerBuffer, wszResult, cchActual * sizeof(WCHAR));
+ return S_OK;
+ }
+ }
+
+ //------------------------------------------------------------------------------------------------------
+ // Deliver a result string (Utf8) to a caller's sized output buffer using the standard convention
+ // followed by all metadata api.
+ //------------------------------------------------------------------------------------------------------
+ static HRESULT DeliverUtf8String(LPCSTR szUtf8Result, __out_ecount_part(cchCallerBuffer, *pchSizeNeeded) LPWSTR wszCallerBuffer, ULONG cchCallerBuffer, ULONG *pchSizeNeeded)
+ {
+ MAKE_WIDEPTR_FROMUTF8_NOTHROW(wzResult, szUtf8Result);
+ if (wzResult == NULL)
+ return E_OUTOFMEMORY;
+ return DeliverUnicodeString(wzResult, wszCallerBuffer, cchCallerBuffer, pchSizeNeeded);
+ }
+
+ //------------------------------------------------------------------------------------------------------
+ // Combine a result namespace/name string pair (Utf8) to a Unicode fullname and deliver to a caller's
+ // sized output buffer using the standard convention followed by all metadata api.
+ //------------------------------------------------------------------------------------------------------
+ static HRESULT DeliverUtf8NamespaceAndName(LPCSTR szUtf8Namespace, LPCSTR szUtf8Name, __out_ecount_part(cchCallerBuffer, *pchSizeNeeded) LPWSTR wszCallerBuffer, ULONG cchCallerBuffer, ULONG *pchSizeNeeded)
+ {
+ HRESULT hr;
+ if (wszCallerBuffer != NULL || pchSizeNeeded != NULL)
+ {
+ MAKE_WIDEPTR_FROMUTF8_NOTHROW(wzNamespace, szUtf8Namespace);
+ IfNullRet(wzNamespace);
+ MAKE_WIDEPTR_FROMUTF8_NOTHROW(wzName, szUtf8Name);
+ IfNullRet(wzName);
+
+ BOOL fTruncation = FALSE;
+ if (wszCallerBuffer != NULL)
+ {
+ fTruncation = !(ns::MakePath(wszCallerBuffer, cchCallerBuffer, wzNamespace, wzName));
+ if (fTruncation && (cchCallerBuffer > 0))
+ { // null-terminate the truncated output string
+ wszCallerBuffer[cchCallerBuffer - 1] = W('\0');
+ }
+ }
+ if (pchSizeNeeded != NULL)
+ {
+ if (fTruncation || (wszCallerBuffer == NULL))
+ {
+ *pchSizeNeeded = ns::GetFullLength(wzNamespace, wzName);
+ }
+ else
+ {
+ *pchSizeNeeded = (ULONG)(wcslen(wszCallerBuffer) + 1);
+ }
+ }
+ hr = fTruncation ? CLDB_S_TRUNCATION : S_OK;
+ }
+ else
+ {
+ hr = S_OK; // Caller did not request name back.
+ }
+ return hr;
+ }
+
+ private:
+ //=========================================================
+ // Private instance data
+ //=========================================================
+ IMDCommon *m_pRawMDCommon;
+ IMetaDataImport2 *m_pRawImport;
+ IMetaDataAssemblyImport *m_pRawAssemblyImport;
+ IMetaDataValidate *m_pRawValidate;
+ IMetaModelCommonRO *m_pRawMetaModelCommonRO;
+ IUnknown *m_pFreeThreadedMarshaler;
+ WinMDAdapter *m_pWinMDAdapter;
+ LONG m_cRef;
+
+}; // class WinMDImport
+
+
+
+//========================================================================================
+// Entrypoint called by IMetaDataDispenser::OpenScope()
+//========================================================================================
+HRESULT CreateWinMDImport(IMDCommon * pRawMDCommon, REFIID riid, /*[out]*/ void **ppWinMDImport)
+{
+ HRESULT hr;
+ *ppWinMDImport = NULL;
+ WinMDImport *pWinMDImport = NULL;
+ IfFailGo(WinMDImport::Create(pRawMDCommon, &pWinMDImport));
+ IfFailGo(pWinMDImport->QueryInterface(riid, ppWinMDImport));
+ hr = S_OK;
+ ErrExit:
+ if (pWinMDImport)
+ pWinMDImport->Release();
+ return hr;
+}
diff --git a/src/md/winmd/winmdinternalimportro.cpp b/src/md/winmd/winmdinternalimportro.cpp
new file mode 100644
index 0000000000..70a54b88b3
--- /dev/null
+++ b/src/md/winmd/winmdinternalimportro.cpp
@@ -0,0 +1,1804 @@
+// 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.
+
+
+
+#include "stdafx.h"
+#include "winmdinterfaces.h"
+#include "inc/adapter.h"
+
+
+#ifdef FEATURE_METADATA_INTERNAL_APIS
+
+
+__checkReturn
+HRESULT TranslateSigHelper( // S_OK or error.
+ IMDInternalImport *pImport, // [IN] import scope.
+ IMDInternalImport *pAssemImport, // [IN] import assembly scope.
+ const void *pbHashValue, // [IN] hash value for the import assembly.
+ ULONG cbHashValue, // [IN] count of bytes in the hash value.
+ PCCOR_SIGNATURE pbSigBlob, // [IN] signature in the importing scope
+ ULONG cbSigBlob, // [IN] count of bytes of signature
+ IMetaDataAssemblyEmit *pAssemEmit, // [IN] assembly emit scope.
+ IMetaDataEmit *emit, // [IN] emit interface
+ CQuickBytes *pqkSigEmit, // [OUT] buffer to hold translated signature
+ ULONG *pcbSig); // [OUT] count of bytes in the translated signature
+
+
+//========================================================================================
+// This metadata importer is used internally by the runtime and exposes an
+// IMDInternalImport* on .winmd files. It applies a small number of on-the-fly
+// conversions to make the .winmd file look like a regular .NET assembly.
+//
+// All those places in src\vm where the runtime calls an IMDInternalImport*
+// pointer, it may now be talking to a WinMDInternalImportRO. Ideally, the
+// runtime will never know the difference (but this being an internal interface,
+// we may tolerate the occasional leakiness in the name of expediency.)
+//========================================================================================
+class WinMDInternalImportRO : public IMDInternalImport, IWinMDImport, IMetaModelCommon
+{
+ public:
+ //=========================================================
+ // Factory
+ //=========================================================
+ static HRESULT Create(IMDCommon *pRawMDCommon, WinMDInternalImportRO **ppWinMDInternalImportRO)
+ {
+ HRESULT hr;
+ *ppWinMDInternalImportRO = NULL;
+ WinMDInternalImportRO *pNewWinMDInternalImport = new (nothrow) WinMDInternalImportRO(pRawMDCommon);
+ IfFailGo(pRawMDCommon->QueryInterface(IID_IMDInternalImport, (void**)&(pNewWinMDInternalImport->m_pRawInternalImport)));
+ IfFailGo(WinMDAdapter::Create(pNewWinMDInternalImport->m_pRawMDCommon, &(pNewWinMDInternalImport->m_pWinMDAdapter)));
+ (*ppWinMDInternalImportRO = pNewWinMDInternalImport)->AddRef();
+ hr = S_OK;
+
+ ErrExit:
+ if (pNewWinMDInternalImport)
+ pNewWinMDInternalImport->Release();
+ return hr;
+ }
+
+ private:
+ //=========================================================
+ // Ctors, Dtors
+ //=========================================================
+ WinMDInternalImportRO(IMDCommon * pRawMDCommon)
+ : m_cRef(1)
+ , m_pWinMDAdapter(NULL)
+ , m_pRawInternalImport(NULL)
+ , m_pRawMDCommon(pRawMDCommon)
+ , m_pRawMetaModelCommon(pRawMDCommon->GetMetaModelCommon())
+ {
+ m_pRawMDCommon->AddRef();
+ }
+
+ //---------------------------------------------------------
+ ~WinMDInternalImportRO()
+ {
+ m_pRawMDCommon->Release();
+ m_pRawInternalImport->Release();
+ delete m_pWinMDAdapter;
+ }
+
+ public:
+ //=========================================================
+ // IUnknown methods
+ //=========================================================
+ STDMETHODIMP QueryInterface(REFIID riid, void** ppUnk)
+ {
+ *ppUnk = 0;
+ if (riid == IID_IUnknown || riid == IID_IWinMDImport)
+ *ppUnk = (IWinMDImport *) this;
+ else if (riid == IID_IMDInternalImport)
+ *ppUnk = (IMDInternalImport *) this;
+ else
+ {
+#ifndef DACCESS_COMPILE
+#ifdef _DEBUG
+ if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_MD_WinMD_AssertOnIllegalUsage))
+ {
+ if (riid == IID_IMDInternalImportENC)
+ _ASSERTE(!"WinMDInternalImportRO::QueryInterface(IID_IMDInternalImportENC) returning E_NOINTERFACE");
+ else if (riid == IID_IMarshal)
+ _ASSERTE(!"WinMDInternalImportRO::QueryInterface(IID_IMarshal) returning E_NOINTERFACE");
+ else
+ _ASSERTE(!"WinMDInternalImportRO::QueryInterface() returning E_NOINTERFACE");
+ }
+#endif //_DEBUG
+#endif
+ return E_NOINTERFACE;
+ }
+ AddRef();
+ return S_OK;
+ }
+ //---------------------------------------------------------
+ STDMETHODIMP_(ULONG) AddRef(void)
+ {
+ return InterlockedIncrement(&m_cRef);
+ }
+ //---------------------------------------------------------
+ STDMETHODIMP_(ULONG) Release(void)
+ {
+ ULONG cRef = InterlockedDecrement(&m_cRef);
+ if (!cRef)
+ delete this;
+ return cRef;
+ }
+
+ public:
+ //=========================================================
+ // IWinMDImport methods
+ //=========================================================
+ STDMETHODIMP IsScenarioWinMDExp(BOOL *pbResult)
+ {
+ if (pbResult == NULL)
+ return E_POINTER;
+
+ *pbResult = m_pWinMDAdapter->IsScenarioWinMDExp();
+ return S_OK;
+ }
+
+ STDMETHODIMP IsRuntimeClassImplementation(mdTypeDef tkTypeDef, BOOL *pbResult)
+ {
+ if (pbResult == NULL)
+ return E_POINTER;
+
+ return m_pWinMDAdapter->IsRuntimeClassImplementation(tkTypeDef, pbResult);
+ }
+
+ //=========================================================
+ // IMDInternalImport methods
+ //=========================================================
+ //*****************************************************************************
+ // return the count of entries of a given kind in a scope
+ // For example, pass in mdtMethodDef will tell you how many MethodDef
+ // contained in a scope
+ //*****************************************************************************
+ STDMETHODIMP_(ULONG) GetCountWithTokenKind(// return hresult
+ DWORD tkKind) // [IN] pass in the kind of token.
+ {
+ if (tkKind == mdtAssemblyRef)
+ {
+ return m_pRawInternalImport->GetCountWithTokenKind(tkKind) + m_pWinMDAdapter->GetExtraAssemblyRefCount();
+ }
+ else
+ {
+ return m_pRawInternalImport->GetCountWithTokenKind(tkKind);
+ }
+ }
+
+ //*****************************************************************************
+ // enumerator for typedef
+ //*****************************************************************************
+ __checkReturn
+ STDMETHODIMP EnumTypeDefInit( // return hresult
+ HENUMInternal *phEnum) // [OUT] buffer to fill for enumerator data
+ {
+ return m_pRawInternalImport->EnumTypeDefInit(phEnum);
+ }
+
+ STDMETHODIMP_(ULONG) EnumTypeDefGetCount(
+ HENUMInternal *phEnum) // [IN] the enumerator to retrieve information
+ {
+ return m_pRawInternalImport->EnumTypeDefGetCount(phEnum);
+ }
+
+ STDMETHODIMP_(void) EnumTypeDefReset(
+ HENUMInternal *phEnum) // [IN] the enumerator to retrieve information
+ {
+ return m_pRawInternalImport->EnumTypeDefReset(phEnum);
+ }
+
+ STDMETHODIMP_(bool) EnumTypeDefNext( // return hresult
+ HENUMInternal *phEnum, // [IN] input enum
+ mdTypeDef *ptd) // [OUT] return token
+ {
+ return m_pRawInternalImport->EnumTypeDefNext(phEnum, ptd);
+ }
+
+ STDMETHODIMP_(void) EnumTypeDefClose(
+ HENUMInternal *phEnum) // [IN] the enumerator to retrieve information
+ {
+ return m_pRawInternalImport->EnumTypeDefClose(phEnum);
+ }
+
+ //*****************************************************************************
+ // enumerator for MethodImpl
+ //*****************************************************************************
+ __checkReturn
+ STDMETHODIMP EnumMethodImplInit( // return hresult
+ mdTypeDef td, // [IN] TypeDef over which to scope the enumeration.
+ HENUMInternal *phEnumBody, // [OUT] buffer to fill for enumerator data for MethodBody tokens.
+ HENUMInternal *) // [OUT] used only on RW imports
+ {
+ HRESULT hr;
+ HENUMInternal::InitDynamicArrayEnum(phEnumBody);
+ phEnumBody->m_tkKind = TBL_MethodImpl << 24;
+ IfFailGo(m_pWinMDAdapter->AddMethodImplsToEnum(td, phEnumBody));
+ hr = S_OK;
+
+ ErrExit:
+ if (FAILED(hr))
+ {
+ HENUMInternal::ClearEnum(phEnumBody);
+ INDEBUG(memset(phEnumBody, 0xcc, sizeof(HENUMInternal)));
+ }
+ return hr;
+ }
+
+ STDMETHODIMP_(ULONG) EnumMethodImplGetCount(
+ HENUMInternal *phEnumBody, // [IN] MethodBody enumerator.
+ HENUMInternal *) // [IN] used only on RW imports
+
+ {
+ return phEnumBody->m_ulCount / 2;
+ }
+
+ STDMETHODIMP_(void) EnumMethodImplReset(
+ HENUMInternal *phEnumBody, // [IN] MethodBody enumerator.
+ HENUMInternal *) // [IN] used only on RW imports
+ {
+ phEnumBody->u.m_ulCur = phEnumBody->u.m_ulStart;
+ return;
+ }
+
+ __checkReturn
+ STDMETHODIMP EnumMethodImplNext( // return hresult (S_OK = TRUE, S_FALSE = FALSE or error code)
+ HENUMInternal *phEnumBody, // [IN] input enum for MethodBody
+ HENUMInternal *, // [IN] used only on RW imports
+ mdToken *ptkBody, // [OUT] return token for MethodBody
+ mdToken *ptkDecl) // [OUT] return token for MethodDecl
+ {
+ _ASSERTE(ptkBody && ptkDecl);
+ return HENUMInternal::EnumWithCount(phEnumBody, 1, ptkBody, ptkDecl, NULL);
+ }
+
+ STDMETHODIMP_(void) EnumMethodImplClose(
+ HENUMInternal *phEnumBody, // [IN] MethodBody enumerator.
+ HENUMInternal *) // [IN] used only on RW imports
+ {
+ HENUMInternal::ClearEnum(phEnumBody);
+ }
+
+ //*****************************************
+ // Enumerator helpers for memberdef, memberref, interfaceimp,
+ // event, property, exception, param
+ //*****************************************
+
+ __checkReturn
+ STDMETHODIMP EnumGlobalFunctionsInit( // return hresult
+ HENUMInternal *phEnum) // [OUT] buffer to fill for enumerator data
+ {
+ return m_pRawInternalImport->EnumGlobalFunctionsInit(phEnum);
+ }
+
+ __checkReturn
+ STDMETHODIMP EnumGlobalFieldsInit( // return hresult
+ HENUMInternal *phEnum) // [OUT] buffer to fill for enumerator data
+ {
+ return m_pRawInternalImport->EnumGlobalFieldsInit(phEnum);
+ }
+
+ __checkReturn
+ STDMETHODIMP EnumInit( // return S_FALSE if record not found
+ DWORD tkKind, // [IN] which table to work on
+ mdToken tkParent, // [IN] token to scope the search
+ HENUMInternal *phEnum) // [OUT] the enumerator to fill
+ {
+ if (tkKind == (TBL_MethodImpl << 24))
+ return EnumMethodImplInit(tkParent, phEnum, NULL);
+
+ HRESULT hr;
+ IfFailGo(m_pRawInternalImport->EnumInit(tkKind, tkParent, phEnum));
+
+ _ASSERTE(phEnum->m_EnumType == MDSimpleEnum);
+
+ if (tkKind == mdtAssemblyRef)
+ {
+ _ASSERTE( phEnum->m_ulCount == m_pWinMDAdapter->GetRawAssemblyRefCount());
+ int n = m_pWinMDAdapter->GetExtraAssemblyRefCount();
+ phEnum->m_ulCount += n;
+ phEnum->u.m_ulEnd += n;
+ }
+
+
+ErrExit:
+ return hr;
+ }
+
+ __checkReturn
+ STDMETHODIMP EnumAllInit( // return S_FALSE if record not found
+ DWORD tkKind, // [IN] which table to work on
+ HENUMInternal *phEnum) // [OUT] the enumerator to fill
+ {
+ HRESULT hr;
+ IfFailGo(m_pRawInternalImport->EnumAllInit(tkKind, phEnum));
+
+ _ASSERTE(phEnum->m_EnumType == MDSimpleEnum);
+
+ if (tkKind == mdtAssemblyRef)
+ {
+ _ASSERTE( phEnum->m_ulCount == m_pWinMDAdapter->GetRawAssemblyRefCount());
+ int n = m_pWinMDAdapter->GetExtraAssemblyRefCount();
+ phEnum->m_ulCount += n;
+ phEnum->u.m_ulEnd += n;
+ }
+
+ErrExit:
+ return hr;
+ }
+
+ STDMETHODIMP_(bool) EnumNext(
+ HENUMInternal *phEnum, // [IN] the enumerator to retrieve information
+ mdToken *ptk) // [OUT] token to scope the search
+ {
+ return m_pRawInternalImport->EnumNext(phEnum, ptk);
+ }
+
+ STDMETHODIMP_(ULONG) EnumGetCount(
+ HENUMInternal *phEnum) // [IN] the enumerator to retrieve information
+ {
+ return m_pRawInternalImport->EnumGetCount(phEnum);
+ }
+
+ STDMETHODIMP_(void) EnumReset(
+ HENUMInternal *phEnum) // [IN] the enumerator to be reset
+ {
+ return m_pRawInternalImport->EnumReset(phEnum);
+ }
+
+ STDMETHODIMP_(void) EnumClose(
+ HENUMInternal *phEnum) // [IN] the enumerator to be closed
+ {
+ return m_pRawInternalImport->EnumClose(phEnum);
+ }
+
+ //*****************************************
+ // Enumerator helpers for declsecurity.
+ //*****************************************
+ __checkReturn
+ STDMETHODIMP EnumPermissionSetsInit( // return S_FALSE if record not found
+ mdToken tkParent, // [IN] token to scope the search
+ CorDeclSecurity Action, // [IN] Action to scope the search
+ HENUMInternal *phEnum) // [OUT] the enumerator to fill
+ {
+ return m_pRawInternalImport->EnumPermissionSetsInit(tkParent, Action, phEnum);
+ }
+
+ //*****************************************
+ // Enumerator helpers for CustomAttribute
+ //*****************************************
+ __checkReturn
+ STDMETHODIMP EnumCustomAttributeByNameInit(// return S_FALSE if record not found
+ mdToken tkParent, // [IN] token to scope the search
+ LPCSTR szName, // [IN] CustomAttribute's name to scope the search
+ HENUMInternal *phEnum) // [OUT] the enumerator to fill
+ {
+ WinMDAdapter::ConvertWellKnownTypeNameFromClrToWinRT(&szName);
+ return m_pRawInternalImport->EnumCustomAttributeByNameInit(tkParent, szName, phEnum);
+ }
+
+ //*****************************************
+ // Nagivator helper to navigate back to the parent token given a token.
+ // For example, given a memberdef token, it will return the containing typedef.
+ //
+ // the mapping is as following:
+ // ---given child type---------parent type
+ // mdMethodDef mdTypeDef
+ // mdFieldDef mdTypeDef
+ // mdInterfaceImpl mdTypeDef
+ // mdParam mdMethodDef
+ // mdProperty mdTypeDef
+ // mdEvent mdTypeDef
+ //
+ //*****************************************
+ __checkReturn
+ STDMETHODIMP GetParentToken(
+ mdToken tkChild, // [IN] given child token
+ mdToken *ptkParent) // [OUT] returning parent
+ {
+ return m_pRawInternalImport->GetParentToken(tkChild, ptkParent);
+ }
+
+ //*****************************************
+ // Custom value helpers
+ //*****************************************
+ __checkReturn
+ STDMETHODIMP GetCustomAttributeProps( // S_OK or error.
+ mdCustomAttribute at, // [IN] The attribute.
+ mdToken *ptkType) // [OUT] Put attribute type here.
+ {
+ return m_pRawInternalImport->GetCustomAttributeProps(at, ptkType);
+ }
+
+ __checkReturn
+ STDMETHODIMP GetCustomAttributeAsBlob(
+ mdCustomAttribute cv, // [IN] given custom value token
+ void const **ppBlob, // [OUT] return the pointer to internal blob
+ ULONG *pcbSize) // [OUT] return the size of the blob
+ {
+ return m_pWinMDAdapter->GetCustomAttributeBlob(cv, ppBlob, pcbSize);
+ }
+
+ // returned void in v1.0/v1.1
+ __checkReturn
+ STDMETHODIMP GetScopeProps(
+ LPCSTR *pszName, // [OUT] scope name
+ GUID *pmvid) // [OUT] version id
+ {
+ return m_pRawInternalImport->GetScopeProps(pszName, pmvid);
+ }
+
+ // The default signature comparison function.
+ static BOOL CompareSignatures(PCCOR_SIGNATURE pvFirstSigBlob, // First signature
+ DWORD cbFirstSigBlob, //
+ PCCOR_SIGNATURE pvSecondSigBlob, // Second signature
+ DWORD cbSecondSigBlob, //
+ void * SigArguments) // No additional arguments required
+ {
+ if (cbFirstSigBlob != cbSecondSigBlob || memcmp(pvFirstSigBlob, pvSecondSigBlob, cbSecondSigBlob))
+ return FALSE;
+ else
+ return TRUE;
+ }
+
+ // finding a particular method
+ __checkReturn
+ STDMETHODIMP FindMethodDef(
+ mdTypeDef classdef, // [IN] given typedef
+ LPCSTR szName, // [IN] member name
+ PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature
+ ULONG cbSigBlob, // [IN] count of bytes in the signature blob
+ mdMethodDef *pmd) // [OUT] matching memberdef
+ {
+ return FindMethodDefUsingCompare(classdef,
+ szName,
+ pvSigBlob,
+ cbSigBlob,
+ CompareSignatures,
+ NULL,
+ pmd);
+ }
+
+ // return a iSeq's param given a MethodDef
+ __checkReturn
+ STDMETHODIMP FindParamOfMethod( // S_OK or error.
+ mdMethodDef md, // [IN] The owning method of the param.
+ ULONG iSeq, // [IN] The sequence # of the param.
+ mdParamDef *pparamdef) // [OUT] Put ParamDef token here.
+ {
+ return m_pRawInternalImport->FindParamOfMethod(md, iSeq, pparamdef);
+ }
+
+ //*****************************************
+ //
+ // GetName* functions
+ //
+ //*****************************************
+
+ // return the name and namespace of typedef
+ __checkReturn
+ STDMETHODIMP GetNameOfTypeDef(
+ mdTypeDef classdef, // given classdef
+ LPCSTR *pszname, // return class name(unqualified)
+ LPCSTR *psznamespace) // return the name space name
+ {
+ if (TypeFromToken(classdef) != mdtTypeDef)
+ return CLDB_E_INTERNALERROR;
+
+ HRESULT hr;
+ IfFailRet(m_pWinMDAdapter->GetTypeDefProps(classdef, psznamespace, pszname, NULL, NULL));
+ return hr;
+ }
+
+ __checkReturn
+ STDMETHODIMP GetIsDualOfTypeDef(
+ mdTypeDef classdef, // [IN] given classdef.
+ ULONG *pDual) // [OUT] return dual flag here.
+ {
+ return m_pRawInternalImport->GetIsDualOfTypeDef(classdef, pDual);
+ }
+
+ __checkReturn
+ STDMETHODIMP GetIfaceTypeOfTypeDef(
+ mdTypeDef classdef, // [IN] given classdef.
+ ULONG *pIface) // [OUT] 0=dual, 1=vtable, 2=dispinterface
+ {
+ return m_pRawInternalImport->GetIfaceTypeOfTypeDef(classdef, pIface);
+ }
+
+ // get the name of either methoddef
+ __checkReturn
+ STDMETHODIMP GetNameOfMethodDef( // return the name of the memberdef in UTF8
+ mdMethodDef md, // given memberdef
+ LPCSTR *pszName)
+ {
+ HRESULT hr = S_OK;
+ IfFailRet(m_pRawInternalImport->GetNameOfMethodDef(md, pszName));
+ return m_pWinMDAdapter->ModifyMethodProps(md, NULL, NULL, NULL, pszName);
+ }
+
+ __checkReturn
+ STDMETHODIMP GetNameAndSigOfMethodDef(
+ mdMethodDef methoddef, // [IN] given memberdef
+ PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to a blob value of CLR signature
+ ULONG *pcbSigBlob, // [OUT] count of bytes in the signature blob
+ LPCSTR *pszName)
+ {
+ PCCOR_SIGNATURE pOrigSig;
+ ULONG cbOrigSig;
+ HRESULT hr = S_OK;
+ IfFailRet(m_pRawInternalImport->GetNameAndSigOfMethodDef(methoddef, &pOrigSig, &cbOrigSig, pszName));
+ IfFailRet(m_pWinMDAdapter->ModifyMethodProps(methoddef, NULL, NULL, NULL, pszName));
+
+ return m_pWinMDAdapter->GetSignatureForToken<IMDInternalImport, mdtMethodDef>(
+ methoddef,
+ &pOrigSig, // ppOrigSig
+ &cbOrigSig, // pcbOrigSig
+ ppvSigBlob,
+ pcbSigBlob,
+ m_pRawInternalImport);
+ }
+
+ // return the name of a FieldDef
+ __checkReturn
+ STDMETHODIMP GetNameOfFieldDef(
+ mdFieldDef fd, // given memberdef
+ LPCSTR *pszName)
+ {
+ return m_pRawInternalImport->GetNameOfFieldDef(fd, pszName);
+ }
+
+ // return the name of typeref
+ __checkReturn
+ STDMETHODIMP GetNameOfTypeRef(
+ mdTypeRef classref, // [IN] given typeref
+ LPCSTR *psznamespace, // [OUT] return typeref name
+ LPCSTR *pszname) // [OUT] return typeref namespace
+ {
+ mdToken resolutionScope;
+ return m_pWinMDAdapter->GetTypeRefProps(classref, psznamespace, pszname, &resolutionScope);
+ }
+
+ // return the resolutionscope of typeref
+ __checkReturn
+ STDMETHODIMP GetResolutionScopeOfTypeRef(
+ mdTypeRef classref, // given classref
+ mdToken *ptkResolutionScope)
+ {
+ LPCSTR sznamespace;
+ LPCSTR szname;
+ return m_pWinMDAdapter->GetTypeRefProps(classref, &sznamespace, &szname, ptkResolutionScope);
+ }
+
+ // Find the type token given the name.
+ __checkReturn
+ STDMETHODIMP FindTypeRefByName(
+ LPCSTR szNamespace, // [IN] Namespace for the TypeRef.
+ LPCSTR szName, // [IN] Name of the TypeRef.
+ mdToken tkResolutionScope, // [IN] Resolution Scope fo the TypeRef.
+ mdTypeRef *ptk) // [OUT] TypeRef token returned.
+ {
+ return m_pWinMDAdapter->FindTypeRef(szNamespace, szName, tkResolutionScope, ptk);
+ }
+
+ // return the TypeDef properties
+ // returned void in v1.0/v1.1
+ __checkReturn
+ STDMETHODIMP GetTypeDefProps(
+ mdTypeDef classdef, // given classdef
+ DWORD *pdwAttr, // return flags on class, tdPublic, tdAbstract
+ mdToken *ptkExtends) // [OUT] Put base class TypeDef/TypeRef here
+ {
+ HRESULT hr;
+ IfFailGo(m_pWinMDAdapter->GetTypeDefProps(classdef, NULL, NULL, pdwAttr, ptkExtends));
+ ErrExit:
+ return hr;
+ }
+
+ // return the item's guid
+ __checkReturn
+ STDMETHODIMP GetItemGuid(
+ mdToken tkObj, // [IN] given item.
+ CLSID *pGuid) // [out[ put guid here.
+ {
+ HRESULT hr;
+ IfFailGo(m_pWinMDAdapter->GetItemGuid(tkObj, pGuid));
+
+ if (hr == S_FALSE)
+ {
+ // if this is not a WinRT type, also look for System.Guid by falling back to the raw internal MD import
+ if (TypeFromToken(tkObj) == mdtTypeDef)
+ {
+ DWORD dwAttr;
+ IfFailGo(m_pWinMDAdapter->GetTypeDefProps(tkObj, NULL, NULL, &dwAttr, NULL));
+
+ if (!IsTdWindowsRuntime(dwAttr))
+ {
+ IfFailGo(m_pRawInternalImport->GetItemGuid(tkObj, pGuid));
+ }
+ else
+ {
+ // reset the return value to S_FALSE if the type is WinRT
+ hr = S_FALSE;
+ }
+ }
+ }
+
+ ErrExit:
+ return hr;
+ }
+
+ // Get enclosing class of the NestedClass.
+ __checkReturn
+ STDMETHODIMP GetNestedClassProps( // S_OK or error
+ mdTypeDef tkNestedClass, // [IN] NestedClass token.
+ mdTypeDef *ptkEnclosingClass) // [OUT] EnclosingClass token.
+ {
+ return m_pRawInternalImport->GetNestedClassProps(tkNestedClass, ptkEnclosingClass);
+ }
+
+ // Get count of Nested classes given the enclosing class.
+ __checkReturn
+ STDMETHODIMP GetCountNestedClasses( // return count of Nested classes.
+ mdTypeDef tkEnclosingClass, // Enclosing class.
+ ULONG *pcNestedClassesCount)
+ {
+ return m_pRawInternalImport->GetCountNestedClasses(tkEnclosingClass, pcNestedClassesCount);
+ }
+
+ // Return array of Nested classes given the enclosing class.
+ __checkReturn
+ STDMETHODIMP GetNestedClasses( // Return actual count.
+ mdTypeDef tkEnclosingClass, // [IN] Enclosing class.
+ mdTypeDef *rNestedClasses, // [OUT] Array of nested class tokens.
+ ULONG ulNestedClasses, // [IN] Size of array.
+ ULONG *pcNestedClasses)
+ {
+ return m_pRawInternalImport->GetNestedClasses(tkEnclosingClass, rNestedClasses, ulNestedClasses, pcNestedClasses);
+ }
+
+ // return the ModuleRef properties
+ // returned void in v1.0/v1.1
+ __checkReturn
+ STDMETHODIMP GetModuleRefProps(
+ mdModuleRef mur, // [IN] moduleref token
+ LPCSTR *pszName) // [OUT] buffer to fill with the moduleref name
+ {
+ return m_pRawInternalImport->GetModuleRefProps(mur, pszName);
+ }
+
+ //*****************************************
+ //
+ // GetSig* functions
+ //
+ //*****************************************
+ __checkReturn
+ STDMETHODIMP GetSigOfMethodDef(
+ mdMethodDef methoddef, // [IN] given memberdef
+ ULONG *pcbSigBlob, // [OUT] count of bytes in the signature blob
+ PCCOR_SIGNATURE *ppSig)
+ {
+ return m_pWinMDAdapter->GetSignatureForToken<IMDInternalImport, mdtMethodDef>(
+ methoddef,
+ NULL,
+ NULL,
+ ppSig,
+ pcbSigBlob,
+ m_pRawInternalImport);
+ }
+
+ __checkReturn
+ STDMETHODIMP GetSigOfFieldDef(
+ mdFieldDef fielddef, // [IN] given fielddef
+ ULONG *pcbSigBlob, // [OUT] count of bytes in the signature blob
+ PCCOR_SIGNATURE *ppSig)
+ {
+ return m_pWinMDAdapter->GetSignatureForToken<IMDInternalImport, mdtFieldDef>(
+ fielddef,
+ NULL,
+ NULL,
+ ppSig,
+ pcbSigBlob,
+ m_pRawInternalImport);
+ }
+
+ __checkReturn
+ STDMETHODIMP GetSigFromToken(
+ mdToken tk, // FieldDef, MethodDef, Signature or TypeSpec token
+ ULONG * pcbSig,
+ PCCOR_SIGNATURE * ppSig)
+ {
+ if (TypeFromToken(tk) == mdtMethodDef)
+ {
+ return GetSigOfMethodDef(tk, pcbSig, ppSig);
+ }
+ else if (TypeFromToken(tk) == mdtFieldDef)
+ {
+ return GetSigOfFieldDef(tk, pcbSig, ppSig);
+ }
+ else if (TypeFromToken(tk) == mdtTypeSpec)
+ {
+ return GetTypeSpecFromToken(tk, ppSig, pcbSig);
+ }
+ // Note: mdtSignature is not part of public WinMD surface, so it does not need signature rewriting - just call the underlying "raw" implementation
+ return m_pRawInternalImport->GetSigFromToken(tk, pcbSig, ppSig);
+ }
+
+
+
+ //*****************************************
+ // get method property
+ //*****************************************
+ __checkReturn
+ STDMETHODIMP GetMethodDefProps(
+ mdMethodDef md, // The method for which to get props.
+ DWORD *pdwFlags)
+ {
+ HRESULT hr;
+ IfFailGo(m_pRawInternalImport->GetMethodDefProps(md, pdwFlags));
+ IfFailGo(m_pWinMDAdapter->ModifyMethodProps(md, pdwFlags, NULL, NULL, NULL));
+ ErrExit:
+ return hr;
+ }
+
+ //*****************************************
+ // return method implementation informaiton, like RVA and implflags
+ //*****************************************
+ // returned void in v1.0/v1.1
+ __checkReturn
+ STDMETHODIMP GetMethodImplProps(
+ mdToken tk, // [IN] MethodDef
+ ULONG *pulCodeRVA, // [OUT] CodeRVA
+ DWORD *pdwImplFlags) // [OUT] Impl. Flags
+ {
+ HRESULT hr;
+ IfFailGo(m_pRawInternalImport->GetMethodImplProps(tk, pulCodeRVA, pdwImplFlags));
+ IfFailGo(m_pWinMDAdapter->ModifyMethodProps(tk, NULL, pdwImplFlags, pulCodeRVA, NULL));
+ ErrExit:
+ return hr;
+ }
+
+ //*****************************************
+ // return method implementation informaiton, like RVA and implflags
+ //*****************************************
+ __checkReturn
+ STDMETHODIMP GetFieldRVA(
+ mdFieldDef fd, // [IN] fielddef
+ ULONG *pulCodeRVA) // [OUT] CodeRVA
+ {
+ return m_pRawInternalImport->GetFieldRVA(fd, pulCodeRVA);
+ }
+
+ //*****************************************
+ // get field property
+ //*****************************************
+ __checkReturn
+ STDMETHODIMP GetFieldDefProps(
+ mdFieldDef fd, // [IN] given fielddef
+ DWORD *pdwFlags) // [OUT] return fdPublic, fdPrive, etc flags
+ {
+ HRESULT hr;
+ IfFailGo(m_pRawInternalImport->GetFieldDefProps(fd, pdwFlags));
+ IfFailGo(m_pWinMDAdapter->ModifyFieldDefProps(fd, pdwFlags));
+ErrExit:
+ return hr;
+ }
+
+ //*****************************************************************************
+ // return default value of a token(could be paramdef, fielddef, or property
+ //*****************************************************************************
+ __checkReturn
+ STDMETHODIMP GetDefaultValue(
+ mdToken tk, // [IN] given FieldDef, ParamDef, or Property
+ MDDefaultValue *pDefaultValue) // [OUT] default value to fill
+ {
+ return m_pRawInternalImport->GetDefaultValue(tk, pDefaultValue);
+ }
+
+
+ //*****************************************
+ // get dispid of a MethodDef or a FieldDef
+ //*****************************************
+ __checkReturn
+ STDMETHODIMP GetDispIdOfMemberDef( // return hresult
+ mdToken tk, // [IN] given methoddef or fielddef
+ ULONG *pDispid) // [OUT] Put the dispid here.
+ {
+ return m_pRawInternalImport->GetDispIdOfMemberDef(tk, pDispid);
+ }
+
+ //*****************************************
+ // return TypeRef/TypeDef given an InterfaceImpl token
+ //*****************************************
+ __checkReturn
+ STDMETHODIMP GetTypeOfInterfaceImpl( // return the TypeRef/typedef token for the interfaceimpl
+ mdInterfaceImpl iiImpl, // given a interfaceimpl
+ mdToken *ptkType)
+ {
+ return m_pRawInternalImport->GetTypeOfInterfaceImpl(iiImpl, ptkType);
+ }
+
+ //*****************************************
+ // look up function for TypeDef
+ //*****************************************
+ __checkReturn
+ STDMETHODIMP FindTypeDef(
+ LPCSTR szNamespace, // [IN] Namespace for the TypeDef.
+ LPCSTR szName, // [IN] Name of the TypeDef.
+ mdToken tkEnclosingClass, // [IN] TypeRef/TypeDef Token for the enclosing class.
+ mdTypeDef *ptypedef) // [IN] return typedef
+ {
+ return m_pWinMDAdapter->FindTypeDef(szNamespace, szName, tkEnclosingClass, ptypedef);
+ }
+
+ //*****************************************
+ // return name and sig of a memberref
+ //*****************************************
+ __checkReturn
+ STDMETHODIMP GetNameAndSigOfMemberRef( // return name here
+ mdMemberRef memberref, // given memberref
+ PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to a blob value of CLR signature
+ ULONG *pcbSigBlob, // [OUT] count of bytes in the signature blob
+ LPCSTR *pszName)
+ {
+ HRESULT hr = S_OK;
+ PCCOR_SIGNATURE pOrigSig;
+ ULONG cbOrigSig;
+
+ IfFailRet(m_pRawInternalImport->GetNameAndSigOfMemberRef(memberref, &pOrigSig, &cbOrigSig, pszName));
+ IfFailRet(m_pWinMDAdapter->ModifyMemberProps(memberref, NULL, NULL, NULL, pszName));
+
+ return m_pWinMDAdapter->GetSignatureForToken<IMDInternalImport, mdtMemberRef>(
+ memberref,
+ &pOrigSig, // ppOrigSig
+ &cbOrigSig, // pcbOrigSig
+ ppvSigBlob,
+ pcbSigBlob,
+ m_pRawInternalImport);
+ }
+
+ //*****************************************************************************
+ // Given memberref, return the parent. It can be TypeRef, ModuleRef, MethodDef
+ //*****************************************************************************
+ __checkReturn
+ STDMETHODIMP GetParentOfMemberRef(
+ mdMemberRef memberref, // given memberref
+ mdToken *ptkParent) // return the parent token
+ {
+ return m_pRawInternalImport->GetParentOfMemberRef(memberref, ptkParent);
+ }
+
+ __checkReturn
+ STDMETHODIMP GetParamDefProps(
+ mdParamDef paramdef, // given a paramdef
+ USHORT *pusSequence, // [OUT] slot number for this parameter
+ DWORD *pdwAttr, // [OUT] flags
+ LPCSTR *pszName) // [OUT] return the name of the parameter
+ {
+ return m_pRawInternalImport->GetParamDefProps(paramdef, pusSequence, pdwAttr, pszName);
+ }
+
+ __checkReturn
+ STDMETHODIMP GetPropertyInfoForMethodDef( // Result.
+ mdMethodDef md, // [IN] memberdef
+ mdProperty *ppd, // [OUT] put property token here
+ LPCSTR *pName, // [OUT] put pointer to name here
+ ULONG *pSemantic) // [OUT] put semantic here
+ {
+ return m_pRawInternalImport->GetPropertyInfoForMethodDef(md, ppd, pName, pSemantic);
+ }
+
+ //*****************************************
+ // class layout/sequence information
+ //*****************************************
+ __checkReturn
+ STDMETHODIMP GetClassPackSize( // return error if class doesn't have packsize
+ mdTypeDef td, // [IN] give typedef
+ ULONG *pdwPackSize) // [OUT] 1, 2, 4, 8, or 16
+ {
+ return m_pRawInternalImport->GetClassPackSize(td, pdwPackSize);
+ }
+
+ __checkReturn
+ STDMETHODIMP GetClassTotalSize( // return error if class doesn't have total size info
+ mdTypeDef td, // [IN] give typedef
+ ULONG *pdwClassSize) // [OUT] return the total size of the class
+ {
+ return m_pRawInternalImport->GetClassTotalSize(td, pdwClassSize);
+ }
+
+ __checkReturn
+ STDMETHODIMP GetClassLayoutInit(
+ mdTypeDef td, // [IN] give typedef
+ MD_CLASS_LAYOUT *pLayout) // [OUT] set up the status of query here
+ {
+ return m_pRawInternalImport->GetClassLayoutInit(td, pLayout);
+ }
+
+ __checkReturn
+ STDMETHODIMP GetClassLayoutNext(
+ MD_CLASS_LAYOUT *pLayout, // [IN|OUT] set up the status of query here
+ mdFieldDef *pfd, // [OUT] return the fielddef
+ ULONG *pulOffset) // [OUT] return the offset/ulSequence associate with it
+ {
+ return m_pRawInternalImport->GetClassLayoutNext(pLayout, pfd, pulOffset);
+ }
+
+ //*****************************************
+ // marshal information of a field
+ //*****************************************
+ __checkReturn
+ STDMETHODIMP GetFieldMarshal( // return error if no native type associate with the token
+ mdFieldDef fd, // [IN] given fielddef
+ PCCOR_SIGNATURE *pSigNativeType, // [OUT] the native type signature
+ ULONG *pcbNativeType) // [OUT] the count of bytes of *ppvNativeType
+ {
+ return m_pRawInternalImport->GetFieldMarshal(fd, pSigNativeType, pcbNativeType);
+ }
+
+
+ //*****************************************
+ // property APIs
+ //*****************************************
+ // find a property by name
+ __checkReturn
+ STDMETHODIMP FindProperty(
+ mdTypeDef td, // [IN] given a typdef
+ LPCSTR szPropName, // [IN] property name
+ mdProperty *pProp) // [OUT] return property token
+ {
+ return m_pRawInternalImport->FindProperty(td, szPropName, pProp);
+ }
+
+ // returned void in v1.0/v1.1
+ __checkReturn
+ STDMETHODIMP GetPropertyProps(
+ mdProperty prop, // [IN] property token
+ LPCSTR *szProperty, // [OUT] property name
+ DWORD *pdwPropFlags, // [OUT] property flags.
+ PCCOR_SIGNATURE *ppvSig, // [OUT] property type. pointing to meta data internal blob
+ ULONG *pcbSig) // [OUT] count of bytes in *ppvSig
+ {
+ HRESULT hr = S_OK;
+ PCCOR_SIGNATURE pOrigSig;
+ ULONG cbOrigSig;
+
+ IfFailRet(m_pRawInternalImport->GetPropertyProps(prop, szProperty, pdwPropFlags, &pOrigSig, &cbOrigSig));
+
+ return m_pWinMDAdapter->GetSignatureForToken<IMDInternalImport, mdtProperty>(
+ prop,
+ &pOrigSig, // ppOrigSig
+ &cbOrigSig, // pcbOrigSig
+ ppvSig,
+ pcbSig,
+ m_pRawInternalImport);
+ }
+
+ //**********************************
+ // Event APIs
+ //**********************************
+ __checkReturn
+ STDMETHODIMP FindEvent(
+ mdTypeDef td, // [IN] given a typdef
+ LPCSTR szEventName, // [IN] event name
+ mdEvent *pEvent) // [OUT] return event token
+ {
+ return m_pRawInternalImport->FindEvent(td, szEventName, pEvent);
+ }
+
+ // returned void in v1.0/v1.1
+ __checkReturn
+ STDMETHODIMP GetEventProps(
+ mdEvent ev, // [IN] event token
+ LPCSTR *pszEvent, // [OUT] Event name
+ DWORD *pdwEventFlags, // [OUT] Event flags.
+ mdToken *ptkEventType) // [OUT] EventType class
+ {
+ return m_pRawInternalImport->GetEventProps(ev, pszEvent, pdwEventFlags, ptkEventType);
+ }
+
+
+ //**********************************
+ // find a particular associate of a property or an event
+ //**********************************
+ __checkReturn
+ STDMETHODIMP FindAssociate(
+ mdToken evprop, // [IN] given a property or event token
+ DWORD associate, // [IN] given a associate semantics(setter, getter, testdefault, reset, AddOn, RemoveOn, Fire)
+ mdMethodDef *pmd) // [OUT] return method def token
+ {
+ return m_pRawInternalImport->FindAssociate(evprop, associate, pmd);
+ }
+
+ // Note, void function in v1.0/v1.1
+ __checkReturn
+ STDMETHODIMP EnumAssociateInit(
+ mdToken evprop, // [IN] given a property or an event token
+ HENUMInternal *phEnum) // [OUT] cursor to hold the query result
+ {
+ return m_pRawInternalImport->EnumAssociateInit(evprop, phEnum);
+ }
+
+ // returned void in v1.0/v1.1
+ __checkReturn
+ STDMETHODIMP GetAllAssociates(
+ HENUMInternal *phEnum, // [IN] query result form GetPropertyAssociateCounts
+ ASSOCIATE_RECORD *pAssociateRec, // [OUT] struct to fill for output
+ ULONG cAssociateRec) // [IN] size of the buffer
+ {
+ return m_pRawInternalImport->GetAllAssociates(phEnum, pAssociateRec, cAssociateRec);
+ }
+
+
+ //**********************************
+ // Get info about a PermissionSet.
+ //**********************************
+ // returned void in v1.0/v1.1
+ __checkReturn
+ STDMETHODIMP 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.
+ {
+ return m_pRawInternalImport->GetPermissionSetProps(pm, pdwAction, ppvPermission, pcbPermission);
+ }
+
+ //****************************************
+ // Get the String given the String token.
+ // Returns a pointer to the string, or NULL in case of error.
+ //****************************************
+ __checkReturn
+ STDMETHODIMP GetUserString(
+ mdString stk, // [IN] the string token.
+ ULONG *pchString, // [OUT] count of characters in the string.
+ BOOL *pbIs80Plus, // [OUT] specifies where there are extended characters >= 0x80.
+ LPCWSTR *pwszUserString)
+ {
+ return m_pRawInternalImport->GetUserString(stk, pchString, pbIs80Plus, pwszUserString);
+ }
+
+ //*****************************************************************************
+ // p-invoke APIs.
+ //*****************************************************************************
+ __checkReturn
+ STDMETHODIMP GetPinvokeMap(
+ mdToken tk, // [IN] FieldDef, MethodDef.
+ DWORD *pdwMappingFlags, // [OUT] Flags used for mapping.
+ LPCSTR *pszImportName, // [OUT] Import name.
+ mdModuleRef *pmrImportDLL) // [OUT] ModuleRef token for the target DLL.
+ {
+ return m_pRawInternalImport->GetPinvokeMap(tk, pdwMappingFlags, pszImportName, pmrImportDLL);
+ }
+
+ //*****************************************************************************
+ // helpers to convert a text signature to a com format
+ //*****************************************************************************
+ __checkReturn
+ STDMETHODIMP ConvertTextSigToComSig( // Return hresult.
+ BOOL fCreateTrIfNotFound, // [IN] create typeref if not found
+ LPCSTR pSignature, // [IN] class file format signature
+ CQuickBytes *pqbNewSig, // [OUT] place holder for CLR signature
+ ULONG *pcbCount) // [OUT] the result size of signature
+ {
+ return m_pRawInternalImport->ConvertTextSigToComSig(fCreateTrIfNotFound, pSignature, pqbNewSig, pcbCount);
+ }
+
+ //*****************************************************************************
+ // Assembly MetaData APIs.
+ //*****************************************************************************
+ // returned void in v1.0/v1.1
+ __checkReturn
+ STDMETHODIMP GetAssemblyProps(
+ 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.
+ LPCSTR *pszName, // [OUT] Buffer to fill with name.
+ AssemblyMetaDataInternal *pMetaData,// [OUT] Assembly MetaData.
+ DWORD *pdwAssemblyFlags) // [OUT] Flags.
+ {
+ return m_pRawInternalImport->GetAssemblyProps(mda, ppbPublicKey, pcbPublicKey, pulHashAlgId, pszName, pMetaData, pdwAssemblyFlags);
+ }
+
+ // returned void in v1.0/v1.1
+ __checkReturn
+ STDMETHODIMP GetAssemblyRefProps(
+ 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.
+ LPCSTR *pszName, // [OUT] Buffer to fill with name.
+ AssemblyMetaDataInternal *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;
+ mdAssemblyRef md = mdar;
+ if (RidFromToken(md) > m_pWinMDAdapter->GetRawAssemblyRefCount())
+ {
+ // The extra framework assemblies we add references to should all have the
+ // same verion, key, culture, etc as those of mscorlib.
+ // So we retrieve the mscorlib properties and change the name.
+ md = m_pWinMDAdapter->GetAssemblyRefMscorlib();
+ }
+
+ IfFailRet(m_pRawInternalImport->GetAssemblyRefProps(md, ppbPublicKeyOrToken, pcbPublicKeyOrToken, pszName, pMetaData, ppbHashValue, pcbHashValue, pdwAssemblyRefFlags));
+
+ USHORT *pusMajorVersion = nullptr;
+ USHORT *pusMinorVersion = nullptr;
+ USHORT *pusBuildNumber = nullptr;
+ USHORT *pusRevisionNumber = nullptr;
+
+ if (pMetaData != nullptr)
+ {
+ pusMajorVersion = &pMetaData->usMajorVersion;
+ pusMinorVersion = &pMetaData->usMinorVersion;
+ pusBuildNumber = &pMetaData->usBuildNumber;
+ pusRevisionNumber = &pMetaData->usRevisionNumber;
+ }
+
+ m_pWinMDAdapter->ModifyAssemblyRefProps(
+ mdar,
+ ppbPublicKeyOrToken,
+ pcbPublicKeyOrToken,
+ pszName,
+ pusMajorVersion,
+ pusMinorVersion,
+ pusBuildNumber,
+ pusRevisionNumber,
+ ppbHashValue,
+ pcbHashValue);
+
+ return hr;
+ }
+
+ // returned void in v1.0/v1.1
+ __checkReturn
+ STDMETHODIMP GetFileProps(
+ mdFile mdf, // [IN] The File for which to get the properties.
+ LPCSTR *pszName, // [OUT] Buffer to fill with 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.
+ {
+ return m_pRawInternalImport->GetFileProps(mdf, pszName, ppbHashValue, pcbHashValue, pdwFileFlags);
+ }
+
+ // returned void in v1.0/v1.1
+ __checkReturn
+ STDMETHODIMP GetExportedTypeProps(
+ mdExportedType mdct, // [IN] The ExportedType for which to get the properties.
+ LPCSTR *pszNamespace, // [OUT] Namespace.
+ LPCSTR *pszName, // [OUT] Name.
+ mdToken *ptkImplementation, // [OUT] mdFile or mdAssemblyRef that provides the ExportedType.
+ mdTypeDef *ptkTypeDef, // [OUT] TypeDef token within the file.
+ DWORD *pdwExportedTypeFlags) // [OUT] Flags.
+ {
+ HRESULT hr;
+ IfFailRet(m_pRawInternalImport->GetExportedTypeProps(mdct, pszNamespace, pszName, ptkImplementation, ptkTypeDef, pdwExportedTypeFlags));
+ IfFailRet(m_pWinMDAdapter->ModifyExportedTypeName(mdct, pszNamespace, pszName));
+ return hr;
+ }
+
+ // returned void in v1.0/v1.1
+ __checkReturn
+ STDMETHODIMP GetManifestResourceProps(
+ mdManifestResource mdmr, // [IN] The ManifestResource for which to get the properties.
+ LPCSTR *pszName, // [OUT] Buffer to fill with name.
+ mdToken *ptkImplementation, // [OUT] mdFile or mdAssemblyRef that provides the ExportedType.
+ DWORD *pdwOffset, // [OUT] Offset to the beginning of the resource within the file.
+ DWORD *pdwResourceFlags) // [OUT] Flags.
+ {
+ return m_pRawInternalImport->GetManifestResourceProps(mdmr, pszName, ptkImplementation, pdwOffset, pdwResourceFlags);
+ }
+
+ __checkReturn
+ STDMETHODIMP FindExportedTypeByName( // S_OK or error
+ LPCSTR szNamespace, // [IN] Namespace of the ExportedType.
+ LPCSTR szName, // [IN] Name of the ExportedType.
+ mdExportedType tkEnclosingType, // [IN] ExportedType for the enclosing class.
+ mdExportedType *pmct) // [OUT] Put ExportedType token here.
+ {
+ return m_pWinMDAdapter->FindExportedType(szNamespace, szName, tkEnclosingType, pmct);
+ }
+
+ __checkReturn
+ STDMETHODIMP FindManifestResourceByName( // S_OK or error
+ LPCSTR szName, // [IN] Name of the ManifestResource.
+ mdManifestResource *pmmr) // [OUT] Put ManifestResource token here.
+ {
+ return m_pRawInternalImport->FindManifestResourceByName(szName, pmmr);
+ }
+
+ __checkReturn
+ STDMETHODIMP GetAssemblyFromScope( // S_OK or error
+ mdAssembly *ptkAssembly) // [OUT] Put token here.
+ {
+ return m_pRawInternalImport->GetAssemblyFromScope(ptkAssembly);
+ }
+
+ __checkReturn
+ STDMETHODIMP GetCustomAttributeByName( // S_OK or error
+ mdToken tkObj, // [IN] Object with Custom Attribute.
+ LPCUTF8 szName, // [IN] Name of desired Custom Attribute.
+ const void **ppData, // [OUT] Put pointer to data here.
+ ULONG *pcbData) // [OUT] Put size of data here.
+ {
+ return m_pWinMDAdapter->GetCustomAttributeByName(tkObj, szName, NULL, ppData, pcbData);
+ }
+
+ // Note: The return type of this method was void in v1
+ __checkReturn
+ STDMETHODIMP GetTypeSpecFromToken( // S_OK or error.
+ mdTypeSpec typespec, // [IN] Signature token.
+ PCCOR_SIGNATURE *ppvSig, // [OUT] return pointer to token.
+ ULONG *pcbSig) // [OUT] return size of signature.
+ {
+ return m_pWinMDAdapter->GetSignatureForToken<IMDInternalImport, mdtTypeSpec>(
+ typespec,
+ NULL, // ppOrigSig
+ NULL, // pcbOrigSig
+ ppvSig,
+ pcbSig,
+ m_pRawInternalImport);
+ }
+
+ __checkReturn
+ STDMETHODIMP SetUserContextData( // S_OK or E_NOTIMPL
+ IUnknown *pIUnk) // The user context.
+ {
+ return m_pRawInternalImport->SetUserContextData(pIUnk);
+ }
+
+ __checkReturn
+ STDMETHODIMP_(BOOL) IsValidToken( // True or False.
+ mdToken tk) // [IN] Given token.
+ {
+ if (TypeFromToken(tk) == mdtAssemblyRef)
+ return m_pWinMDAdapter->IsValidAssemblyRefToken(tk);
+
+ return m_pRawInternalImport->IsValidToken(tk);
+ }
+
+
+ __checkReturn
+ STDMETHODIMP TranslateSigWithScope(
+ IMDInternalImport* pAssemImport, // [IN] import assembly scope.
+ const void* pbHashValue, // [IN] hash value for the import assembly.
+ ULONG cbHashValue, // [IN] count of bytes in the hash value.
+ PCCOR_SIGNATURE pbSigBlob, // [IN] signature in the importing scope
+ ULONG cbSigBlob, // [IN] count of bytes of signature
+ IMetaDataAssemblyEmit* pAssemEmit, // [IN] assembly emit scope.
+ IMetaDataEmit* emit, // [IN] emit interface
+ CQuickBytes* pqkSigEmit, // [OUT] buffer to hold translated signature
+ ULONG* pcbSig) // [OUT] count of bytes in the translated signature
+ {
+ return TranslateSigHelper(
+ this,
+ pAssemImport,
+ pbHashValue,
+ cbHashValue,
+ pbSigBlob,
+ cbSigBlob,
+ pAssemEmit,
+ emit,
+ pqkSigEmit,
+ pcbSig);
+ }
+
+
+ STDMETHODIMP_(IMetaModelCommon*) GetMetaModelCommon() // Return MetaModelCommon interface.
+ {
+ return static_cast<IMetaModelCommon*>(this);
+ }
+
+ STDMETHODIMP_(IUnknown *) GetCachedPublicInterface(BOOL fWithLock) // return the cached public interface
+ {
+ return m_pRawInternalImport->GetCachedPublicInterface(fWithLock);
+ }
+ __checkReturn
+
+ STDMETHODIMP SetCachedPublicInterface(IUnknown *pUnk) // no return value
+ {
+ return m_pRawInternalImport->SetCachedPublicInterface(pUnk);
+ }
+
+ STDMETHODIMP_(UTSemReadWrite*) GetReaderWriterLock() // return the reader writer lock
+ {
+ return m_pRawInternalImport->GetReaderWriterLock();
+ }
+
+ __checkReturn
+ STDMETHODIMP SetReaderWriterLock(UTSemReadWrite * pSem)
+ {
+ return m_pRawInternalImport->SetReaderWriterLock(pSem);
+ }
+
+ STDMETHODIMP_(mdModule) GetModuleFromScope() // [OUT] Put mdModule token here.
+ {
+ return m_pRawInternalImport->GetModuleFromScope();
+ }
+
+
+ //-----------------------------------------------------------------
+ // Additional custom methods
+
+ // finding a particular method
+ __checkReturn
+ STDMETHODIMP FindMethodDefUsingCompare(
+ mdTypeDef classdef, // [IN] given typedef
+ LPCSTR szName, // [IN] member name
+ PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature
+ ULONG cbSigBlob, // [IN] count of bytes in the signature blob
+ PSIGCOMPARE pSignatureCompare, // [IN] Routine to compare signatures
+ void* pSignatureArgs, // [IN] Additional info to supply the compare function
+ mdMethodDef *pmd) // [OUT] matching memberdef
+ {
+ if (pvSigBlob == NULL || cbSigBlob == 0 || pSignatureCompare == NULL)
+ {
+ // if signature matching is not needed, we can delegate to the underlying implementation
+ return m_pRawInternalImport->FindMethodDefUsingCompare(classdef, szName, pvSigBlob, cbSigBlob, pSignatureCompare, pSignatureArgs, pmd);
+ }
+
+ // The following code emulates MDInternalRO::FindMethodDefUsingCompare. We cannot call the underlying
+ // implementation because we need to compare pvSigBlob to reinterpreted signatures.
+ _ASSERTE(szName && pmd);
+
+ HRESULT hr = S_OK;
+ HENUMInternal hEnum;
+
+ CQuickBytes qbSig; // holds non-varargs signature
+
+ *pmd = mdMethodDefNil;
+
+ // check to see if this is a vararg signature
+ PCCOR_SIGNATURE pvSigTemp = pvSigBlob;
+ if (isCallConv(CorSigUncompressCallingConv(pvSigTemp), IMAGE_CEE_CS_CALLCONV_VARARG))
+ {
+ // Get the fixed part of VARARG signature
+ IfFailGo(_GetFixedSigOfVarArg(pvSigBlob, cbSigBlob, &qbSig, &cbSigBlob));
+ pvSigBlob = (PCCOR_SIGNATURE) qbSig.Ptr();
+ }
+
+ // now iterate all methods in td and compare name and signature
+ IfFailGo(EnumInit(mdtMethodDef, classdef, &hEnum));
+
+ mdMethodDef md;
+ while(EnumNext(&hEnum, &md))
+ {
+ PCCOR_SIGNATURE pvMethodSigBlob;
+ ULONG cbMethodSigBlob;
+ LPCSTR szMethodName;
+
+ IfFailGo(GetNameAndSigOfMethodDef(md, &pvMethodSigBlob, &cbMethodSigBlob, &szMethodName));
+
+ if (strcmp(szName, szMethodName) == 0)
+ {
+ // we have a name match, check signature
+ if (pSignatureCompare(pvMethodSigBlob, cbMethodSigBlob, pvSigBlob, cbSigBlob, pSignatureArgs) == FALSE)
+ continue;
+
+ // ignore PrivateScope methods
+ DWORD dwMethodAttr;
+ IfFailGo(GetMethodDefProps(md, &dwMethodAttr));
+
+ if (IsMdPrivateScope(dwMethodAttr))
+ continue;
+
+ // we found the method
+ *pmd = md;
+ goto ErrExit;
+ }
+ }
+ hr = CLDB_E_RECORD_NOTFOUND;
+
+ ErrExit:
+ EnumClose(&hEnum);
+ return hr;
+ }
+
+ // Additional v2 methods.
+
+ //*****************************************
+ // return a field offset for a given field
+ //*****************************************
+ __checkReturn
+ STDMETHODIMP GetFieldOffset(
+ mdFieldDef fd, // [IN] fielddef
+ ULONG *pulOffset) // [OUT] FieldOffset
+ {
+ return m_pRawInternalImport->GetFieldOffset(fd, pulOffset);
+ }
+
+ __checkReturn
+ STDMETHODIMP GetMethodSpecProps(
+ mdMethodSpec ms, // [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
+ {
+ HRESULT hr = S_OK;
+ PCCOR_SIGNATURE pOrigSig;
+ ULONG cbOrigSig;
+
+ IfFailRet(m_pRawInternalImport->GetMethodSpecProps(ms, tkParent, &pOrigSig, &cbOrigSig));
+
+ return m_pWinMDAdapter->GetSignatureForToken<IMDInternalImport, mdtMethodSpec>(
+ ms,
+ &pOrigSig, // ppOrigSig
+ &cbOrigSig, // pcbOrigSig
+ ppvSigBlob,
+ pcbSigBlob,
+ m_pRawInternalImport);
+ }
+
+ __checkReturn
+ STDMETHODIMP GetTableInfoWithIndex(
+ ULONG index, // [IN] pass in the table index
+ void **pTable, // [OUT] pointer to table at index
+ void **pTableSize) // [OUT] size of table at index
+ {
+ // This abstraction breaker is apparently used only by SOS... at this time of writing.
+ return m_pRawInternalImport->GetTableInfoWithIndex(index, pTable, pTableSize);
+ }
+
+ __checkReturn
+ STDMETHODIMP ApplyEditAndContinue(
+ void *pDeltaMD, // [IN] the delta metadata
+ ULONG cbDeltaMD, // [IN] length of pData
+ IMDInternalImport **ppv) // [OUT] the resulting metadata interface
+ {
+ WINMD_COMPAT_ASSERT("IMDInternalImport::ApplyEditAndContinue() not supported on .winmd files.");
+ return E_NOTIMPL;
+ }
+
+ //**********************************
+ // Generics APIs
+ //**********************************
+ __checkReturn
+ STDMETHODIMP GetGenericParamProps( // S_OK or error.
+ mdGenericParam rd, // [IN] The type parameter
+ ULONG* pulSequence, // [OUT] Parameter sequence number
+ DWORD* pdwAttr, // [OUT] Type parameter flags (for future use)
+ mdToken *ptOwner, // [OUT] The owner (TypeDef or MethodDef)
+ DWORD *reserved, // [OUT] The kind (TypeDef/Ref/Spec, for future use)
+ LPCSTR *szName) // [OUT] The name
+ {
+ return m_pRawInternalImport->GetGenericParamProps(rd, pulSequence, pdwAttr, ptOwner, reserved, szName);
+ }
+
+ __checkReturn
+ STDMETHODIMP GetGenericParamConstraintProps( // S_OK or error.
+ mdGenericParamConstraint rd, // [IN] The constraint token
+ mdGenericParam *ptGenericParam, // [OUT] GenericParam that is constrained
+ mdToken *ptkConstraintType) // [OUT] TypeDef/Ref/Spec constraint
+ {
+ return m_pRawInternalImport->GetGenericParamConstraintProps(rd, ptGenericParam, ptkConstraintType);
+ }
+
+ //*****************************************************************************
+ // This function gets the "built for" version of a metadata scope.
+ // NOTE: if the scope has never been saved, it will not have a built-for
+ // version, and an empty string will be returned.
+ //*****************************************************************************
+ __checkReturn
+ STDMETHODIMP GetVersionString( // S_OK or error.
+ LPCSTR *pVer) // [OUT] Put version string here.
+ {
+ return m_pWinMDAdapter->GetVersionString(pVer);
+ }
+
+ __checkReturn
+ STDMETHODIMP SafeAndSlowEnumCustomAttributeByNameInit(// return S_FALSE if record not found
+ mdToken tkParent, // [IN] token to scope the search
+ LPCSTR szName, // [IN] CustomAttribute's name to scope the search
+ HENUMInternal *phEnum) // [OUT] The enumerator
+ {
+ WinMDAdapter::ConvertWellKnownTypeNameFromClrToWinRT(&szName);
+ return m_pRawInternalImport->SafeAndSlowEnumCustomAttributeByNameInit(tkParent, szName, phEnum);
+ }
+ __checkReturn
+ STDMETHODIMP SafeAndSlowEnumCustomAttributeByNameNext(// return S_FALSE if record not found
+ mdToken tkParent, // [IN] token to scope the search
+ LPCSTR szName, // [IN] CustomAttribute's name to scope the search
+ HENUMInternal *phEnum, // [IN] The enumerator
+ mdCustomAttribute *mdAttribute) // [OUT] The custom attribute that was found
+ {
+ WinMDAdapter::ConvertWellKnownTypeNameFromClrToWinRT(&szName);
+ return m_pRawInternalImport->SafeAndSlowEnumCustomAttributeByNameNext(tkParent, szName, phEnum, mdAttribute);
+ }
+
+
+ __checkReturn
+ STDMETHODIMP GetTypeDefRefTokenInTypeSpec(// return S_FALSE if enclosing type does not have a token
+ mdTypeSpec tkTypeSpec, // [IN] TypeSpec token to look at
+ mdToken *tkEnclosedToken) // [OUT] The enclosed type token
+ {
+ return m_pRawInternalImport->GetTypeDefRefTokenInTypeSpec(tkTypeSpec, tkEnclosedToken);
+ }
+
+ STDMETHODIMP_(DWORD) GetMetadataStreamVersion() //returns DWORD with major version of
+ // MD stream in senior word and minor version--in junior word
+ {
+ return m_pRawInternalImport->GetMetadataStreamVersion();
+ }
+
+ __checkReturn
+ STDMETHODIMP GetNameOfCustomAttribute(// S_OK or error
+ mdCustomAttribute mdAttribute, // [IN] The Custom Attribute
+ LPCUTF8 *pszNamespace, // [OUT] Namespace of Custom Attribute.
+ LPCUTF8 *pszName) // [OUT] Name of Custom Attribute.
+ {
+ HRESULT hr;
+ IfFailRet(m_pRawInternalImport->GetNameOfCustomAttribute(mdAttribute, pszNamespace, pszName));
+ WinMDAdapter::ConvertWellKnownTypeNameFromWinRTToClr(pszNamespace, pszName);
+ return hr;
+ }
+
+ STDMETHODIMP SetOptimizeAccessForSpeed(// S_OK or error
+ BOOL fOptSpeed)
+ {
+ return m_pRawInternalImport->SetOptimizeAccessForSpeed(fOptSpeed);
+ }
+
+ STDMETHODIMP SetVerifiedByTrustedSource(// S_OK or error
+ BOOL fVerified)
+ {
+ return m_pRawInternalImport->SetVerifiedByTrustedSource(fVerified);
+ }
+
+ STDMETHODIMP GetRvaOffsetData(// S_OK or error
+ DWORD *pFirstMethodRvaOffset, // [OUT] Offset (from start of metadata) to the first RVA field in MethodDef table.
+ DWORD *pMethodDefRecordSize, // [OUT] Size of each record in MethodDef table.
+ DWORD *pMethodDefCount, // [OUT] Number of records in MethodDef table.
+ DWORD *pFirstFieldRvaOffset, // [OUT] Offset (from start of metadata) to the first RVA field in FieldRVA table.
+ DWORD *pFieldRvaRecordSize, // [OUT] Size of each record in FieldRVA table.
+ DWORD *pFieldRvaCount) // [OUT] Number of records in FieldRVA table.
+ {
+ return m_pRawInternalImport->GetRvaOffsetData(
+ pFirstMethodRvaOffset,
+ pMethodDefRecordSize,
+ pMethodDefCount,
+ pFirstFieldRvaOffset,
+ pFieldRvaRecordSize,
+ pFieldRvaCount);
+ }
+
+
+ // ********************************************************************************
+ // **************** Implementation of IMetaModelCommon methods ********************
+ // ********************************************************************************
+
+ __checkReturn
+ HRESULT CommonGetScopeProps(
+ LPCUTF8 *pszName,
+ GUID *pMvid)
+ {
+ return m_pRawMetaModelCommon->CommonGetScopeProps(pszName, pMvid);
+ }
+
+ __checkReturn
+ HRESULT CommonGetTypeRefProps(
+ mdTypeRef tr,
+ LPCUTF8 *pszNamespace,
+ LPCUTF8 *pszName,
+ mdToken *ptkResolution)
+ {
+ return m_pWinMDAdapter->GetTypeRefProps(tr, pszNamespace, pszName, ptkResolution);
+ }
+
+ __checkReturn
+ HRESULT CommonGetTypeDefProps(
+ mdTypeDef td,
+ LPCUTF8 *pszNameSpace,
+ LPCUTF8 *pszName,
+ DWORD *pdwFlags,
+ mdToken *pdwExtends,
+ ULONG *pMethodList)
+ {
+ // We currently don't support retrieving the method list.
+ if (pMethodList)
+ return E_NOTIMPL;
+
+ return m_pWinMDAdapter->GetTypeDefProps(td, pszNameSpace, pszName, pdwFlags, pdwExtends);
+ }
+
+ __checkReturn
+ HRESULT CommonGetTypeSpecProps(
+ mdTypeSpec ts,
+ PCCOR_SIGNATURE *ppvSig,
+ ULONG *pcbSig)
+ {
+ return m_pWinMDAdapter->GetSignatureForToken<IMDInternalImport, mdtTypeSpec>(
+ ts,
+ NULL, // ppOrigSig
+ NULL, // pcbOrigSig
+ ppvSig,
+ pcbSig,
+ m_pRawInternalImport);
+ }
+
+ __checkReturn
+ HRESULT CommonGetEnclosingClassOfTypeDef(
+ mdTypeDef td,
+ mdTypeDef *ptkEnclosingTypeDef)
+ {
+ return m_pRawMetaModelCommon->CommonGetEnclosingClassOfTypeDef(td, ptkEnclosingTypeDef);
+ }
+
+ __checkReturn
+ HRESULT CommonGetAssemblyProps(
+ USHORT *pusMajorVersion,
+ USHORT *pusMinorVersion,
+ USHORT *pusBuildNumber,
+ USHORT *pusRevisionNumber,
+ DWORD *pdwFlags,
+ const void **ppbPublicKey,
+ ULONG *pcbPublicKey,
+ LPCUTF8 *pszName,
+ LPCUTF8 *pszLocale)
+ {
+ HRESULT hr;
+ AssemblyMetaDataInternal MetaData;
+ mdToken tkAssembly = TokenFromRid(1, mdtAssembly);
+
+ IfFailRet(GetAssemblyProps(
+ tkAssembly,
+ ppbPublicKey,
+ pcbPublicKey,
+ NULL,
+ pszName,
+ &MetaData,
+ pdwFlags));
+
+ if (pusMajorVersion)
+ *pusMajorVersion = MetaData.usMajorVersion;
+ if (pusMinorVersion)
+ *pusMinorVersion = MetaData.usMinorVersion;
+ if (pusBuildNumber)
+ *pusBuildNumber = MetaData.usBuildNumber;
+ if (pusRevisionNumber)
+ *pusRevisionNumber = MetaData.usRevisionNumber;
+ if (pszLocale)
+ *pszLocale = MetaData.szLocale;
+
+ return S_OK;
+ }
+
+ __checkReturn
+ HRESULT CommonGetAssemblyRefProps(
+ mdAssemblyRef tkAssemRef,
+ USHORT *pusMajorVersion,
+ USHORT *pusMinorVersion,
+ USHORT *pusBuildNumber,
+ USHORT *pusRevisionNumber,
+ DWORD *pdwFlags,
+ const void **ppbPublicKeyOrToken,
+ ULONG *pcbPublicKeyOrToken,
+ LPCUTF8 *pszName,
+ LPCUTF8 *pszLocale,
+ const void **ppbHashValue,
+ ULONG *pcbHashValue)
+ {
+ HRESULT hr;
+
+ AssemblyMetaDataInternal MetaData;
+ IfFailRet(GetAssemblyRefProps(
+ tkAssemRef,
+ ppbPublicKeyOrToken,
+ pcbPublicKeyOrToken,
+ pszName,
+ &MetaData,
+ ppbHashValue,
+ pcbHashValue,
+ pdwFlags));
+
+ if (pusMajorVersion)
+ *pusMajorVersion = MetaData.usMajorVersion;
+ if (pusMinorVersion)
+ *pusMinorVersion = MetaData.usMinorVersion;
+ if (pusBuildNumber)
+ *pusBuildNumber = MetaData.usBuildNumber;
+ if (pusRevisionNumber)
+ *pusRevisionNumber = MetaData.usRevisionNumber;
+ if (pszLocale)
+ *pszLocale = MetaData.szLocale;
+
+ return S_OK;
+ }
+
+ __checkReturn
+ HRESULT CommonGetModuleRefProps(
+ mdModuleRef tkModuleRef,
+ LPCUTF8 *pszName)
+ {
+ return m_pRawMetaModelCommon->CommonGetModuleRefProps(tkModuleRef, pszName);
+ }
+
+ __checkReturn
+ HRESULT CommonFindExportedType(
+ LPCUTF8 szNamespace,
+ LPCUTF8 szName,
+ mdToken tkEnclosingType,
+ mdExportedType *ptkExportedType)
+ {
+ return m_pWinMDAdapter->FindExportedType(szNamespace, szName, tkEnclosingType, ptkExportedType);
+ }
+
+ __checkReturn
+ HRESULT CommonGetExportedTypeProps(
+ mdToken tkExportedType,
+ LPCUTF8 *pszNamespace,
+ LPCUTF8 *pszName,
+ mdToken *ptkImpl)
+ {
+ return GetExportedTypeProps(
+ tkExportedType,
+ pszNamespace,
+ pszName,
+ ptkImpl,
+ NULL,
+ NULL);
+ }
+
+ __checkReturn
+ HRESULT CommonGetCustomAttributeByNameEx( // S_OK or error.
+ mdToken tkObj, // [IN] Object with Custom Attribute.
+ LPCUTF8 szName, // [IN] Name of desired Custom Attribute.
+ mdCustomAttribute *ptkCA, // [OUT] put custom attribute token here
+ const void **ppData, // [OUT] Put pointer to data here.
+ ULONG *pcbData) // [OUT] Put size of data here.
+ {
+ return m_pWinMDAdapter->GetCustomAttributeByName(tkObj, szName, ptkCA, ppData, pcbData);
+ }
+
+ __checkReturn
+ HRESULT FindParentOfMethodHelper(mdMethodDef md, mdTypeDef *ptd)
+ {
+ return m_pRawMetaModelCommon->FindParentOfMethodHelper(md, ptd);
+ }
+
+ int CommonIsRo()
+ {
+ return m_pRawMetaModelCommon->CommonIsRo();
+ }
+
+ private:
+ //=========================================================
+ // Private instance data
+ //=========================================================
+ IMDCommon *m_pRawMDCommon;
+ IMetaModelCommon *m_pRawMetaModelCommon;
+ IMDInternalImport *m_pRawInternalImport;
+ WinMDAdapter *m_pWinMDAdapter;
+ LONG m_cRef;
+}; // class WinMDInternalImportRO
+
+
+
+
+//========================================================================================
+// Entrypoint called by GetMDInternalInterface()
+//========================================================================================
+HRESULT CreateWinMDInternalImportRO(IMDCommon * pRawMDCommon, REFIID riid, /*[out]*/ void **ppWinMDInternalImport)
+{
+ HRESULT hr;
+ *ppWinMDInternalImport = NULL;
+ WinMDInternalImportRO *pNewImport = NULL;
+ IfFailGo(WinMDInternalImportRO::Create(pRawMDCommon, &pNewImport));
+ IfFailGo(pNewImport->QueryInterface(riid, ppWinMDInternalImport));
+ hr = S_OK;
+
+ ErrExit:
+ if (pNewImport)
+ pNewImport->Release();
+ return hr;
+
+}
+
+#endif // FEATURE_METADATA_INTERNAL_APIS
+
+
+
diff --git a/src/md/winmd/wks/.gitmirror b/src/md/winmd/wks/.gitmirror
new file mode 100644
index 0000000000..f507630f94
--- /dev/null
+++ b/src/md/winmd/wks/.gitmirror
@@ -0,0 +1 @@
+Only contents of this folder, excluding subfolders, will be mirrored by the Git-TFS Mirror. \ No newline at end of file
diff --git a/src/md/winmd/wks/CMakeLists.txt b/src/md/winmd/wks/CMakeLists.txt
new file mode 100644
index 0000000000..139b68b28c
--- /dev/null
+++ b/src/md/winmd/wks/CMakeLists.txt
@@ -0,0 +1,4 @@
+include(../../md_wks.cmake)
+
+add_precompiled_header(stdafx.h ../stdafx.cpp MDWINMD_SOURCES)
+add_library_clr(mdwinmd_wks ${MDWINMD_SOURCES}) \ No newline at end of file
diff --git a/src/md/winmd/wks/MDWinMD_wks.nativeproj b/src/md/winmd/wks/MDWinMD_wks.nativeproj
new file mode 100644
index 0000000000..cc0a6f2bc1
--- /dev/null
+++ b/src/md/winmd/wks/MDWinMD_wks.nativeproj
@@ -0,0 +1,19 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <!-- All features are set in file:..\..\MD.props -->
+ <MetadataFlavor>wks</MetadataFlavor>
+ </PropertyGroup>
+
+ <!--Import the settings-->
+ <Import Project="$(_NTDRIVE)$(_NTROOT)\ndp\clr\src\MD\WinMD\WinMD.settings.targets" />
+
+ <!--Leaf project Properties-->
+ <PropertyGroup>
+ <BuildCoreBinaries>true</BuildCoreBinaries>
+ <BuildSysBinaries>true</BuildSysBinaries>
+ <OutputName>MDWinMD_wks</OutputName>
+ </PropertyGroup>
+
+ <!--Import the targets-->
+ <Import Project="$(_NTDRIVE)$(_NTROOT)\ndp\clr\clr.targets" />
+</Project>