summaryrefslogtreecommitdiff
path: root/src/md/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'src/md/runtime')
-rw-r--r--src/md/runtime/.gitmirror1
-rw-r--r--src/md/runtime/CMakeLists.txt23
-rw-r--r--src/md/runtime/Runtime.settings.targets43
-rw-r--r--src/md/runtime/crossgen/.gitmirror1
-rw-r--r--src/md/runtime/crossgen/CMakeLists.txt5
-rw-r--r--src/md/runtime/crossgen/MDRuntime_crossgen.nativeproj15
-rw-r--r--src/md/runtime/dac/.gitmirror1
-rw-r--r--src/md/runtime/dac/CMakeLists.txt7
-rw-r--r--src/md/runtime/dac/dirs.proj19
-rw-r--r--src/md/runtime/dbi/.gitmirror1
-rw-r--r--src/md/runtime/dbi/CMakeLists.txt3
-rw-r--r--src/md/runtime/dbi/MDRuntime-dbi.props10
-rw-r--r--src/md/runtime/dbi/dirs.proj19
-rw-r--r--src/md/runtime/dirs.proj22
-rw-r--r--src/md/runtime/liteweightstgdb.cpp262
-rw-r--r--src/md/runtime/mdcolumndescriptors.cpp214
-rw-r--r--src/md/runtime/mdfileformat.cpp195
-rw-r--r--src/md/runtime/mdinternaldisp.cpp1834
-rw-r--r--src/md/runtime/mdinternaldisp.h44
-rw-r--r--src/md/runtime/mdinternalro.cpp3742
-rw-r--r--src/md/runtime/mdinternalro.h849
-rw-r--r--src/md/runtime/metamodel.cpp1240
-rw-r--r--src/md/runtime/metamodelcolumndefs.h401
-rw-r--r--src/md/runtime/metamodelro.cpp444
-rw-r--r--src/md/runtime/recordpool.cpp388
-rw-r--r--src/md/runtime/stdafx.cpp12
-rw-r--r--src/md/runtime/stdafx.h24
-rw-r--r--src/md/runtime/wks/.gitmirror1
-rw-r--r--src/md/runtime/wks/CMakeLists.txt5
-rw-r--r--src/md/runtime/wks/MDRuntime.nativeproj19
30 files changed, 9844 insertions, 0 deletions
diff --git a/src/md/runtime/.gitmirror b/src/md/runtime/.gitmirror
new file mode 100644
index 0000000000..f507630f94
--- /dev/null
+++ b/src/md/runtime/.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/runtime/CMakeLists.txt b/src/md/runtime/CMakeLists.txt
new file mode 100644
index 0000000000..96c9b5114a
--- /dev/null
+++ b/src/md/runtime/CMakeLists.txt
@@ -0,0 +1,23 @@
+add_definitions(-DNO_COR)
+
+set(MDRUNTIME_SOURCES
+ mdcolumndescriptors.cpp
+ liteweightstgdb.cpp
+ mdfileformat.cpp
+ metamodel.cpp
+ metamodelro.cpp
+ recordpool.cpp
+ mdinternaldisp.cpp
+ mdinternalro.cpp
+)
+
+convert_to_absolute_path(MDRUNTIME_SOURCES ${MDRUNTIME_SOURCES})
+
+if(CLR_CMAKE_PLATFORM_UNIX)
+ add_compile_options(-fPIC)
+endif(CLR_CMAKE_PLATFORM_UNIX)
+
+add_subdirectory(dac)
+add_subdirectory(wks)
+add_subdirectory(dbi)
+add_subdirectory(crossgen)
diff --git a/src/md/runtime/Runtime.settings.targets b/src/md/runtime/Runtime.settings.targets
new file mode 100644
index 0000000000..1ac62d7181
--- /dev/null
+++ b/src/md/runtime/Runtime.settings.targets
@@ -0,0 +1,43 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <!--Import the settings-->
+ <Import Project="$(_NTDRIVE)$(_NTROOT)\ndp\clr\src\MD\MD.props" />
+
+ <!--Leaf project Properties-->
+ <PropertyGroup>
+ <MDRuntimeSrcDirectory>$(ClrSrcDirectory)\MD\Runtime\</MDRuntimeSrcDirectory>
+ <UserIncludes>
+ $(UserIncludes);
+ $(ClrSrcDirectory)\MD\inc;
+ $(ClrSrcDirectory)\vm;
+ $(ClrSrcDirectory)\strongname\inc</UserIncludes>
+ <ClAdditionalOptions>$(ClAdditionalOptions) -DUNICODE -D_UNICODE -DNO_COR</ClAdditionalOptions>
+ <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>$(MDRuntimeSrcDirectory)\stdafx.cpp</PCHCompile>
+ <PCHObject>stdafx_mdruntime.obj</PCHObject>
+ <LinkUseCMT>false</LinkUseCMT>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <ProjectReference Include="$(ClrSrcDirectory)inc\corguids.nativeproj">
+ <Comment>clrinternal.h</Comment>
+ </ProjectReference>
+ </ItemGroup>
+
+ <!--Leaf Project Items-->
+ <ItemGroup>
+ <CppCompile Include="$(MDRuntimeSrcDirectory)\MDColumnDescriptors.cpp" />
+ <CppCompile Include="$(MDRuntimeSrcDirectory)\LiteWeightStgdb.cpp" />
+ <CppCompile Include="$(MDRuntimeSrcDirectory)\MDFileFormat.cpp" />
+ <CppCompile Include="$(MDRuntimeSrcDirectory)\MetaModel.cpp" />
+ <CppCompile Include="$(MDRuntimeSrcDirectory)\MetaModelRO.cpp" />
+ <CppCompile Include="$(MDRuntimeSrcDirectory)\RecordPool.cpp" />
+
+ <!-- These sources contain internal Read-Only API implementation (IMDInternalRO) -->
+ <CppCompile Include="$(MDRuntimeSrcDirectory)\MDInternalDisp.cpp" />
+ <CppCompile Include="$(MDRuntimeSrcDirectory)\MDInternalRO.cpp" />
+ </ItemGroup>
+</Project>
diff --git a/src/md/runtime/crossgen/.gitmirror b/src/md/runtime/crossgen/.gitmirror
new file mode 100644
index 0000000000..f507630f94
--- /dev/null
+++ b/src/md/runtime/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/runtime/crossgen/CMakeLists.txt b/src/md/runtime/crossgen/CMakeLists.txt
new file mode 100644
index 0000000000..dfd0f34665
--- /dev/null
+++ b/src/md/runtime/crossgen/CMakeLists.txt
@@ -0,0 +1,5 @@
+include(${CLR_DIR}/crossgen.cmake)
+include(../../md_wks.cmake)
+
+add_precompiled_header(stdafx.h ../stdafx.cpp MDRUNTIME_SOURCES)
+add_library_clr(mdruntime_crossgen ${MDRUNTIME_SOURCES})
diff --git a/src/md/runtime/crossgen/MDRuntime_crossgen.nativeproj b/src/md/runtime/crossgen/MDRuntime_crossgen.nativeproj
new file mode 100644
index 0000000000..6b8cc00ffc
--- /dev/null
+++ b/src/md/runtime/crossgen/MDRuntime_crossgen.nativeproj
@@ -0,0 +1,15 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="dogfood">
+ <PropertyGroup>
+ <BuildSysBinaries>true</BuildSysBinaries>
+ <!-- All features are set in file:..\..\MD.props -->
+ <MetadataFlavor>wks</MetadataFlavor>
+ <OutputName>mdruntime_crossgen</OutputName>
+ </PropertyGroup>
+
+ <!--Import the settings-->
+ <Import Project="$(_NTDRIVE)$(_NTROOT)\ndp\clr\xplat\SetCrossGen.props" />
+ <Import Project="$(_NTDRIVE)$(_NTROOT)\ndp\clr\src\MD\Runtime\Runtime.settings.targets" />
+
+ <!--Import the targets-->
+ <Import Project="$(_NTDRIVE)$(_NTROOT)\ndp\clr\clr.targets" />
+</Project>
diff --git a/src/md/runtime/dac/.gitmirror b/src/md/runtime/dac/.gitmirror
new file mode 100644
index 0000000000..f507630f94
--- /dev/null
+++ b/src/md/runtime/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/runtime/dac/CMakeLists.txt b/src/md/runtime/dac/CMakeLists.txt
new file mode 100644
index 0000000000..337968e2ed
--- /dev/null
+++ b/src/md/runtime/dac/CMakeLists.txt
@@ -0,0 +1,7 @@
+
+include(${CLR_DIR}/dac.cmake)
+include(../../md_dac.cmake)
+
+add_precompiled_header(stdafx.h ../stdafx.cpp MDRUNTIME_SOURCES)
+
+add_library_clr(mdruntime_dac ${MDRUNTIME_SOURCES}) \ No newline at end of file
diff --git a/src/md/runtime/dac/dirs.proj b/src/md/runtime/dac/dirs.proj
new file mode 100644
index 0000000000..cc9e7a722c
--- /dev/null
+++ b/src/md/runtime/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" />
+
+ <!--The following projects will build during PHASE 1-->
+ <PropertyGroup>
+ <BuildInPhase1>true</BuildInPhase1>
+ <BuildInPhaseDefault>false</BuildInPhaseDefault>
+ <BuildCoreBinaries>true</BuildCoreBinaries>
+ <BuildSysBinaries>true</BuildSysBinaries>
+ </PropertyGroup>
+
+ <ItemGroup Condition="'$(BuildExePhase)' == '1'">
+ <ProjectFile Include="HostLocal\mdruntime_dac.nativeproj" />
+ </ItemGroup>
+
+ <!--Import the targets-->
+ <Import Project="$(_NTDRIVE)$(_NTROOT)\tools\Microsoft.DevDiv.Traversal.targets" />
+</Project>
diff --git a/src/md/runtime/dbi/.gitmirror b/src/md/runtime/dbi/.gitmirror
new file mode 100644
index 0000000000..f507630f94
--- /dev/null
+++ b/src/md/runtime/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/runtime/dbi/CMakeLists.txt b/src/md/runtime/dbi/CMakeLists.txt
new file mode 100644
index 0000000000..6f706d2bfb
--- /dev/null
+++ b/src/md/runtime/dbi/CMakeLists.txt
@@ -0,0 +1,3 @@
+include(../../md_dbi.cmake)
+add_precompiled_header(stdafx.h ../stdafx.cpp MDRUNTIME_SOURCES)
+add_library_clr(mdruntime-dbi ${MDRUNTIME_SOURCES}) \ No newline at end of file
diff --git a/src/md/runtime/dbi/MDRuntime-dbi.props b/src/md/runtime/dbi/MDRuntime-dbi.props
new file mode 100644
index 0000000000..ce3ff3224b
--- /dev/null
+++ b/src/md/runtime/dbi/MDRuntime-dbi.props
@@ -0,0 +1,10 @@
+<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 the settings-->
+ <Import Project="$(_NTDRIVE)$(_NTROOT)\ndp\clr\src\MD\Runtime\Runtime.settings.targets" />
+
+</Project>
diff --git a/src/md/runtime/dbi/dirs.proj b/src/md/runtime/dbi/dirs.proj
new file mode 100644
index 0000000000..0f2f9b0613
--- /dev/null
+++ b/src/md/runtime/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" />
+
+ <!--The following projects will build during PHASE 1-->
+ <PropertyGroup>
+ <BuildInPhase1>true</BuildInPhase1>
+ <BuildInPhaseDefault>false</BuildInPhaseDefault>
+ <BuildCoreBinaries>true</BuildCoreBinaries>
+ <BuildSysBinaries>true</BuildSysBinaries>
+ </PropertyGroup>
+
+ <ItemGroup Condition="'$(BuildExePhase)' == '1'">
+ <ProjectFile Condition="'$(FeatureDbiDebugging)'=='true'" Include="HostLocal\mdruntime-dbi.nativeproj" />
+ </ItemGroup>
+
+ <!--Import the targets-->
+ <Import Project="$(_NTDRIVE)$(_NTROOT)\tools\Microsoft.DevDiv.Traversal.targets" />
+</Project>
diff --git a/src/md/runtime/dirs.proj b/src/md/runtime/dirs.proj
new file mode 100644
index 0000000000..2bd75ad013
--- /dev/null
+++ b/src/md/runtime/dirs.proj
@@ -0,0 +1,22 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <!--Import the settings-->
+ <Import Project="$(_NTDRIVE)$(_NTROOT)\ndp\clr\clr.props" />
+
+ <!--The following projects will build during PHASE 1-->
+ <PropertyGroup>
+ <BuildInPhase1>true</BuildInPhase1>
+ <BuildInPhaseDefault>false</BuildInPhaseDefault>
+ <BuildCoreBinaries>true</BuildCoreBinaries>
+ <BuildSysBinaries>true</BuildSysBinaries>
+ </PropertyGroup>
+
+ <ItemGroup Condition="'$(BuildExePhase)' == '1'">
+ <ProjectFile Include="wks\mdruntime.nativeproj" />
+ <ProjectFile Include="dbi\dirs.proj" />
+ <ProjectFile Include="dac\dirs.proj" />
+ <ProjectFile Include="winrt\mdruntime-winrt.nativeproj" />
+ </ItemGroup>
+
+ <!--Import the targets-->
+ <Import Project="$(_NTDRIVE)$(_NTROOT)\tools\Microsoft.DevDiv.Traversal.targets" />
+</Project>
diff --git a/src/md/runtime/liteweightstgdb.cpp b/src/md/runtime/liteweightstgdb.cpp
new file mode 100644
index 0000000000..8e64ad16e6
--- /dev/null
+++ b/src/md/runtime/liteweightstgdb.cpp
@@ -0,0 +1,262 @@
+// 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.
+//*****************************************************************************
+// LiteWeightStgdb.cpp
+//
+
+//
+// This contains definition of class CLiteWeightStgDB. This is light weight
+// read-only implementation for accessing compressed meta data format.
+//
+//*****************************************************************************
+#include "stdafx.h" // Precompiled header.
+#include "mdfileformat.h"
+#include "metamodelro.h"
+#include "liteweightstgdb.h"
+#include "metadatatracker.h"
+
+#include "../hotdata/export.h"
+
+__checkReturn
+HRESULT _CallInitOnMemHelper(CLiteWeightStgdb<CMiniMd> *pStgdb, ULONG cbData, LPCVOID pData)
+{
+ return pStgdb->InitOnMem(cbData,pData);
+}
+
+//*****************************************************************************
+// Open an in-memory metadata section for read
+//*****************************************************************************
+template <class MiniMd>
+__checkReturn
+HRESULT
+CLiteWeightStgdb<MiniMd>::InitOnMem(
+ ULONG cbData, // count of bytes in pData
+ LPCVOID pData) // points to meta data section in memory
+{
+ STORAGEHEADER sHdr; // Header for the storage.
+ PSTORAGESTREAM pStream; // Pointer to each stream.
+ int bFoundMd = false; // true when compressed data found.
+ int i; // Loop control.
+ HRESULT hr = S_OK;
+ ULONG cbStreamBuffer;
+
+ // Don't double open.
+ _ASSERTE((m_pvMd == NULL) && (m_cbMd == 0));
+
+ // Validate the signature of the format, or it isn't ours.
+ IfFailGo(MDFormat::VerifySignature((PSTORAGESIGNATURE)pData, cbData));
+
+#ifdef FEATURE_PREJIT
+ m_MiniMd.m_pHotTablesDirectory = NULL;
+#endif //FEATURE_PREJIT
+
+ // Remaining buffer size behind the stream header (pStream).
+ cbStreamBuffer = cbData;
+ // Get back the first stream.
+ pStream = MDFormat::GetFirstStream_Verify(&sHdr, pData, &cbStreamBuffer);
+ if (pStream == NULL)
+ {
+ Debug_ReportError("Invalid MetaData storage signature - cannot get the first stream header.");
+ IfFailGo(CLDB_E_FILE_CORRUPT);
+ }
+
+ // Loop through each stream and pick off the ones we need.
+ for (i = 0; i < sHdr.GetiStreams(); i++)
+ {
+ // Do we have enough buffer to read stream header?
+ if (cbStreamBuffer < sizeof(*pStream))
+ {
+ Debug_ReportError("Stream header is not within MetaData block.");
+ IfFailGo(CLDB_E_FILE_CORRUPT);
+ }
+ // Pick off the location and size of the data.
+ if (pStream->GetOffset() >= cbData)
+ { // Stream data are not in the buffer. Stream header is corrupted.
+ Debug_ReportError("Stream data are not within MetaData block.");
+ IfFailGo(CLDB_E_FILE_CORRUPT);
+ }
+ void *pvCurrentData = (void *)((BYTE *)pData + pStream->GetOffset());
+ ULONG cbCurrentData = pStream->GetSize();
+
+ // Get next stream.
+ PSTORAGESTREAM pNext = pStream->NextStream_Verify();
+ if (pNext == NULL)
+ { // Stream header is corrupted.
+ Debug_ReportError("Invalid stream header - cannot get next stream header.");
+ IfFailGo(CLDB_E_FILE_CORRUPT);
+ }
+
+ // Range check
+ if ((LPBYTE)pNext > ((LPBYTE)pData + cbData))
+ {
+ Debug_ReportError("Stream header is not within MetaData block.");
+ IfFailGo(CLDB_E_FILE_CORRUPT);
+ }
+
+ // Stream end must fit into the buffer and we have to check integer overflow (stream start is already checked)
+ if ((((LPBYTE)pvCurrentData + cbCurrentData) < (LPBYTE)pvCurrentData) ||
+ (((LPBYTE)pvCurrentData + cbCurrentData) > ((LPBYTE)pData + cbData)))
+ {
+ Debug_ReportError("Stream data are not within MetaData block.");
+ IfFailGo(CLDB_E_FILE_CORRUPT);
+ }
+
+ // String pool.
+ if (strcmp(pStream->GetName(), STRING_POOL_STREAM_A) == 0)
+ {
+ METADATATRACKER_ONLY(MetaDataTracker::NoteSection(TBL_COUNT + MDPoolStrings, pvCurrentData, cbCurrentData, 1));
+ // String pool has to end with a null-terminator, therefore we don't have to check string pool content on access.
+ // Shrink size of the pool to the last null-terminator found.
+ while (cbCurrentData != 0)
+ {
+ if (((LPBYTE)pvCurrentData)[cbCurrentData - 1] == 0)
+ { // We have found last null terminator
+ break;
+ }
+ // Shrink size of the pool
+ cbCurrentData--;
+ Debug_ReportError("String heap/pool does not end with null-terminator ... shrinking the heap.");
+ }
+ // Initialize string heap with null-terminated block of data
+ IfFailGo(m_MiniMd.m_StringHeap.Initialize(
+ MetaData::DataBlob((BYTE *)pvCurrentData, cbCurrentData),
+ FALSE)); // fCopyData
+ }
+
+ // Literal String Blob pool.
+ else if (strcmp(pStream->GetName(), US_BLOB_POOL_STREAM_A) == 0)
+ {
+ METADATATRACKER_ONLY(MetaDataTracker::NoteSection(TBL_COUNT + MDPoolUSBlobs, pvCurrentData, cbCurrentData, 1));
+ // Initialize user string heap with block of data
+ IfFailGo(m_MiniMd.m_UserStringHeap.Initialize(
+ MetaData::DataBlob((BYTE *)pvCurrentData, cbCurrentData),
+ FALSE)); // fCopyData
+ }
+
+ // GUID pool.
+ else if (strcmp(pStream->GetName(), GUID_POOL_STREAM_A) == 0)
+ {
+ METADATATRACKER_ONLY(MetaDataTracker::NoteSection(TBL_COUNT + MDPoolGuids, pvCurrentData, cbCurrentData, 1));
+ // Initialize guid heap with block of data
+ IfFailGo(m_MiniMd.m_GuidHeap.Initialize(
+ MetaData::DataBlob((BYTE *)pvCurrentData, cbCurrentData),
+ FALSE)); // fCopyData
+ }
+
+ // Blob pool.
+ else if (strcmp(pStream->GetName(), BLOB_POOL_STREAM_A) == 0)
+ {
+ METADATATRACKER_ONLY(MetaDataTracker::NoteSection(TBL_COUNT + MDPoolBlobs, pvCurrentData, cbCurrentData, 1));
+ // Initialize blob heap with block of data
+ IfFailGo(m_MiniMd.m_BlobHeap.Initialize(
+ MetaData::DataBlob((BYTE *)pvCurrentData, cbCurrentData),
+ FALSE)); // fCopyData
+ }
+
+ // Found the compressed meta data stream.
+ else if (strcmp(pStream->GetName(), COMPRESSED_MODEL_STREAM_A) == 0)
+ {
+ IfFailGo( m_MiniMd.InitOnMem(pvCurrentData, cbCurrentData) );
+ bFoundMd = true;
+ }
+
+ // Found the hot meta data stream
+ else if (strcmp(pStream->GetName(), HOT_MODEL_STREAM_A) == 0)
+ {
+#ifdef FEATURE_PREJIT
+ BYTE * hotStreamEnd = reinterpret_cast< BYTE * >( pvCurrentData ) + cbCurrentData;
+ ULONG * hotMetadataDir = reinterpret_cast< ULONG * >( hotStreamEnd ) - 2;
+ ULONG hotPoolsSize = *hotMetadataDir;
+
+ m_MiniMd.m_pHotTablesDirectory = (struct MetaData::HotTablesDirectory *)
+ (reinterpret_cast<BYTE *>(hotMetadataDir) - hotPoolsSize - sizeof(struct MetaData::HotTablesDirectory));
+ MetaData::HotTable::CheckTables(m_MiniMd.m_pHotTablesDirectory);
+
+ DataBuffer hotMetaData(
+ reinterpret_cast<BYTE *>(pvCurrentData),
+ cbCurrentData);
+ IfFailGo(InitHotPools(hotMetaData));
+#else //!FEATURE_PREJIT
+ Debug_ReportError("MetaData hot stream is peresent, but ngen is not supported.");
+ // Ignore the stream
+#endif //!FEATURE_PREJIT
+ }
+ // Pick off the next stream if there is one.
+ pStream = pNext;
+ cbStreamBuffer = (ULONG)((LPBYTE)pData + cbData - (LPBYTE)pNext);
+ }
+
+ // If the meta data wasn't found, we can't handle this file.
+ if (!bFoundMd)
+ {
+ Debug_ReportError("MetaData compressed model stream #~ not found.");
+ IfFailGo(CLDB_E_FILE_CORRUPT);
+ }
+ else
+ { // Validate sensible heaps.
+ IfFailGo(m_MiniMd.PostInit(0));
+ }
+
+ // Save off the location.
+ m_pvMd = pData;
+ m_cbMd = cbData;
+
+ErrExit:
+ return hr;
+} // CLiteWeightStgdb<MiniMd>::InitOnMem
+
+
+template <class MiniMd>
+__checkReturn
+HRESULT
+CLiteWeightStgdb<MiniMd>::InitHotPools(
+ DataBuffer hotMetaDataBuffer)
+{
+ HRESULT hr;
+ MetaData::HotMetaData hotMetaData;
+ MetaData::HotHeapsDirectoryIterator heapsIterator;
+
+ IfFailRet(hotMetaData.Initialize(hotMetaDataBuffer));
+
+ IfFailRet(hotMetaData.GetHeapsDirectoryIterator(&heapsIterator));
+
+ for (;;)
+ {
+ MetaData::HotHeap hotHeap;
+ MetaData::HeapIndex hotHeapIndex;
+
+ hr = heapsIterator.GetNext(&hotHeap, &hotHeapIndex);
+ if (hr == S_FALSE)
+ { // End of iteration
+ return S_OK;
+ }
+
+ switch (hotHeapIndex.Get())
+ {
+ case MetaData::HeapIndex::StringHeapIndex:
+ {
+ m_MiniMd.m_StringHeap.InitializeHotData(hotHeap);
+ break;
+ }
+ case MetaData::HeapIndex::GuidHeapIndex:
+ {
+ m_MiniMd.m_GuidHeap.InitializeHotData(hotHeap);
+ break;
+ }
+ case MetaData::HeapIndex::UserStringHeapIndex:
+ {
+ m_MiniMd.m_UserStringHeap.InitializeHotData(hotHeap);
+ break;
+ }
+ case MetaData::HeapIndex::BlobHeapIndex:
+ {
+ m_MiniMd.m_BlobHeap.InitializeHotData(hotHeap);
+ break;
+ }
+ default:
+ Debug_ReportInternalError("There's a bug in HotHeapsDirectoryIterator - it should verify the heap index.");
+ IfFailRet(METADATA_E_INTERNAL_ERROR);
+ }
+ }
+} // CLiteWeightStgdb<MiniMd>::InitHotPools
diff --git a/src/md/runtime/mdcolumndescriptors.cpp b/src/md/runtime/mdcolumndescriptors.cpp
new file mode 100644
index 0000000000..dfd063ecb6
--- /dev/null
+++ b/src/md/runtime/mdcolumndescriptors.cpp
@@ -0,0 +1,214 @@
+// 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"
+
+const BYTE CMiniMdBase::s_ModuleCol[] = {2,
+ 97,0,2, 101,2,2, 102,4,2, 102,6,2, 102,8,2,
+ 97,0,2, 101,2,4, 102,6,2, 102,8,2, 102,10,2,
+};
+const BYTE CMiniMdBase::s_TypeRefCol[] = {2,
+ 75,0,2, 101,2,2, 101,4,2,
+ 75,0,2, 101,2,4, 101,6,4,
+};
+const BYTE CMiniMdBase::s_TypeDefCol[] = {2,
+ 99,0,4, 101,4,2, 101,6,2, 64,8,2, 4,10,2, 6,12,2,
+ 99,0,4, 101,4,4, 101,8,4, 64,12,2, 4,14,2, 6,16,2,
+};
+const BYTE CMiniMdBase::s_FieldPtrCol[] = {1,
+ 4,0,2,
+};
+const BYTE CMiniMdBase::s_FieldCol[] = {3,
+ 97,0,2, 101,2,2, 103,4,2,
+ 97,0,2, 101,2,4, 103,6,4,
+ 97,0,2, 101,2,4, 103,6,2,
+};
+const BYTE CMiniMdBase::s_MethodPtrCol[] = {1,
+ 6,0,2,
+};
+const BYTE CMiniMdBase::s_MethodCol[] = {3,
+ 99,0,4, 97,4,2, 97,6,2, 101,8,2, 103,10,2, 8,12,2,
+ 99,0,4, 97,4,2, 97,6,2, 101,8,4, 103,12,4, 8,16,2,
+ 99,0,4, 97,4,2, 97,6,2, 101,8,4, 103,12,2, 8,14,2,
+};
+const BYTE CMiniMdBase::s_ParamPtrCol[] = {1,
+ 8,0,2,
+};
+const BYTE CMiniMdBase::s_ParamCol[] = {2,
+ 97,0,2, 97,2,2, 101,4,2,
+ 97,0,2, 97,2,2, 101,4,4,
+};
+const BYTE CMiniMdBase::s_InterfaceImplCol[] = {1,
+ 2,0,2, 64,2,2,
+};
+const BYTE CMiniMdBase::s_MemberRefCol[] = {3,
+ 69,0,2, 101,2,2, 103,4,2,
+ 69,0,4, 101,4,4, 103,8,4,
+ 69,0,2, 101,2,4, 103,6,2,
+};
+const BYTE CMiniMdBase::s_ConstantCol[] = {3,
+ 100,0,1, 65,2,2, 103,4,2,
+ 100,0,1, 65,2,4, 103,6,4,
+ 100,0,1, 65,2,2, 103,4,4,
+};
+const BYTE CMiniMdBase::s_CustomAttributeCol[] = {3,
+ 66,0,2, 74,2,2, 103,4,2,
+ 66,0,4, 74,4,4, 103,8,4,
+ 66,0,4, 74,4,2, 103,6,2,
+};
+const BYTE CMiniMdBase::s_FieldMarshalCol[] = {2,
+ 67,0,2, 103,2,2,
+ 67,0,2, 103,2,4,
+};
+const BYTE CMiniMdBase::s_DeclSecurityCol[] = {3,
+ 96,0,2, 68,2,2, 103,4,2,
+ 96,0,2, 68,2,4, 103,6,4,
+ 96,0,2, 68,2,2, 103,4,4,
+};
+const BYTE CMiniMdBase::s_ClassLayoutCol[] = {1,
+ 97,0,2, 99,2,4, 2,6,2,
+};
+const BYTE CMiniMdBase::s_FieldLayoutCol[] = {1,
+ 99,0,4, 4,4,2,
+};
+const BYTE CMiniMdBase::s_StandAloneSigCol[] = {2,
+ 103,0,2,
+ 103,0,4,
+};
+const BYTE CMiniMdBase::s_EventMapCol[] = {1,
+ 2,0,2, 20,2,2,
+};
+const BYTE CMiniMdBase::s_EventPtrCol[] = {1,
+ 20,0,2,
+};
+const BYTE CMiniMdBase::s_EventCol[] = {2,
+ 97,0,2, 101,2,2, 64,4,2,
+ 97,0,2, 101,2,4, 64,6,2,
+};
+const BYTE CMiniMdBase::s_PropertyMapCol[] = {1,
+ 2,0,2, 23,2,2,
+};
+const BYTE CMiniMdBase::s_PropertyPtrCol[] = {1,
+ 23,0,2,
+};
+const BYTE* CMiniMdBase::s_PropertyCol = s_FieldCol;
+const BYTE CMiniMdBase::s_MethodSemanticsCol[] = {1,
+ 97,0,2, 6,2,2, 70,4,2,
+};
+const BYTE CMiniMdBase::s_MethodImplCol[] = {1,
+ 2,0,2, 71,2,2, 71,4,2,
+};
+const BYTE CMiniMdBase::s_ModuleRefCol[] = {2,
+ 101,0,2,
+ 101,0,4,
+};
+const BYTE* CMiniMdBase::s_TypeSpecCol = s_StandAloneSigCol;
+const BYTE CMiniMdBase::s_ImplMapCol[] = {2,
+ 97,0,2, 72,2,2, 101,4,2, 26,6,2,
+ 97,0,2, 72,2,2, 101,4,4, 26,8,2,
+};
+const BYTE* CMiniMdBase::s_FieldRVACol = s_FieldLayoutCol;
+const BYTE CMiniMdBase::s_ENCLogCol[] = {1,
+ 99,0,4, 99,4,4,
+};
+const BYTE CMiniMdBase::s_ENCMapCol[] = {1,
+ 99,0,4,
+};
+const BYTE CMiniMdBase::s_AssemblyCol[] = {3,
+ 99,0,4, 97,4,2, 97,6,2, 97,8,2, 97,10,2, 99,12,4, 103,16,2, 101,18,2, 101,20,2,
+ 99,0,4, 97,4,2, 97,6,2, 97,8,2, 97,10,2, 99,12,4, 103,16,4, 101,20,4, 101,24,4,
+ 99,0,4, 97,4,2, 97,6,2, 97,8,2, 97,10,2, 99,12,4, 103,16,2, 101,18,4, 101,22,4,
+};
+const BYTE* CMiniMdBase::s_AssemblyProcessorCol = s_ENCMapCol;
+const BYTE CMiniMdBase::s_AssemblyOSCol[] = {1,
+ 99,0,4, 99,4,4, 99,8,4,
+};
+const BYTE CMiniMdBase::s_AssemblyRefCol[] = {3,
+ 97,0,2, 97,2,2, 97,4,2, 97,6,2, 99,8,4, 103,12,2, 101,14,2, 101,16,2, 103,18,2,
+ 97,0,2, 97,2,2, 97,4,2, 97,6,2, 99,8,4, 103,12,4, 101,16,4, 101,20,4, 103,24,4,
+ 97,0,2, 97,2,2, 97,4,2, 97,6,2, 99,8,4, 103,12,2, 101,14,4, 101,18,4, 103,22,2,
+};
+const BYTE CMiniMdBase::s_AssemblyRefProcessorCol[] = {1,
+ 99,0,4, 35,4,2,
+};
+const BYTE CMiniMdBase::s_AssemblyRefOSCol[] = {1,
+ 99,0,4, 99,4,4, 99,8,4, 35,12,2,
+};
+const BYTE CMiniMdBase::s_FileCol[] = {3,
+ 99,0,4, 101,4,2, 103,6,2,
+ 99,0,4, 101,4,4, 103,8,4,
+ 99,0,4, 101,4,4, 103,8,2,
+};
+const BYTE CMiniMdBase::s_ExportedTypeCol[] = {2,
+ 99,0,4, 99,4,4, 101,8,2, 101,10,2, 73,12,2,
+ 99,0,4, 99,4,4, 101,8,4, 101,12,4, 73,16,2,
+};
+const BYTE CMiniMdBase::s_ManifestResourceCol[] = {2,
+ 99,0,4, 99,4,4, 101,8,2, 73,10,2,
+ 99,0,4, 99,4,4, 101,8,4, 73,12,2,
+};
+const BYTE CMiniMdBase::s_NestedClassCol[] = {1,
+ 2,0,2, 2,2,2,
+};
+const BYTE CMiniMdBase::s_GenericParamCol[] = {2,
+ 97,0,2, 97,2,2, 76,4,2, 101,6,2, 64,8,2, 64,10,2,
+ 97,0,2, 97,2,2, 76,4,2, 101,6,4, 64,10,2, 64,12,2,
+};
+const BYTE CMiniMdBase::s_MethodSpecCol[] = {2,
+ 71,0,2, 103,2,2,
+ 71,0,2, 103,2,4,
+};
+const BYTE CMiniMdBase::s_GenericParamConstraintCol[] = {1,
+ 42,0,2, 64,2,2,
+};
+
+const BYTE* const CMiniMdBase::s_TableColumnDescriptors[] = {
+s_ModuleCol,
+s_TypeRefCol,
+s_TypeDefCol,
+s_FieldPtrCol,
+s_FieldCol,
+s_MethodPtrCol,
+s_MethodCol,
+s_ParamPtrCol,
+s_ParamCol,
+s_InterfaceImplCol,
+s_MemberRefCol,
+s_ConstantCol,
+s_CustomAttributeCol,
+s_FieldMarshalCol,
+s_DeclSecurityCol,
+s_ClassLayoutCol,
+s_FieldLayoutCol,
+s_StandAloneSigCol,
+s_EventMapCol,
+s_EventPtrCol,
+s_EventCol,
+s_PropertyMapCol,
+s_PropertyPtrCol,
+s_FieldCol,
+s_MethodSemanticsCol,
+s_MethodImplCol,
+s_ModuleRefCol,
+s_StandAloneSigCol,
+s_ImplMapCol,
+s_FieldLayoutCol,
+s_ENCLogCol,
+s_ENCMapCol,
+s_AssemblyCol,
+s_ENCMapCol,
+s_AssemblyOSCol,
+s_AssemblyRefCol,
+s_AssemblyRefProcessorCol,
+s_AssemblyRefOSCol,
+s_FileCol,
+s_ExportedTypeCol,
+s_ManifestResourceCol,
+s_NestedClassCol,
+s_GenericParamCol,
+s_MethodSpecCol,
+s_GenericParamConstraintCol
+};
diff --git a/src/md/runtime/mdfileformat.cpp b/src/md/runtime/mdfileformat.cpp
new file mode 100644
index 0000000000..2edd2e0292
--- /dev/null
+++ b/src/md/runtime/mdfileformat.cpp
@@ -0,0 +1,195 @@
+// 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.
+//*****************************************************************************
+// MDFileFormat.cpp
+//
+
+//
+// This file contains a set of helpers to verify and read the file format.
+// This code does not handle the paging of the data, or different types of
+// I/O. See the StgTiggerStorage and StgIO code for this level of support.
+//
+//*****************************************************************************
+
+#include "stdafx.h" // Standard header file.
+#include "mdfileformat.h" // The format helpers.
+#include "posterror.h" // Error handling code.
+
+//*****************************************************************************
+// Verify the signature at the front of the file to see what type it is.
+//*****************************************************************************
+#define STORAGE_MAGIC_OLD_SIG 0x2B4D4F43 // +MOC (old version of BSJB signature code:STORAGE_MAGIC_SIG)
+HRESULT
+MDFormat::VerifySignature(
+ PSTORAGESIGNATURE pSig, // The signature to check.
+ ULONG cbData)
+{
+ HRESULT hr = S_OK;
+
+ // If signature didn't match, you shouldn't be here.
+ ULONG dwSignature = pSig->GetSignature();
+ if (dwSignature == STORAGE_MAGIC_OLD_SIG)
+ {
+ Debug_ReportError("Invalid MetaData storage signature - old magic signature +MOC.");
+ return PostError(CLDB_E_FILE_OLDVER, 1, 0);
+ }
+ if (dwSignature != STORAGE_MAGIC_SIG)
+ {
+ Debug_ReportError("Invalid MetaData storage signature - unrecognized magic signature, should be BSJB.");
+ return PostError(CLDB_E_FILE_CORRUPT);
+ }
+
+ // Check for overflow
+ ULONG lVersionString = pSig->GetVersionStringLength();
+ ULONG sum = sizeof(STORAGESIGNATURE) + lVersionString;
+ if ((sum < sizeof(STORAGESIGNATURE)) || (sum < lVersionString))
+ {
+ Debug_ReportError("Invalid MetaData storage signature - version string too long, integer overflow.");
+ return PostError(CLDB_E_FILE_CORRUPT);
+ }
+
+ // Check for invalid version string size
+ if ((sizeof(STORAGESIGNATURE) + lVersionString) > cbData)
+ {
+ Debug_ReportError("Invalid MetaData storage signature - version string too long.");
+ return PostError(CLDB_E_FILE_CORRUPT);
+ }
+
+ // Check that the version string is null terminated. This string
+ // is ANSI, so no double-null checks need to be made.
+ {
+ BYTE *pStart = &pSig->pVersion[0];
+ BYTE *pEnd = pStart + lVersionString + 1; // Account for terminating NULL
+ BYTE *pCur;
+
+ for (pCur = pStart; pCur < pEnd; pCur++)
+ {
+ if (*pCur == 0)
+ break;
+ }
+
+ // If we got to the end without hitting a NULL, we have a bad version string
+ if (pCur == pEnd)
+ {
+ Debug_ReportError("Invalid MetaData storage signature - version string has not null-terminator.");
+ return PostError(CLDB_E_FILE_CORRUPT);
+ }
+ }
+
+#if !defined(FEATURE_METADATA_STANDALONE_WINRT)
+ // Only a specific version of the 0.x format is supported by this code
+ // in order to support the NT 5 beta clients which used this format.
+ if (pSig->GetMajorVer() == FILE_VER_MAJOR_v0)
+ {
+ if (pSig->GetMinorVer() < FILE_VER_MINOR_v0)
+ {
+ Debug_ReportError("Invalid MetaData storage signature - unrecognized version, should be 1.1.");
+ hr = CLDB_E_FILE_OLDVER;
+ }
+ }
+ else
+#endif // !defined(FEATURE_METADATA_STANDALONE_WINRT)
+ // There is currently no code to migrate an old format of the 1.x. This
+ // would be added only under special circumstances.
+ if ((pSig->GetMajorVer() != FILE_VER_MAJOR) || (pSig->GetMinorVer() != FILE_VER_MINOR))
+ {
+ Debug_ReportError("Invalid MetaData storage signature - unrecognized version, should be 1.1.");
+ hr = CLDB_E_FILE_OLDVER;
+ }
+
+ if (FAILED(hr))
+ hr = PostError(hr, (int)pSig->GetMajorVer(), (int)pSig->GetMinorVer());
+ return hr;
+} // MDFormat::VerifySignature
+
+//*****************************************************************************
+// Skip over the header and find the actual stream data.
+// It doesn't perform any checks for buffer overflow - use GetFirstStream_Verify
+// instead.
+//*****************************************************************************
+PSTORAGESTREAM
+MDFormat::GetFirstStream(
+ PSTORAGEHEADER pHeader, // Return copy of header struct.
+ const void *pvMd) // Pointer to the full file.
+{
+ const BYTE *pbMd;
+
+ // Header data starts after signature.
+ pbMd = (const BYTE *) pvMd;
+ pbMd += sizeof(STORAGESIGNATURE);
+ pbMd += ((STORAGESIGNATURE*)pvMd)->GetVersionStringLength();
+ PSTORAGEHEADER pHdr = (PSTORAGEHEADER) pbMd;
+ *pHeader = *pHdr;
+ pbMd += sizeof(STORAGEHEADER);
+
+ // ECMA specifies that the flags field is "reserved, must be 0".
+ if (pHdr->GetFlags() != 0)
+ return NULL;
+
+ // The pointer is now at the first stream in the list.
+ return ((PSTORAGESTREAM) pbMd);
+} // MDFormat::GetFirstStream
+
+//*****************************************************************************
+// Skip over the header and find the actual stream data. Secure version of
+// GetFirstStream method.
+// The header is supposed to be verified by VerifySignature.
+//
+// Returns pointer to the first stream (behind storage header) and the size of
+// the remaining buffer in *pcbMd (could be 0).
+// Returns NULL if there is not enough buffer for reading the headers. The *pcbMd
+// could be changed if NULL returned.
+//
+// Caller has to check available buffer size before using the first stream.
+//*****************************************************************************
+PSTORAGESTREAM
+MDFormat::GetFirstStream_Verify(
+ PSTORAGEHEADER pHeader, // Return copy of header struct.
+ const void *pvMd, // Pointer to the full file.
+ ULONG *pcbMd) // [in, out] Size of pvMd buffer (we don't want to read behind it)
+{
+ const BYTE *pbMd;
+
+ // Header data starts after signature.
+ pbMd = (const BYTE *)pvMd;
+ // Check read buffer overflow
+ if (*pcbMd < sizeof(STORAGESIGNATURE))
+ {
+ Debug_ReportError("Invalid MetaData - Storage signature doesn't fit.");
+ return NULL;
+ }
+ pbMd += sizeof(STORAGESIGNATURE);
+ *pcbMd -= sizeof(STORAGESIGNATURE);
+
+ ULONG cbVersionString = ((STORAGESIGNATURE *)pvMd)->GetVersionStringLength();
+ // Check read buffer overflow
+ if (*pcbMd < cbVersionString)
+ {
+ Debug_ReportError("Invalid MetaData storage signature - Version string doesn't fit.");
+ return NULL;
+ }
+ pbMd += cbVersionString;
+ *pcbMd -= cbVersionString;
+
+ // Is there enough space for storage header?
+ if (*pcbMd < sizeof(STORAGEHEADER))
+ {
+ Debug_ReportError("Invalid MetaData storage header - Storage header doesn't fit.");
+ return NULL;
+ }
+ PSTORAGEHEADER pHdr = (PSTORAGEHEADER) pbMd;
+ *pHeader = *pHdr;
+ pbMd += sizeof(STORAGEHEADER);
+ *pcbMd -= sizeof(STORAGEHEADER);
+
+ // ECMA specifies that the flags field is "reserved, must be 0".
+ if (pHdr->GetFlags() != 0)
+ {
+ Debug_ReportError("Invalid MetaData storage header - Flags are not 0.");
+ return NULL;
+ }
+
+ // The pointer is now at the first stream in the list.
+ return (PSTORAGESTREAM)pbMd;
+} // MDFormat::GetFirstStream
diff --git a/src/md/runtime/mdinternaldisp.cpp b/src/md/runtime/mdinternaldisp.cpp
new file mode 100644
index 0000000000..1f5725ff01
--- /dev/null
+++ b/src/md/runtime/mdinternaldisp.cpp
@@ -0,0 +1,1834 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+// ===========================================================================
+// File: MDInternalDisp.CPP
+//
+
+// Notes:
+//
+//
+// ===========================================================================
+#include "stdafx.h"
+#include "mdinternaldisp.h"
+#include "mdinternalro.h"
+#include "posterror.h"
+#include "corpriv.h"
+#include "assemblymdinternaldisp.h"
+#include "pedecoder.h"
+#include "winmdinterfaces.h"
+
+#ifdef FEATURE_METADATA_INTERNAL_APIS
+
+// forward declaration
+HRESULT GetInternalWithRWFormat(
+ LPVOID pData,
+ ULONG cbData,
+ DWORD flags, // [IN] MDInternal_OpenForRead or MDInternal_OpenForENC
+ REFIID riid, // [in] The interface desired.
+ void **ppIUnk); // [out] Return interface on success.
+
+//*****************************************************************************
+// CheckFileFormat
+// This function will determine if the in-memory image is a readonly, readwrite,
+// or ICR format.
+//*****************************************************************************
+HRESULT
+CheckFileFormat(
+ LPVOID pData,
+ ULONG cbData,
+ MDFileFormat *pFormat) // [OUT] the file format
+{
+ HRESULT hr = NOERROR;
+ STORAGEHEADER sHdr; // Header for the storage.
+ PSTORAGESTREAM pStream; // Pointer to each stream.
+ int i;
+ ULONG cbStreamBuffer;
+
+ _ASSERTE(pFormat != NULL);
+
+ *pFormat = MDFormat_Invalid;
+
+ // Validate the signature of the format, or it isn't ours.
+ if (FAILED(hr = MDFormat::VerifySignature((PSTORAGESIGNATURE) pData, cbData)))
+ goto ErrExit;
+
+ // Remaining buffer size behind the stream header (pStream).
+ cbStreamBuffer = cbData;
+ // Get back the first stream.
+ pStream = MDFormat::GetFirstStream_Verify(&sHdr, pData, &cbStreamBuffer);
+ if (pStream == NULL)
+ {
+ Debug_ReportError("Invalid MetaData storage signature - cannot get the first stream header.");
+ IfFailGo(CLDB_E_FILE_CORRUPT);
+ }
+
+ // Loop through each stream and pick off the ones we need.
+ for (i = 0; i < sHdr.GetiStreams(); i++)
+ {
+ // Do we have enough buffer to read stream header?
+ if (cbStreamBuffer < sizeof(*pStream))
+ {
+ Debug_ReportError("Stream header is not within MetaData block.");
+ IfFailGo(CLDB_E_FILE_CORRUPT);
+ }
+ // Get next stream.
+ PSTORAGESTREAM pNext = pStream->NextStream_Verify();
+
+ // Check that stream header is within the buffer.
+ if (((LPBYTE)pStream >= ((LPBYTE)pData + cbData)) ||
+ ((LPBYTE)pNext > ((LPBYTE)pData + cbData)))
+ {
+ Debug_ReportError("Stream header is not within MetaData block.");
+ hr = CLDB_E_FILE_CORRUPT;
+ goto ErrExit;
+ }
+
+ // Check that the stream data starts and fits within the buffer.
+ // need two checks on size because of wraparound.
+ if ((pStream->GetOffset() > cbData) ||
+ (pStream->GetSize() > cbData) ||
+ ((pStream->GetSize() + pStream->GetOffset()) < pStream->GetOffset()) ||
+ ((pStream->GetSize() + pStream->GetOffset()) > cbData))
+ {
+ Debug_ReportError("Stream data are not within MetaData block.");
+ hr = CLDB_E_FILE_CORRUPT;
+ goto ErrExit;
+ }
+
+ // Pick off the location and size of the data.
+
+ if (strcmp(pStream->GetName(), COMPRESSED_MODEL_STREAM_A) == 0)
+ {
+ // Validate that only one of compressed/uncompressed is present.
+ if (*pFormat != MDFormat_Invalid)
+ { // Already found a good stream.
+ Debug_ReportError("Compressed model stream #~ is second important stream.");
+ hr = CLDB_E_FILE_CORRUPT;
+ goto ErrExit;
+ }
+ // Found the compressed meta data stream.
+ *pFormat = MDFormat_ReadOnly;
+ }
+ else if (strcmp(pStream->GetName(), ENC_MODEL_STREAM_A) == 0)
+ {
+#ifdef FEATURE_METADATA_STANDALONE_WINRT
+ Debug_ReportError("ENC model stream #- is not supported.");
+ hr = CLDB_E_FILE_CORRUPT;
+ goto ErrExit;
+#else //!FEATURE_METADATA_STANDALONE_WINRT
+ // Validate that only one of compressed/uncompressed is present.
+ if (*pFormat != MDFormat_Invalid)
+ { // Already found a good stream.
+ Debug_ReportError("ENC model stream #- is second important stream.");
+ hr = CLDB_E_FILE_CORRUPT;
+ goto ErrExit;
+ }
+ // Found the ENC meta data stream.
+ *pFormat = MDFormat_ReadWrite;
+#endif //!FEATURE_METADATA_STANDALONE_WINRT
+ }
+ else if (strcmp(pStream->GetName(), SCHEMA_STREAM_A) == 0)
+ {
+#ifdef FEATURE_METADATA_STANDALONE_WINRT
+ Debug_ReportError("Schema stream #Schema is not supported.");
+ hr = CLDB_E_FILE_CORRUPT;
+ goto ErrExit;
+#else //!FEATURE_METADATA_STANDALONE_WINRT
+ // Found the uncompressed format
+ *pFormat = MDFormat_ICR;
+
+ // keep going. We may find the compressed format later.
+ // If so, we want to use the compressed format.
+#endif //!FEATURE_METADATA_STANDALONE_WINRT
+ }
+
+ // Pick off the next stream if there is one.
+ pStream = pNext;
+ cbStreamBuffer = (ULONG)((LPBYTE)pData + cbData - (LPBYTE)pNext);
+ }
+
+ if (*pFormat == MDFormat_Invalid)
+ { // Didn't find a good stream.
+ Debug_ReportError("Cannot find MetaData stream.");
+ hr = CLDB_E_FILE_CORRUPT;
+ }
+
+ErrExit:
+ return hr;
+} // CheckFileFormat
+
+
+
+//*****************************************************************************
+// GetMDInternalInterface.
+// This function will check the metadata section and determine if it should
+// return an interface which implements ReadOnly or ReadWrite.
+//*****************************************************************************
+STDAPI GetMDInternalInterface(
+ LPVOID pData,
+ ULONG cbData,
+ DWORD flags, // [IN] ofRead or ofWrite.
+ REFIID riid, // [in] The interface desired.
+ void **ppIUnk) // [out] Return interface on success.
+{
+ HRESULT hr = NOERROR;
+ MDInternalRO *pInternalRO = NULL;
+ IMDCommon *pInternalROMDCommon = NULL;
+ MDFileFormat format;
+
+ BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(return COR_E_STACKOVERFLOW);
+
+ if (ppIUnk == NULL)
+ IfFailGo(E_INVALIDARG);
+
+ // Determine the file format we're trying to read.
+ IfFailGo( CheckFileFormat(pData, cbData, &format) );
+
+ // Found a fully-compressed, read-only format.
+ if ( format == MDFormat_ReadOnly )
+ {
+ pInternalRO = new (nothrow) MDInternalRO;
+ IfNullGo( pInternalRO );
+
+ IfFailGo( pInternalRO->Init(const_cast<void*>(pData), cbData) );
+
+#ifdef FEATURE_COMINTEROP
+ IfFailGo(pInternalRO->QueryInterface(IID_IMDCommon, (void**)&pInternalROMDCommon));
+ IfFailGo( (flags & ofNoTransform) ? S_FALSE : CheckIfWinMDAdapterNeeded(pInternalROMDCommon));
+ if (hr == S_OK)
+ {
+ IfFailGo(CreateWinMDInternalImportRO(pInternalROMDCommon, riid, (void**)ppIUnk));
+ }
+ else
+#endif // FEATURE_COMINTEROP
+ {
+ IfFailGo(pInternalRO->QueryInterface(riid, ppIUnk));
+ }
+
+ }
+ else
+ {
+ // Found a not-fully-compressed, ENC format.
+ _ASSERTE( format == MDFormat_ReadWrite );
+ IfFailGo( GetInternalWithRWFormat( pData, cbData, flags, riid, ppIUnk ) );
+ }
+
+ErrExit:
+
+ // clean up
+ if ( pInternalRO )
+ pInternalRO->Release();
+ if ( pInternalROMDCommon )
+ pInternalROMDCommon->Release();
+
+ END_SO_INTOLERANT_CODE;
+
+ return hr;
+} // GetMDInternalInterface
+
+
+#ifdef FEATURE_FUSION
+
+#ifndef DACCESS_COMPILE
+
+//*****************************************************************************
+// GetAssemblyMDInternalImport.
+// Instantiating an instance of AssemblyMDInternalImport.
+// This class can support the IMetaDataAssemblyImport and some functionalities
+// of IMetaDataImport on the internal import interface (IMDInternalImport).
+//*****************************************************************************
+STDAPI GetAssemblyMDInternalImport( // Return code.
+ LPCWSTR szFileName, // [in] The scope to open.
+ REFIID riid, // [in] The interface desired.
+ IUnknown **ppIUnk) // [out] Return interface on success.
+{
+ return GetAssemblyMDInternalImportEx(szFileName, riid, MDInternalImport_Default, ppIUnk);
+}
+
+STDAPI GetAssemblyMDInternalImportEx( // Return code.
+ LPCWSTR szFileName, // [in] The scope to open.
+ REFIID riid, // [in] The interface desired.
+ MDInternalImportFlags flags, // [in] Flags to control opening the assembly
+ IUnknown **ppIUnk, // [out] Return interface on success.
+ HANDLE hFile)
+{
+ HRESULT hr;
+
+ if (!szFileName || !szFileName[0] || !ppIUnk)
+ return E_INVALIDARG;
+
+ // Sanity check the name.
+ if (wcslen(szFileName) >= _MAX_PATH)
+ return E_INVALIDARG;
+
+ if (memcmp(szFileName, W("file:"), 10) == 0)
+ szFileName = &szFileName[5];
+
+ HCORMODULEHolder hModule;
+ DWORD dwFileLength;
+
+ BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(return COR_E_STACKOVERFLOW);
+
+ IfFailGoto(RuntimeOpenImageInternal(szFileName, &hModule, &dwFileLength, flags, hFile), ErrAsmExpected);
+
+ IfFailGo(GetAssemblyMDInternalImportHelper(hModule, riid, flags, ppIUnk));
+
+
+ErrAsmExpected:
+ if(hr == COR_E_BADIMAGEFORMAT)
+ hr = COR_E_ASSEMBLYEXPECTED;
+
+ErrExit:
+;
+ END_SO_INTOLERANT_CODE;
+
+ return hr;
+}
+
+HRESULT GetAssemblyMDInternalImportFromImage(
+ HCORMODULE hImage,
+ REFIID riid,
+ IUnknown **ppIUnk)
+{
+
+ HRESULT hr;
+
+ IfFailGo(GetAssemblyMDInternalImportHelper(hImage, riid, MDInternalImport_Default, ppIUnk));
+
+ErrExit:
+ return hr;
+}
+
+STDAPI GetAssemblyMDInternalImportByStream( // Return code.
+ IStream *pIStream, // [in] The IStream for the file
+ UINT64 AssemblyId, // [in] Unique Id for the assembly
+ REFIID riid, // [in] The interface desired.
+ IUnknown **ppIUnk) // [out] Return interface on success.
+{
+ return GetAssemblyMDInternalImportByStreamEx(pIStream, AssemblyId, riid, MDInternalImport_Default, ppIUnk);
+}
+
+STDAPI GetAssemblyMDInternalImportByStreamEx( // Return code.
+ IStream *pIStream, // [in] The IStream for the file
+ UINT64 AssemblyId, // [in] Unique Id for the assembly
+ REFIID riid, // [in] The interface desired.
+ MDInternalImportFlags flags, // [in[ Flags to control opening the assembly
+ IUnknown **ppIUnk) // [out] Return interface on success.
+{
+ if (!pIStream || !ppIUnk)
+ return E_INVALIDARG;
+
+ HRESULT hr;
+ DWORD dwFileLength;
+ HCORMODULEHolder hModule;
+
+ BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(return COR_E_STACKOVERFLOW);
+
+ IfFailGoto(RuntimeOpenImageByStream(pIStream, AssemblyId, 0, &hModule, &dwFileLength, flags), ErrAsmExpected);
+
+ IfFailGo(GetAssemblyMDInternalImportHelper(hModule, riid, flags, ppIUnk));
+
+
+ErrAsmExpected:
+ if(hr == COR_E_BADIMAGEFORMAT)
+ hr = COR_E_ASSEMBLYEXPECTED;
+
+ErrExit:
+ ;
+ END_SO_INTOLERANT_CODE;
+
+ return hr;
+}
+
+
+HRESULT GetAssemblyMDInternalImportHelper(HCORMODULE hModule,
+ REFIID riid,
+ MDInternalImportFlags flags,
+ IUnknown **ppIUnk)
+{
+ AssemblyMDInternalImport *pAssemblyMDInternalImport = NULL;
+ HRESULT hr;
+ LPVOID base;
+ PEDecoder pe;
+ IfFailGoto(RuntimeGetImageBase(hModule,&base,TRUE,NULL), ErrAsmExpected);
+
+ if (base!=NULL)
+ IfFailGoto(pe.Init(base), ErrAsmExpected);
+ else
+ {
+ COUNT_T lgth;
+ IfFailGoto(RuntimeGetImageBase(hModule,&base,FALSE,&lgth), ErrAsmExpected);
+ pe.Init(base, lgth);
+ }
+
+ // Both of these need to pass.
+ if (!pe.HasCorHeader() || !pe.CheckCorHeader())
+ IfFailGo(COR_E_ASSEMBLYEXPECTED);
+ // Only one of these needs to.
+ if (!pe.CheckILFormat() && !pe.CheckNativeFormat())
+ IfFailGo(COR_E_BADIMAGEFORMAT);
+
+ COUNT_T cbMetaData;
+ LPCVOID pMetaData;
+ pMetaData = pe.GetMetadata(&cbMetaData);
+
+ // Get the IL metadata.
+ IMDInternalImport *pMDInternalImport;
+ IfFailGo(RuntimeGetMDInternalImport(hModule, flags, &pMDInternalImport));
+ if (pMDInternalImport == NULL)
+ IfFailGo(E_OUTOFMEMORY);
+
+ _ASSERTE(pMDInternalImport);
+ pAssemblyMDInternalImport = new (nothrow) AssemblyMDInternalImport (pMDInternalImport);
+ if (!pAssemblyMDInternalImport) {
+ pMDInternalImport->Release();
+ IfFailGo(E_OUTOFMEMORY);
+ }
+
+ { // identify PE kind and machine type, plus the version string location
+ DWORD dwKind=0;
+ DWORD dwMachine=0;
+ RuntimeGetImageKind(hModule,&dwKind,&dwMachine);
+ pAssemblyMDInternalImport->SetPEKind(dwKind);
+ pAssemblyMDInternalImport->SetMachine(dwMachine);
+
+ {
+ LPCSTR pString = NULL;
+ IfFailGo(GetImageRuntimeVersionString((PVOID)pMetaData, &pString));
+
+ pAssemblyMDInternalImport->SetVersionString(pString);
+ }
+
+ }
+
+ pAssemblyMDInternalImport->SetHandle(hModule);
+
+#ifdef FEATURE_PREJIT
+ // Check for zap header for INativeImageInstallInfo
+ // Dont do this if we are returning the IL metadata as CORCOMPILE_DEPENDENCY
+ // references the native image metadata, not the IL metadata.
+
+ if (pe.HasNativeHeader() && !(flags & MDInternalImport_ILMetaData))
+ {
+ CORCOMPILE_VERSION_INFO *pNativeVersionInfo = pe.GetNativeVersionInfo();
+
+ COUNT_T cDeps;
+ CORCOMPILE_DEPENDENCY *pDeps = pe.GetNativeDependencies(&cDeps);
+
+ pAssemblyMDInternalImport->SetZapVersionInfo(pNativeVersionInfo, pDeps, cDeps);
+ }
+#endif // FEATURE_PREJIT
+
+ IfFailGo(pAssemblyMDInternalImport->QueryInterface(riid, (void**)ppIUnk));
+
+ return hr;
+
+ErrAsmExpected:
+ if(hr == COR_E_BADIMAGEFORMAT)
+ hr = COR_E_ASSEMBLYEXPECTED;
+
+ErrExit:
+
+ if (pAssemblyMDInternalImport)
+ delete pAssemblyMDInternalImport;
+
+ return hr;
+}
+
+AssemblyMDInternalImport::AssemblyMDInternalImport (IMDInternalImport *pMDInternalImport)
+: m_cRef(0),
+ m_pHandle(0),
+ m_pBase(NULL),
+#ifdef FEATURE_PREJIT
+ m_pZapVersionInfo(NULL),
+#endif // FEATURE_PREJIT
+ m_pMDInternalImport(pMDInternalImport),
+ m_dwPEKind(0),
+ m_dwMachine(0),
+ m_szVersionString("")
+{
+ _ASSERTE(m_pMDInternalImport);
+} // AssemblyMDInternalImport
+
+AssemblyMDInternalImport::~AssemblyMDInternalImport ()
+{
+ m_pMDInternalImport->Release();
+
+ if (m_pBase)
+ {
+ UnmapViewOfFile(m_pBase);
+ m_pBase = NULL;
+ CloseHandle(m_pHandle);
+ }
+ else if(m_pHandle)
+ {
+ HRESULT hr;
+ hr = RuntimeReleaseHandle(m_pHandle);
+ _ASSERTE(SUCCEEDED(hr));
+ }
+
+ m_pHandle = NULL;
+}
+
+ULONG AssemblyMDInternalImport::AddRef()
+{
+ return InterlockedIncrement(&m_cRef);
+} // ULONG AssemblyMDInternalImport::AddRef()
+
+ULONG AssemblyMDInternalImport::Release()
+{
+ ULONG cRef = InterlockedDecrement(&m_cRef);
+ if (!cRef)
+ {
+ VALIDATE_BACKOUT_STACK_CONSUMPTION;
+ delete this;
+ }
+ return (cRef);
+} // ULONG AssemblyMDInternalImport::Release()
+
+HRESULT AssemblyMDInternalImport::QueryInterface(REFIID riid, void **ppUnk)
+{
+ *ppUnk = 0;
+
+ if (riid == IID_IUnknown)
+ *ppUnk = (IUnknown *) (IMetaDataAssemblyImport *) this;
+ else if (riid == IID_IMetaDataAssemblyImport)
+ *ppUnk = (IMetaDataAssemblyImport *) this;
+ else if (riid == IID_IMetaDataImport)
+ *ppUnk = (IMetaDataImport *) this;
+ else if (riid == IID_IMetaDataImport2)
+ *ppUnk = (IMetaDataImport2 *) this;
+ else if (riid == IID_ISNAssemblySignature)
+ *ppUnk = (ISNAssemblySignature *) this;
+#ifdef FEATURE_PREJIT
+ else if (riid == IID_IGetIMDInternalImport)
+ *ppUnk = (IGetIMDInternalImport *) this;
+ else if (riid == IID_INativeImageInstallInfo && m_pZapVersionInfo)
+ *ppUnk = (INativeImageInstallInfo *) this;
+#endif // FEATURE_PREJIT
+ else
+ return (E_NOINTERFACE);
+ AddRef();
+ return (S_OK);
+}
+
+
+STDMETHODIMP AssemblyMDInternalImport::GetAssemblyProps ( // S_OK or error.
+ mdAssembly mda, // [IN] The Assembly for which to get the properties.
+ const void **ppbPublicKey, // [OUT] Pointer to the public key.
+ ULONG *pcbPublicKey, // [OUT] Count of bytes in the public key.
+ ULONG *pulHashAlgId, // [OUT] Hash Algorithm.
+ __out_ecount (cchName) LPWSTR szName, // [OUT] Buffer to fill with name.
+ ULONG cchName, // [IN] Size of buffer in wide chars.
+ ULONG *pchName, // [OUT] Actual # of wide chars in name.
+ ASSEMBLYMETADATA *pMetaData, // [OUT] Assembly MetaData.
+ DWORD *pdwAssemblyFlags) // [OUT] Flags.
+{
+ HRESULT hr;
+ LPCSTR _szName;
+ AssemblyMetaDataInternal _AssemblyMetaData;
+
+ _AssemblyMetaData.ulProcessor = 0;
+ _AssemblyMetaData.ulOS = 0;
+
+ IfFailRet(m_pMDInternalImport->GetAssemblyProps(
+ mda, // [IN] The Assembly for which to get the properties.
+ ppbPublicKey, // [OUT] Pointer to the public key.
+ pcbPublicKey, // [OUT] Count of bytes in the public key.
+ pulHashAlgId, // [OUT] Hash Algorithm.
+ &_szName, // [OUT] Buffer to fill with name.
+ &_AssemblyMetaData, // [OUT] Assembly MetaData.
+ pdwAssemblyFlags)); // [OUT] Flags.
+
+ if (pchName != NULL)
+ {
+ *pchName = WszMultiByteToWideChar(CP_UTF8, 0, _szName, -1, szName, cchName);
+ if (*pchName == 0)
+ {
+ return HRESULT_FROM_GetLastError();
+ }
+ }
+
+ if (pMetaData)
+ {
+ pMetaData->usMajorVersion = _AssemblyMetaData.usMajorVersion;
+ pMetaData->usMinorVersion = _AssemblyMetaData.usMinorVersion;
+ pMetaData->usBuildNumber = _AssemblyMetaData.usBuildNumber;
+ pMetaData->usRevisionNumber = _AssemblyMetaData.usRevisionNumber;
+ pMetaData->ulProcessor = 0;
+ pMetaData->ulOS = 0;
+
+ pMetaData->cbLocale = WszMultiByteToWideChar(CP_UTF8, 0, _AssemblyMetaData.szLocale, -1, pMetaData->szLocale, pMetaData->cbLocale);
+ if (pMetaData->cbLocale == 0)
+ {
+ return HRESULT_FROM_GetLastError();
+ }
+ }
+
+ return S_OK;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::GetAssemblyRefProps ( // S_OK or error.
+ mdAssemblyRef mdar, // [IN] The AssemblyRef for which to get the properties.
+ const void **ppbPublicKeyOrToken, // [OUT] Pointer to the public key or token.
+ ULONG *pcbPublicKeyOrToken, // [OUT] Count of bytes in the public key or token.
+ __out_ecount (cchName) LPWSTR szName, // [OUT] Buffer to fill with name.
+ ULONG cchName, // [IN] Size of buffer in wide chars.
+ ULONG *pchName, // [OUT] Actual # of wide chars in name.
+ ASSEMBLYMETADATA *pMetaData, // [OUT] Assembly MetaData.
+ const void **ppbHashValue, // [OUT] Hash blob.
+ ULONG *pcbHashValue, // [OUT] Count of bytes in the hash blob.
+ DWORD *pdwAssemblyRefFlags) // [OUT] Flags.
+{
+ HRESULT hr;
+ LPCSTR _szName;
+ AssemblyMetaDataInternal _AssemblyMetaData;
+
+ _AssemblyMetaData.ulProcessor = 0;
+ _AssemblyMetaData.ulOS = 0;
+
+ IfFailRet(m_pMDInternalImport->GetAssemblyRefProps(
+ mdar, // [IN] The Assembly for which to get the properties.
+ ppbPublicKeyOrToken, // [OUT] Pointer to the public key or token.
+ pcbPublicKeyOrToken, // [OUT] Count of bytes in the public key or token.
+ &_szName, // [OUT] Buffer to fill with name.
+ &_AssemblyMetaData, // [OUT] Assembly MetaData.
+ ppbHashValue, // [OUT] Hash blob.
+ pcbHashValue, // [OUT] Count of bytes in the hash blob.
+ pdwAssemblyRefFlags)); // [OUT] Flags.
+
+ if (pchName != NULL)
+ {
+ *pchName = WszMultiByteToWideChar(CP_UTF8, 0, _szName, -1, szName, cchName);
+ if (*pchName == 0)
+ {
+ return HRESULT_FROM_GetLastError();
+ }
+ }
+
+ pMetaData->usMajorVersion = _AssemblyMetaData.usMajorVersion;
+ pMetaData->usMinorVersion = _AssemblyMetaData.usMinorVersion;
+ pMetaData->usBuildNumber = _AssemblyMetaData.usBuildNumber;
+ pMetaData->usRevisionNumber = _AssemblyMetaData.usRevisionNumber;
+ pMetaData->ulProcessor = 0;
+ pMetaData->ulOS = 0;
+
+ pMetaData->cbLocale = WszMultiByteToWideChar(CP_UTF8, 0, _AssemblyMetaData.szLocale, -1, pMetaData->szLocale, pMetaData->cbLocale);
+ if (pMetaData->cbLocale == 0)
+ {
+ return HRESULT_FROM_GetLastError();
+ }
+
+ return S_OK;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::GetFileProps ( // S_OK or error.
+ mdFile mdf, // [IN] The File for which to get the properties.
+ __out_ecount (cchName) LPWSTR szName, // [OUT] Buffer to fill with name.
+ ULONG cchName, // [IN] Size of buffer in wide chars.
+ ULONG *pchName, // [OUT] Actual # of wide chars in name.
+ const void **ppbHashValue, // [OUT] Pointer to the Hash Value Blob.
+ ULONG *pcbHashValue, // [OUT] Count of bytes in the Hash Value Blob.
+ DWORD *pdwFileFlags) // [OUT] Flags.
+{
+ HRESULT hr;
+ LPCSTR _szName;
+ IfFailRet(m_pMDInternalImport->GetFileProps(
+ mdf,
+ &_szName,
+ ppbHashValue,
+ pcbHashValue,
+ pdwFileFlags));
+
+ if (pchName != NULL)
+ {
+ *pchName = WszMultiByteToWideChar(CP_UTF8, 0, _szName, -1, szName, cchName);
+ if (*pchName == 0)
+ {
+ return HRESULT_FROM_GetLastError();
+ }
+ }
+
+ return S_OK;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::GetExportedTypeProps ( // S_OK or error.
+ mdExportedType mdct, // [IN] The ExportedType for which to get the properties.
+ __out_ecount (cchName) LPWSTR szName, // [OUT] Buffer to fill with name.
+ ULONG cchName, // [IN] Size of buffer in wide chars.
+ ULONG *pchName, // [OUT] Actual # of wide chars in name.
+ mdToken *ptkImplementation, // [OUT] mdFile or mdAssemblyRef or mdExportedType.
+ mdTypeDef *ptkTypeDef, // [OUT] TypeDef token within the file.
+ DWORD *pdwExportedTypeFlags) // [OUT] Flags.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::GetManifestResourceProps ( // S_OK or error.
+ mdManifestResource mdmr, // [IN] The ManifestResource for which to get the properties.
+ __out_ecount (cchName) LPWSTR szName, // [OUT] Buffer to fill with name.
+ ULONG cchName, // [IN] Size of buffer in wide chars.
+ ULONG *pchName, // [OUT] Actual # of wide chars in name.
+ mdToken *ptkImplementation, // [OUT] mdFile or mdAssemblyRef that provides the ManifestResource.
+ DWORD *pdwOffset, // [OUT] Offset to the beginning of the resource within the file.
+ DWORD *pdwResourceFlags) // [OUT] Flags.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::EnumAssemblyRefs ( // S_OK or error
+ HCORENUM *phEnum, // [IN|OUT] Pointer to the enum.
+ mdAssemblyRef rAssemblyRefs[], // [OUT] Put AssemblyRefs here.
+ ULONG cMax, // [IN] Max AssemblyRefs to put.
+ ULONG *pcTokens) // [OUT] Put # put here.
+{
+ HENUMInternal **ppmdEnum = reinterpret_cast<HENUMInternal **> (phEnum);
+ HRESULT hr = NOERROR;
+ HENUMInternal *pEnum;
+
+ if (*ppmdEnum == NULL)
+ {
+ // create the enumerator.
+ IfFailGo(HENUMInternal::CreateSimpleEnum(
+ mdtAssemblyRef,
+ 0,
+ 1,
+ &pEnum));
+
+ IfFailGo(m_pMDInternalImport->EnumInit(mdtAssemblyRef, 0, pEnum));
+
+ // set the output parameter.
+ *ppmdEnum = pEnum;
+ }
+ else
+ {
+ pEnum = *ppmdEnum;
+ }
+
+ // we can only fill the minimum of what the caller asked for or what we have left.
+ IfFailGo(HENUMInternal::EnumWithCount(pEnum, cMax, rAssemblyRefs, pcTokens));
+ErrExit:
+ HENUMInternal::DestroyEnumIfEmpty(ppmdEnum);
+
+ return hr;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::EnumFiles ( // S_OK or error
+ HCORENUM *phEnum, // [IN|OUT] Pointer to the enum.
+ mdFile rFiles[], // [OUT] Put Files here.
+ ULONG cMax, // [IN] Max Files to put.
+ ULONG *pcTokens) // [OUT] Put # put here.
+{
+ HENUMInternal **ppmdEnum = reinterpret_cast<HENUMInternal **> (phEnum);
+ HRESULT hr = NOERROR;
+ HENUMInternal *pEnum;
+
+ if (*ppmdEnum == NULL)
+ {
+ // create the enumerator.
+ IfFailGo(HENUMInternal::CreateSimpleEnum(
+ mdtFile,
+ 0,
+ 1,
+ &pEnum));
+
+ IfFailGo(m_pMDInternalImport->EnumInit(mdtFile, 0, pEnum));
+
+ // set the output parameter.
+ *ppmdEnum = pEnum;
+ }
+ else
+ {
+ pEnum = *ppmdEnum;
+ }
+
+ // we can only fill the minimum of what the caller asked for or what we have left.
+ IfFailGo(HENUMInternal::EnumWithCount(pEnum, cMax, rFiles, pcTokens));
+
+ErrExit:
+ HENUMInternal::DestroyEnumIfEmpty(ppmdEnum);
+ return hr;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::EnumExportedTypes ( // S_OK or error
+ HCORENUM *phEnum, // [IN|OUT] Pointer to the enum.
+ mdExportedType rExportedTypes[], // [OUT] Put ExportedTypes here.
+ ULONG cMax, // [IN] Max ExportedTypes to put.
+ ULONG *pcTokens) // [OUT] Put # put here.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::EnumManifestResources ( // S_OK or error
+ HCORENUM *phEnum, // [IN|OUT] Pointer to the enum.
+ mdManifestResource rManifestResources[], // [OUT] Put ManifestResources here.
+ ULONG cMax, // [IN] Max Resources to put.
+ ULONG *pcTokens) // [OUT] Put # put here.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::GetAssemblyFromScope ( // S_OK or error
+ mdAssembly *ptkAssembly) // [OUT] Put token here.
+{
+ return m_pMDInternalImport->GetAssemblyFromScope (ptkAssembly);
+}
+
+STDMETHODIMP AssemblyMDInternalImport::FindExportedTypeByName (// S_OK or error
+ LPCWSTR szName, // [IN] Name of the ExportedType.
+ mdToken mdtExportedType, // [IN] ExportedType for the enclosing class.
+ mdExportedType *ptkExportedType) // [OUT] Put the ExportedType token here.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::FindManifestResourceByName ( // S_OK or error
+ LPCWSTR szName, // [IN] Name of the ManifestResource.
+ mdManifestResource *ptkManifestResource) // [OUT] Put the ManifestResource token here.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+void AssemblyMDInternalImport::CloseEnum (
+ HCORENUM hEnum) // Enum to be closed.
+{
+ HENUMInternal *pmdEnum = reinterpret_cast<HENUMInternal *> (hEnum);
+
+ if (pmdEnum == NULL)
+ return;
+
+ HENUMInternal::DestroyEnum(pmdEnum);
+}
+
+STDMETHODIMP AssemblyMDInternalImport::FindAssembliesByName ( // S_OK or error
+ LPCWSTR szAppBase, // [IN] optional - can be NULL
+ LPCWSTR szPrivateBin, // [IN] optional - can be NULL
+ LPCWSTR szAssemblyName, // [IN] required - this is the assembly you are requesting
+ IUnknown *ppIUnk[], // [OUT] put IMetaDataAssemblyImport pointers here
+ ULONG cMax, // [IN] The max number to put
+ ULONG *pcAssemblies) // [OUT] The number of assemblies returned.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::CountEnum (HCORENUM hEnum, ULONG *pulCount)
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::ResetEnum (HCORENUM hEnum, ULONG ulPos)
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::EnumTypeDefs (HCORENUM *phEnum, mdTypeDef rTypeDefs[],
+ ULONG cMax, ULONG *pcTypeDefs)
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::EnumInterfaceImpls (HCORENUM *phEnum, mdTypeDef td,
+ mdInterfaceImpl rImpls[], ULONG cMax,
+ ULONG* pcImpls)
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::EnumTypeRefs (HCORENUM *phEnum, mdTypeRef rTypeRefs[],
+ ULONG cMax, ULONG* pcTypeRefs)
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::FindTypeDefByName ( // S_OK or error.
+ LPCWSTR szTypeDef, // [IN] Name of the Type.
+ mdToken tkEnclosingClass, // [IN] TypeDef/TypeRef for Enclosing class.
+ mdTypeDef *ptd) // [OUT] Put the TypeDef token here.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::GetScopeProps ( // S_OK or error.
+ __out_ecount (cchName) LPWSTR szName, // [OUT] Put the name here.
+ ULONG cchName, // [IN] Size of name buffer in wide chars.
+ ULONG *pchName, // [OUT] Put size of name (wide chars) here.
+ GUID *pmvid) // [OUT, OPTIONAL] Put MVID here.
+{
+ HRESULT hr;
+ LPCSTR _szName;
+
+ if (!m_pMDInternalImport->IsValidToken(m_pMDInternalImport->GetModuleFromScope()))
+ return COR_E_BADIMAGEFORMAT;
+
+ IfFailRet(m_pMDInternalImport->GetScopeProps(&_szName, pmvid));
+
+ if (pchName != NULL)
+ {
+ *pchName = WszMultiByteToWideChar(CP_UTF8, 0, _szName, -1, szName, cchName);
+ if (*pchName == 0)
+ {
+ return HRESULT_FROM_GetLastError();
+ }
+ }
+
+ return S_OK;
+
+}
+
+STDMETHODIMP AssemblyMDInternalImport::GetModuleFromScope ( // S_OK.
+ mdModule *pmd) // [OUT] Put mdModule token here.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::GetTypeDefProps ( // S_OK or error.
+ mdTypeDef td, // [IN] TypeDef token for inquiry.
+ __out_ecount (cchTypeDef) LPWSTR szTypeDef, // [OUT] Put name here.
+ ULONG cchTypeDef, // [IN] size of name buffer in wide chars.
+ ULONG *pchTypeDef, // [OUT] put size of name (wide chars) here.
+ DWORD *pdwTypeDefFlags, // [OUT] Put flags here.
+ mdToken *ptkExtends) // [OUT] Put base class TypeDef/TypeRef here.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::GetInterfaceImplProps ( // S_OK or error.
+ mdInterfaceImpl iiImpl, // [IN] InterfaceImpl token.
+ mdTypeDef *pClass, // [OUT] Put implementing class token here.
+ mdToken *ptkIface) // [OUT] Put implemented interface token here.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::GetTypeRefProps ( // S_OK or error.
+ mdTypeRef tr, // [IN] TypeRef token.
+ mdToken *ptkResolutionScope, // [OUT] Resolution scope, ModuleRef or AssemblyRef.
+ __out_ecount (cchName) LPWSTR szName, // [OUT] Name of the TypeRef.
+ ULONG cchName, // [IN] Size of buffer.
+ ULONG *pchName) // [OUT] Size of Name.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::ResolveTypeRef (mdTypeRef tr, REFIID riid, IUnknown **ppIScope, mdTypeDef *ptd)
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::EnumMembers ( // S_OK, S_FALSE, or error.
+ HCORENUM *phEnum, // [IN|OUT] Pointer to the enum.
+ mdTypeDef cl, // [IN] TypeDef to scope the enumeration.
+ mdToken rMembers[], // [OUT] Put MemberDefs here.
+ ULONG cMax, // [IN] Max MemberDefs to put.
+ ULONG *pcTokens) // [OUT] Put # put here.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::EnumMembersWithName ( // S_OK, S_FALSE, or error.
+ HCORENUM *phEnum, // [IN|OUT] Pointer to the enum.
+ mdTypeDef cl, // [IN] TypeDef to scope the enumeration.
+ LPCWSTR szName, // [IN] Limit results to those with this name.
+ mdToken rMembers[], // [OUT] Put MemberDefs here.
+ ULONG cMax, // [IN] Max MemberDefs to put.
+ ULONG *pcTokens) // [OUT] Put # put here.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::EnumMethods ( // S_OK, S_FALSE, or error.
+ HCORENUM *phEnum, // [IN|OUT] Pointer to the enum.
+ mdTypeDef cl, // [IN] TypeDef to scope the enumeration.
+ mdMethodDef rMethods[], // [OUT] Put MethodDefs here.
+ ULONG cMax, // [IN] Max MethodDefs to put.
+ ULONG *pcTokens) // [OUT] Put # put here.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::EnumMethodsWithName ( // S_OK, S_FALSE, or error.
+ HCORENUM *phEnum, // [IN|OUT] Pointer to the enum.
+ mdTypeDef cl, // [IN] TypeDef to scope the enumeration.
+ LPCWSTR szName, // [IN] Limit results to those with this name.
+ mdMethodDef rMethods[], // [OU] Put MethodDefs here.
+ ULONG cMax, // [IN] Max MethodDefs to put.
+ ULONG *pcTokens) // [OUT] Put # put here.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::EnumFields ( // S_OK, S_FALSE, or error.
+ HCORENUM *phEnum, // [IN|OUT] Pointer to the enum.
+ mdTypeDef cl, // [IN] TypeDef to scope the enumeration.
+ mdFieldDef rFields[], // [OUT] Put FieldDefs here.
+ ULONG cMax, // [IN] Max FieldDefs to put.
+ ULONG *pcTokens) // [OUT] Put # put here.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::EnumFieldsWithName ( // S_OK, S_FALSE, or error.
+ HCORENUM *phEnum, // [IN|OUT] Pointer to the enum.
+ mdTypeDef cl, // [IN] TypeDef to scope the enumeration.
+ LPCWSTR szName, // [IN] Limit results to those with this name.
+ mdFieldDef rFields[], // [OUT] Put MemberDefs here.
+ ULONG cMax, // [IN] Max MemberDefs to put.
+ ULONG *pcTokens) // [OUT] Put # put here.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+
+STDMETHODIMP AssemblyMDInternalImport::EnumParams ( // S_OK, S_FALSE, or error.
+ HCORENUM *phEnum, // [IN|OUT] Pointer to the enum.
+ mdMethodDef mb, // [IN] MethodDef to scope the enumeration.
+ mdParamDef rParams[], // [OUT] Put ParamDefs here.
+ ULONG cMax, // [IN] Max ParamDefs to put.
+ ULONG *pcTokens) // [OUT] Put # put here.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::EnumMemberRefs ( // S_OK, S_FALSE, or error.
+ HCORENUM *phEnum, // [IN|OUT] Pointer to the enum.
+ mdToken tkParent, // [IN] Parent token to scope the enumeration.
+ mdMemberRef rMemberRefs[], // [OUT] Put MemberRefs here.
+ ULONG cMax, // [IN] Max MemberRefs to put.
+ ULONG *pcTokens) // [OUT] Put # put here.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::EnumMethodImpls ( // S_OK, S_FALSE, or error
+ HCORENUM *phEnum, // [IN|OUT] Pointer to the enum.
+ mdTypeDef td, // [IN] TypeDef to scope the enumeration.
+ mdToken rMethodBody[], // [OUT] Put Method Body tokens here.
+ mdToken rMethodDecl[], // [OUT] Put Method Declaration tokens here.
+ ULONG cMax, // [IN] Max tokens to put.
+ ULONG *pcTokens) // [OUT] Put # put here.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::EnumPermissionSets ( // S_OK, S_FALSE, or error.
+ HCORENUM *phEnum, // [IN|OUT] Pointer to the enum.
+ mdToken tk, // [IN] if !NIL, token to scope the enumeration.
+ DWORD dwActions, // [IN] if !0, return only these actions.
+ mdPermission rPermission[], // [OUT] Put Permissions here.
+ ULONG cMax, // [IN] Max Permissions to put.
+ ULONG *pcTokens) // [OUT] Put # put here.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::FindMember (
+ mdTypeDef td, // [IN] given typedef
+ LPCWSTR szName, // [IN] member name
+ PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of COM+ signature
+ ULONG cbSigBlob, // [IN] count of bytes in the signature blob
+ mdToken *pmb) // [OUT] matching memberdef
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::FindMethod (
+ mdTypeDef td, // [IN] given typedef
+ LPCWSTR szName, // [IN] member name
+ PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of COM+ signature
+ ULONG cbSigBlob, // [IN] count of bytes in the signature blob
+ mdMethodDef *pmb) // [OUT] matching memberdef
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::FindField (
+ mdTypeDef td, // [IN] given typedef
+ LPCWSTR szName, // [IN] member name
+ PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of COM+ signature
+ ULONG cbSigBlob, // [IN] count of bytes in the signature blob
+ mdFieldDef *pmb) // [OUT] matching memberdef
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::FindMemberRef (
+ mdTypeRef td, // [IN] given typeRef
+ LPCWSTR szName, // [IN] member name
+ PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of COM+ signature
+ ULONG cbSigBlob, // [IN] count of bytes in the signature blob
+ mdMemberRef *pmr) // [OUT] matching memberref
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::GetMethodProps (
+ mdMethodDef mb, // The method for which to get props.
+ mdTypeDef *pClass, // Put method's class here.
+ __out_ecount (cchMethod) LPWSTR szMethod, // Put method's name here.
+ ULONG cchMethod, // Size of szMethod buffer in wide chars.
+ ULONG *pchMethod, // Put actual size here
+ DWORD *pdwAttr, // Put flags here.
+ PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to the blob value of meta data
+ ULONG *pcbSigBlob, // [OUT] actual size of signature blob
+ ULONG *pulCodeRVA, // [OUT] codeRVA
+ DWORD *pdwImplFlags) // [OUT] Impl. Flags
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::GetMemberRefProps ( // S_OK or error.
+ mdMemberRef mr, // [IN] given memberref
+ mdToken *ptk, // [OUT] Put classref or classdef here.
+ __out_ecount (cchMember) LPWSTR szMember, // [OUT] buffer to fill for member's name
+ ULONG cchMember, // [IN] the count of char of szMember
+ ULONG *pchMember, // [OUT] actual count of char in member name
+ PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to meta data blob value
+ ULONG *pbSig) // [OUT] actual size of signature blob
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::EnumProperties ( // S_OK, S_FALSE, or error.
+ HCORENUM *phEnum, // [IN|OUT] Pointer to the enum.
+ mdTypeDef td, // [IN] TypeDef to scope the enumeration.
+ mdProperty rProperties[], // [OUT] Put Properties here.
+ ULONG cMax, // [IN] Max properties to put.
+ ULONG *pcProperties) // [OUT] Put # put here.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::EnumEvents ( // S_OK, S_FALSE, or error.
+ HCORENUM *phEnum, // [IN|OUT] Pointer to the enum.
+ mdTypeDef td, // [IN] TypeDef to scope the enumeration.
+ mdEvent rEvents[], // [OUT] Put events here.
+ ULONG cMax, // [IN] Max events to put.
+ ULONG *pcEvents) // [OUT] Put # put here.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::GetEventProps ( // S_OK, S_FALSE, or error.
+ mdEvent ev, // [IN] event token
+ mdTypeDef *pClass, // [OUT] typedef containing the event declarion.
+ LPCWSTR szEvent, // [OUT] Event name
+ ULONG cchEvent, // [IN] the count of wchar of szEvent
+ ULONG *pchEvent, // [OUT] actual count of wchar for event's name
+ DWORD *pdwEventFlags, // [OUT] Event flags.
+ mdToken *ptkEventType, // [OUT] EventType class
+ mdMethodDef *pmdAddOn, // [OUT] AddOn method of the event
+ mdMethodDef *pmdRemoveOn, // [OUT] RemoveOn method of the event
+ mdMethodDef *pmdFire, // [OUT] Fire method of the event
+ mdMethodDef rmdOtherMethod[], // [OUT] other method of the event
+ ULONG cMax, // [IN] size of rmdOtherMethod
+ ULONG *pcOtherMethod) // [OUT] total number of other method of this event
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::EnumMethodSemantics ( // S_OK, S_FALSE, or error.
+ HCORENUM *phEnum, // [IN|OUT] Pointer to the enum.
+ mdMethodDef mb, // [IN] MethodDef to scope the enumeration.
+ mdToken rEventProp[], // [OUT] Put Event/Property here.
+ ULONG cMax, // [IN] Max properties to put.
+ ULONG *pcEventProp) // [OUT] Put # put here.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::GetMethodSemantics ( // S_OK, S_FALSE, or error.
+ mdMethodDef mb, // [IN] method token
+ mdToken tkEventProp, // [IN] event/property token.
+ DWORD *pdwSemanticsFlags) // [OUT] the role flags for the method/propevent pair
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::GetClassLayout (
+ mdTypeDef td, // [IN] give typedef
+ DWORD *pdwPackSize, // [OUT] 1, 2, 4, 8, or 16
+ COR_FIELD_OFFSET rFieldOffset[], // [OUT] field offset array
+ ULONG cMax, // [IN] size of the array
+ ULONG *pcFieldOffset, // [OUT] needed array size
+ ULONG *pulClassSize) // [OUT] the size of the class
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::GetFieldMarshal (
+ mdToken tk, // [IN] given a field's memberdef
+ PCCOR_SIGNATURE *ppvNativeType, // [OUT] native type of this field
+ ULONG *pcbNativeType) // [OUT] the count of bytes of *ppvNativeType
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::GetRVA ( // S_OK or error.
+ mdToken tk, // Member for which to set offset
+ ULONG *pulCodeRVA, // The offset
+ DWORD *pdwImplFlags) // the implementation flags
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::GetPermissionSetProps (
+ mdPermission pm, // [IN] the permission token.
+ DWORD *pdwAction, // [OUT] CorDeclSecurity.
+ void const **ppvPermission, // [OUT] permission blob.
+ ULONG *pcbPermission) // [OUT] count of bytes of pvPermission.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::GetSigFromToken ( // S_OK or error.
+ mdSignature mdSig, // [IN] Signature token.
+ PCCOR_SIGNATURE *ppvSig, // [OUT] return pointer to token.
+ ULONG *pcbSig) // [OUT] return size of signature.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::GetModuleRefProps ( // S_OK or error.
+ mdModuleRef mur, // [IN] moduleref token.
+ __out_ecount (cchName) LPWSTR szName, // [OUT] buffer to fill with the moduleref name.
+ ULONG cchName, // [IN] size of szName in wide characters.
+ ULONG *pchName) // [OUT] actual count of characters in the name.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::EnumModuleRefs ( // S_OK or error.
+ HCORENUM *phEnum, // [IN|OUT] pointer to the enum.
+ mdModuleRef rModuleRefs[], // [OUT] put modulerefs here.
+ ULONG cmax, // [IN] max memberrefs to put.
+ ULONG *pcModuleRefs) // [OUT] put # put here.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::GetTypeSpecFromToken ( // S_OK or error.
+ mdTypeSpec typespec, // [IN] TypeSpec token.
+ PCCOR_SIGNATURE *ppvSig, // [OUT] return pointer to TypeSpec signature
+ ULONG *pcbSig) // [OUT] return size of signature.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::GetNameFromToken ( // Not Recommended! May be removed!
+ mdToken tk, // [IN] Token to get name from. Must have a name.
+ MDUTF8CSTR *pszUtf8NamePtr) // [OUT] Return pointer to UTF8 name in heap.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::EnumUnresolvedMethods ( // S_OK, S_FALSE, or error.
+ HCORENUM *phEnum, // [IN|OUT] Pointer to the enum.
+ mdToken rMethods[], // [OUT] Put MemberDefs here.
+ ULONG cMax, // [IN] Max MemberDefs to put.
+ ULONG *pcTokens) // [OUT] Put # put here.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::GetUserString ( // S_OK or error.
+ mdString stk, // [IN] String token.
+ __out_ecount (cchString) LPWSTR szString, // [OUT] Copy of string.
+ ULONG cchString, // [IN] Max chars of room in szString.
+ ULONG *pchString) // [OUT] How many chars in actual string.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::GetPinvokeMap ( // S_OK or error.
+ mdToken tk, // [IN] FieldDef or MethodDef.
+ DWORD *pdwMappingFlags, // [OUT] Flags used for mapping.
+ __out_ecount (cchImportName) LPWSTR szImportName, // [OUT] Import name.
+ ULONG cchImportName, // [IN] Size of the name buffer.
+ ULONG *pchImportName, // [OUT] Actual number of characters stored.
+ mdModuleRef *pmrImportDLL) // [OUT] ModuleRef token for the target DLL.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::EnumSignatures ( // S_OK or error.
+ HCORENUM *phEnum, // [IN|OUT] pointer to the enum.
+ mdSignature rSignatures[], // [OUT] put signatures here.
+ ULONG cmax, // [IN] max signatures to put.
+ ULONG *pcSignatures) // [OUT] put # put here.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::EnumTypeSpecs ( // S_OK or error.
+ HCORENUM *phEnum, // [IN|OUT] pointer to the enum.
+ mdTypeSpec rTypeSpecs[], // [OUT] put TypeSpecs here.
+ ULONG cmax, // [IN] max TypeSpecs to put.
+ ULONG *pcTypeSpecs) // [OUT] put # put here.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::EnumUserStrings ( // S_OK or error.
+ HCORENUM *phEnum, // [IN/OUT] pointer to the enum.
+ mdString rStrings[], // [OUT] put Strings here.
+ ULONG cmax, // [IN] max Strings to put.
+ ULONG *pcStrings) // [OUT] put # put here.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::GetParamForMethodIndex ( // S_OK or error.
+ mdMethodDef md, // [IN] Method token.
+ ULONG ulParamSeq, // [IN] Parameter sequence.
+ mdParamDef *ppd) // [IN] Put Param token here.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::EnumCustomAttributes ( // S_OK or error.
+ HCORENUM *phEnum, // [IN, OUT] COR enumerator.
+ mdToken tk, // [IN] Token to scope the enumeration, 0 for all.
+ mdToken tkType, // [IN] Type of interest, 0 for all.
+ mdCustomAttribute rCustomAttributes[], // [OUT] Put custom attribute tokens here.
+ ULONG cMax, // [IN] Size of rCustomAttributes.
+ ULONG *pcCustomAttributes) // [OUT, OPTIONAL] Put count of token values here.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::GetCustomAttributeProps ( // S_OK or error.
+ mdCustomAttribute cv, // [IN] CustomAttribute token.
+ mdToken *ptkObj, // [OUT, OPTIONAL] Put object token here.
+ mdToken *ptkType, // [OUT, OPTIONAL] Put AttrType token here.
+ void const **ppBlob, // [OUT, OPTIONAL] Put pointer to data here.
+ ULONG *pcbSize) // [OUT, OPTIONAL] Put size of date here.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::FindTypeRef (
+ mdToken tkResolutionScope, // [IN] ModuleRef, AssemblyRef or TypeRef.
+ LPCWSTR szName, // [IN] TypeRef Name.
+ mdTypeRef *ptr) // [OUT] matching TypeRef.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::GetMemberProps (
+ mdToken mb, // The member for which to get props.
+ mdTypeDef *pClass, // Put member's class here.
+ __out_ecount (cchMember) LPWSTR szMember, // Put member's name here.
+ ULONG cchMember, // Size of szMember buffer in wide chars.
+ ULONG *pchMember, // Put actual size here
+ DWORD *pdwAttr, // Put flags here.
+ PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to the blob value of meta data
+ ULONG *pcbSigBlob, // [OUT] actual size of signature blob
+ ULONG *pulCodeRVA, // [OUT] codeRVA
+ DWORD *pdwImplFlags, // [OUT] Impl. Flags
+ DWORD *pdwCPlusTypeFlag, // [OUT] flag for value type. selected ELEMENT_TYPE_*
+ UVCP_CONSTANT *ppValue, // [OUT] constant value
+ ULONG *pcchValue) // [OUT] size of constant string in chars, 0 for non-strings.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::GetFieldProps (
+ mdFieldDef mb, // The field for which to get props.
+ mdTypeDef *pClass, // Put field's class here.
+ __out_ecount (cchField) LPWSTR szField, // Put field's name here.
+ ULONG cchField, // Size of szField buffer in wide chars.
+ ULONG *pchField, // Put actual size here
+ DWORD *pdwAttr, // Put flags here.
+ PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to the blob value of meta data
+ ULONG *pcbSigBlob, // [OUT] actual size of signature blob
+ DWORD *pdwCPlusTypeFlag, // [OUT] flag for value type. selected ELEMENT_TYPE_*
+ UVCP_CONSTANT *ppValue, // [OUT] constant value
+ ULONG *pcchValue) // [OUT] size of constant string in chars, 0 for non-strings.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::GetPropertyProps ( // S_OK, S_FALSE, or error.
+ mdProperty prop, // [IN] property token
+ mdTypeDef *pClass, // [OUT] typedef containing the property declarion.
+ LPCWSTR szProperty, // [OUT] Property name
+ ULONG cchProperty, // [IN] the count of wchar of szProperty
+ ULONG *pchProperty, // [OUT] actual count of wchar for property name
+ DWORD *pdwPropFlags, // [OUT] property flags.
+ PCCOR_SIGNATURE *ppvSig, // [OUT] property type. pointing to meta data internal blob
+ ULONG *pbSig, // [OUT] count of bytes in *ppvSig
+ DWORD *pdwCPlusTypeFlag, // [OUT] flag for value type. selected ELEMENT_TYPE_*
+ UVCP_CONSTANT *ppDefaultValue, // [OUT] constant value
+ ULONG *pcchDefaultValue, // [OUT] size of constant string in chars, 0 for non-strings.
+ mdMethodDef *pmdSetter, // [OUT] setter method of the property
+ mdMethodDef *pmdGetter, // [OUT] getter method of the property
+ mdMethodDef rmdOtherMethod[], // [OUT] other method of the property
+ ULONG cMax, // [IN] size of rmdOtherMethod
+ ULONG *pcOtherMethod) // [OUT] total number of other method of this property
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::GetParamProps ( // S_OK or error.
+ mdParamDef tk, // [IN]The Parameter.
+ mdMethodDef *pmd, // [OUT] Parent Method token.
+ ULONG *pulSequence, // [OUT] Parameter sequence.
+ __out_ecount (cchName) LPWSTR szName, // [OUT] Put name here.
+ ULONG cchName, // [OUT] Size of name buffer.
+ ULONG *pchName, // [OUT] Put actual size of name here.
+ DWORD *pdwAttr, // [OUT] Put flags here.
+ DWORD *pdwCPlusTypeFlag, // [OUT] Flag for value type. selected ELEMENT_TYPE_*.
+ UVCP_CONSTANT *ppValue, // [OUT] Constant value.
+ ULONG *pcchValue) // [OUT] size of constant string in chars, 0 for non-strings.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::GetCustomAttributeByName ( // S_OK or error.
+ mdToken tkObj, // [IN] Object with Custom Attribute.
+ LPCWSTR szName, // [IN] Name of desired Custom Attribute.
+ const void **ppData, // [OUT] Put pointer to data here.
+ ULONG *pcbData) // [OUT] Put size of data here.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+BOOL AssemblyMDInternalImport::IsValidToken ( // True or False.
+ mdToken tk) // [IN] Given token.
+{
+ _ASSERTE(!"NYI");
+ return FALSE;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::GetNestedClassProps ( // S_OK or error.
+ mdTypeDef tdNestedClass, // [IN] NestedClass token.
+ mdTypeDef *ptdEnclosingClass) // [OUT] EnclosingClass token.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::GetNativeCallConvFromSig ( // S_OK or error.
+ void const *pvSig, // [IN] Pointer to signature.
+ ULONG cbSig, // [IN] Count of signature bytes.
+ ULONG *pCallConv) // [OUT] Put calling conv here (see CorPinvokemap).
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::IsGlobal ( // S_OK or error.
+ mdToken pd, // [IN] Type, Field, or Method token.
+ int *pbGlobal) // [OUT] Put 1 if global, 0 otherwise.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::GetMethodSpecProps(
+ mdMethodSpec mi, // [IN] The method instantiation
+ mdToken *tkParent, // [OUT] MethodDef or MemberRef
+ PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to the blob value of meta data
+ ULONG *pcbSigBlob) // [OUT] actual size of signature blob
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+// *** ISNAssemblySignature methods ***
+
+STDMETHODIMP AssemblyMDInternalImport::GetSNAssemblySignature(
+ BYTE *pbSig, // [IN, OUT] Buffer to write signature
+ DWORD *pcbSig) // [IN, OUT] Size of buffer, bytes written
+{
+ return RuntimeGetAssemblyStrongNameHashForModule(m_pHandle, this, pbSig, pcbSig);
+}
+
+
+#include "strongname.h"
+
+#ifdef FEATURE_PREJIT
+// *** IGetIMDInternalImport ***
+STDMETHODIMP AssemblyMDInternalImport::GetIMDInternalImport(
+ IMDInternalImport ** pIMDInternalImport)
+{
+ m_pMDInternalImport->AddRef();
+ *pIMDInternalImport = m_pMDInternalImport;
+ return S_OK;
+}
+
+
+
+// ===========================================================================
+
+class CNativeImageDependency : public INativeImageDependency
+{
+public:
+ CNativeImageDependency(CORCOMPILE_DEPENDENCY * pDependency)
+ : m_cRef(1), m_pDependency(pDependency)
+ {
+ }
+
+ ~CNativeImageDependency()
+ {
+ }
+
+ //
+ // IUnknown
+ //
+
+ STDMETHODIMP_(ULONG) AddRef()
+ {
+ return InterlockedIncrement(&m_cRef);
+ }
+
+ STDMETHODIMP_(ULONG) Release()
+ {
+ ULONG cRef = InterlockedDecrement(&m_cRef);
+ if (!cRef)
+ delete this;
+ return (cRef);
+ }
+
+ STDMETHODIMP QueryInterface(REFIID riid, void **ppUnk)
+ {
+ *ppUnk = 0;
+
+ if (riid == IID_IUnknown)
+ *ppUnk = (IUnknown *) (IMetaDataAssemblyImport *) this;
+ else if (riid == IID_INativeImageDependency)
+ *ppUnk = (INativeImageDependency *) this;
+ else
+ return (E_NOINTERFACE);
+ AddRef();
+ return (S_OK);
+ }
+
+ //
+ // INativeImageDependency
+ //
+
+ STDMETHODIMP GetILAssemblyRef(mdAssemblyRef * pAssemblyRef)
+ {
+ BEGIN_ENTRYPOINT_NOTHROW;
+
+ *pAssemblyRef = m_pDependency->dwAssemblyRef;
+ END_ENTRYPOINT_NOTHROW;
+
+ return S_OK;
+ }
+
+ STDMETHODIMP GetILAssemblyDef(
+ mdAssemblyRef * ppAssemblyDef,
+ CORCOMPILE_ASSEMBLY_SIGNATURE * pSign)
+ {
+ BEGIN_ENTRYPOINT_NOTHROW;
+
+ *ppAssemblyDef = m_pDependency->dwAssemblyDef;
+ *pSign = m_pDependency->signAssemblyDef;
+ END_ENTRYPOINT_NOTHROW;
+
+ return S_OK;
+ }
+
+ STDMETHODIMP GetNativeAssemblyDef(CORCOMPILE_NGEN_SIGNATURE * pNativeSign)
+ {
+ BEGIN_ENTRYPOINT_NOTHROW;
+
+ *pNativeSign = m_pDependency->signNativeImage;
+ END_ENTRYPOINT_NOTHROW;
+
+ return S_OK;
+ }
+
+ STDMETHODIMP GetPEKind(PEKIND *pPEKind)
+ {
+ BEGIN_ENTRYPOINT_NOTHROW;
+
+ *pPEKind = PEKIND((m_pDependency->dependencyInfo & CORCOMPILE_DEPENDENCY_PEKIND_MASK) >> CORCOMPILE_DEPENDENCY_PEKIND_SHIFT);
+ END_ENTRYPOINT_NOTHROW;
+
+ return S_OK;
+ }
+
+protected:
+
+ LONG m_cRef;
+ CORCOMPILE_DEPENDENCY * m_pDependency;
+};
+
+// ===========================================================================
+// *** INativeImageInstallInfo ***
+// ===========================================================================
+
+STDMETHODIMP AssemblyMDInternalImport::GetSignature(CORCOMPILE_NGEN_SIGNATURE * pNgenSign)
+{
+ BEGIN_ENTRYPOINT_NOTHROW;
+
+ *pNgenSign = m_pZapVersionInfo->signature;
+ END_ENTRYPOINT_NOTHROW;
+
+ return S_OK;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::GetVersionInfo(CORCOMPILE_VERSION_INFO * pVersionInfo)
+{
+ BEGIN_ENTRYPOINT_NOTHROW;
+
+ *pVersionInfo = *m_pZapVersionInfo;
+ END_ENTRYPOINT_NOTHROW;
+ return S_OK;
+}
+
+
+
+STDMETHODIMP AssemblyMDInternalImport::GetILSignature(CORCOMPILE_ASSEMBLY_SIGNATURE * pILSign)
+{
+ BEGIN_ENTRYPOINT_NOTHROW;
+
+ *pILSign = m_pZapVersionInfo->sourceAssembly;
+ END_ENTRYPOINT_NOTHROW;
+ return S_OK;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::GetConfigMask(DWORD * pConfigMask)
+{
+ BEGIN_ENTRYPOINT_NOTHROW;
+
+ *pConfigMask = m_pZapVersionInfo->wConfigFlags;
+ END_ENTRYPOINT_NOTHROW;
+
+ return S_OK;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::EnumDependencies (
+ HCORENUM * phEnum, // [IN/OUT] - Pointer to the enum
+ INativeImageDependency *rDeps[], // [OUT]
+ ULONG cMax, // Max dependancies to enumerate in this iteration
+ DWORD * pdwCount // [OUT] - Number of dependancies actually enumerated
+ )
+{
+ HRESULT hr = S_OK;
+
+ BEGIN_ENTRYPOINT_NOTHROW;
+
+ CORCOMPILE_DEPENDENCY * pDependenciesEnd = m_pZapDependencies + m_cZapDependencies;
+
+ CORCOMPILE_DEPENDENCY * pNextDependency;
+
+ // Is the enum just being initialized, or are we walking an existing one?
+ if ((*phEnum) == NULL)
+ pNextDependency = m_pZapDependencies;
+ else
+ pNextDependency = (CORCOMPILE_DEPENDENCY *)(*phEnum);
+
+ DWORD count;
+ for (count = 0;
+ pNextDependency < pDependenciesEnd && count < cMax;
+ count++, pNextDependency++)
+ {
+ CNativeImageDependency * pDep = new (nothrow) CNativeImageDependency(pNextDependency);
+ IfNullGo( pDep );
+
+ rDeps[count] = pDep;
+ }
+
+ *phEnum = (HCORENUM)(pNextDependency < pDependenciesEnd) ? pNextDependency : NULL;
+ *pdwCount = count;
+
+ErrExit:
+ END_ENTRYPOINT_NOTHROW;
+
+ return hr;
+}
+
+
+STDMETHODIMP AssemblyMDInternalImport::GetDependency (
+ const CORCOMPILE_NGEN_SIGNATURE *pcngenSign, // [IN] ngenSig of dependency you want
+ CORCOMPILE_DEPENDENCY *pDep // [OUT] matching dependency
+ )
+{
+ HRESULT hr = S_OK;
+
+ BEGIN_ENTRYPOINT_NOTHROW;
+
+ _ASSERTE(pcngenSign != NULL);
+ _ASSERTE(*pcngenSign != INVALID_NGEN_SIGNATURE);
+ _ASSERTE(pDep != NULL);
+
+ CORCOMPILE_DEPENDENCY * pDependenciesEnd = m_pZapDependencies + m_cZapDependencies;
+ CORCOMPILE_DEPENDENCY * pNextDependency = m_pZapDependencies;
+ while (pNextDependency != pDependenciesEnd)
+ {
+ if (pNextDependency->signNativeImage == *pcngenSign)
+ {
+ *pDep = *pNextDependency;
+ hr = S_OK;
+ goto ErrExit;
+ }
+ pNextDependency++;
+ }
+ hr = S_FALSE;
+
+ErrExit:
+ END_ENTRYPOINT_NOTHROW;
+
+ return hr;
+}
+
+
+#endif // FEATURE_PREJIT
+
+
+//*****************************************************************************
+// IMetaDataImport2 methods
+//*****************************************************************************
+STDMETHODIMP AssemblyMDInternalImport::GetGenericParamProps( // S_OK or error.
+ mdGenericParam gp, // [IN] GenericParam
+ ULONG *pulParamSeq, // [OUT] Index of the type parameter
+ DWORD *pdwParamFlags, // [OUT] Flags, for future use (e.g. variance)
+ mdToken *ptOwner, // [OUT] Owner (TypeDef or MethodDef)
+ DWORD *reserved, // [OUT] For future use (e.g. non-type parameters)
+ __out_ecount (cchName) LPWSTR wzname, // [OUT] Put name here
+ ULONG cchName, // [IN] Size of buffer
+ ULONG *pchName) // [OUT] Put size of name (wide chars) here.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::GetGenericParamConstraintProps( // S_OK or error.
+ mdGenericParamConstraint gpc, // [IN] GenericParamConstraint
+ mdGenericParam *ptGenericParam, // [OUT] GenericParam that is constrained
+ mdToken *ptkConstraintType) // [OUT] TypeDef/Ref/Spec constraint
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::EnumGenericParams( // S_OK or error.
+ HCORENUM *phEnum, // [IN|OUT] Pointer to the enum.
+ mdToken tk, // [IN] TypeDef or MethodDef whose generic parameters are requested
+ mdGenericParam rGenericParams[], // [OUT] Put GenericParams here.
+ ULONG cMax, // [IN] Max GenericParams to put.
+ ULONG *pcGenericParams) // [OUT] Put # put here.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::EnumGenericParamConstraints( // S_OK or error.
+ HCORENUM *phEnum, // [IN|OUT] Pointer to the enum.
+ mdGenericParam tk, // [IN] GenericParam whose constraints are requested
+ mdGenericParamConstraint rGenericParamConstraints[], // [OUT] Put GenericParamConstraints here.
+ ULONG cMax, // [IN] Max GenericParamConstraints to put.
+ ULONG *pcGenericParamConstraints) // [OUT] Put # put here.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::EnumMethodSpecs( // S_OK or error.
+ HCORENUM *phEnum, // [IN|OUT] Pointer to the enum.
+ mdToken tk, // [IN] MethodDef or MemberRef whose MethodSpecs are requested
+ mdMethodSpec rMethodSpecs[], // [OUT] Put MethodSpecs here.
+ ULONG cMax, // [IN] Max tokens to put.
+ ULONG *pcMethodSpecs) // [OUT] Put actual count here.
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::GetPEKind( // S_OK or error.
+ DWORD* pdwPEKind, // [OUT] The kind of PE (0 - not a PE)
+ DWORD* pdwMachine) // [OUT] Machine as defined in NT header
+{
+ HRESULT hr = S_OK;
+ if(pdwPEKind) *pdwPEKind = m_dwPEKind;
+ if(pdwMachine) *pdwMachine = m_dwMachine;
+ return hr;
+}
+
+STDMETHODIMP AssemblyMDInternalImport::GetVersionString( // S_OK or error.
+ __out_ecount (ccBufSize) LPWSTR pwzBuf, // Put version string here.
+ DWORD ccBufSize, // [in] size of the buffer, in wide chars
+ DWORD *pccBufSize) // [out] Size of the version string, wide chars, including terminating nul.
+{
+ HRESULT hr=S_OK;
+ DWORD L = WszMultiByteToWideChar(CP_UTF8,0,m_szVersionString,-1,pwzBuf,ccBufSize);
+ if(ccBufSize < L)
+ hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
+
+ if(pccBufSize) *pccBufSize = L;
+ return hr;
+}
+
+#endif //!DACCESS_COMPILE
+
+#endif // FEATURE_FUSION
+
+#endif //FEATURE_METADATA_INTERNAL_APIS
diff --git a/src/md/runtime/mdinternaldisp.h b/src/md/runtime/mdinternaldisp.h
new file mode 100644
index 0000000000..689e1f498e
--- /dev/null
+++ b/src/md/runtime/mdinternaldisp.h
@@ -0,0 +1,44 @@
+// 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.
+//*****************************************************************************
+// MDInternalDispenser.h
+//
+
+//
+// Contains utility code for MD directory
+//
+//*****************************************************************************
+#ifndef __MDInternalDispenser__h__
+#define __MDInternalDispenser__h__
+
+#ifdef FEATURE_METADATA_INTERNAL_APIS
+
+#include "mdinternalro.h"
+
+
+enum MDFileFormat
+{
+ MDFormat_ReadOnly = 0,
+ MDFormat_ReadWrite = 1,
+ MDFormat_ICR = 2,
+ MDFormat_Invalid = 3
+};
+
+
+HRESULT CheckFileFormat(LPVOID pData, ULONG cbData, MDFileFormat *pFormat);
+STDAPI GetMDInternalInterface(
+ LPVOID pData, // [IN] Buffer with the metadata.
+ ULONG cbData, // [IN] Size of the data in the buffer.
+ DWORD flags, // [IN] MDInternal_OpenForRead or MDInternal_OpenForENC
+ REFIID riid, // [in] The interface desired.
+ void **ppIUnk); // [out] Return interface on success.
+
+HRESULT GetAssemblyMDInternalImportHelper(HCORMODULE hModule,
+ REFIID riid,
+ MDInternalImportFlags flags,
+ IUnknown **ppIUnk);
+
+#endif //FEATURE_METADATA_INTERNAL_APIS
+
+#endif // __MDInternalDispenser__h__
diff --git a/src/md/runtime/mdinternalro.cpp b/src/md/runtime/mdinternalro.cpp
new file mode 100644
index 0000000000..d16d2b02eb
--- /dev/null
+++ b/src/md/runtime/mdinternalro.cpp
@@ -0,0 +1,3742 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+// ===========================================================================
+// File: MDInternalRO.CPP
+//
+
+// Notes:
+//
+//
+// ===========================================================================
+#include "stdafx.h"
+#include "mdinternalro.h"
+#include "metamodelro.h"
+#include "liteweightstgdb.h"
+#include "corhlpr.h"
+#include "../compiler/regmeta.h"
+#include "caparser.h"
+
+#ifdef FEATURE_METADATA_INTERNAL_APIS
+
+__checkReturn
+HRESULT _FillMDDefaultValue(
+ BYTE bType,
+ void const *pValue,
+ ULONG cbValue,
+ MDDefaultValue *pMDDefaultValue);
+
+#ifndef DACCESS_COMPILE
+__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
+#endif //!DACCESS_COMPILE
+
+__checkReturn
+HRESULT GetInternalWithRWFormat(
+ LPVOID pData,
+ ULONG cbData,
+ DWORD flags, // [IN] MDInternal_OpenForRead or MDInternal_OpenForENC
+ REFIID riid, // [in] The interface desired.
+ void **ppIUnk); // [out] Return interface on success.
+
+// forward declaration
+__checkReturn
+HRESULT MDApplyEditAndContinue( // S_OK or error.
+ IMDInternalImport **ppIMD, // [in, out] The metadata to be updated.
+ IMDInternalImportENC *pDeltaMD); // [in] The delta metadata.
+
+
+//*****************************************************************************
+// Constructor
+//*****************************************************************************
+MDInternalRO::MDInternalRO()
+ : m_pMethodSemanticsMap(0),
+ m_cRefs(1)
+{
+} // MDInternalRO::MDInternalRO
+
+
+
+//*****************************************************************************
+// Destructor
+//*****************************************************************************
+MDInternalRO::~MDInternalRO()
+{
+ m_LiteWeightStgdb.Uninit();
+ if (m_pMethodSemanticsMap)
+ delete[] m_pMethodSemanticsMap;
+ m_pMethodSemanticsMap = 0;
+} // MDInternalRO::~MDInternalRO
+
+//*****************************************************************************
+// IUnknown
+//*****************************************************************************
+ULONG MDInternalRO::AddRef()
+{
+ return InterlockedIncrement(&m_cRefs);
+} // MDInternalRO::AddRef
+
+ULONG MDInternalRO::Release()
+{
+ ULONG cRef = InterlockedDecrement(&m_cRefs);
+ if (cRef == 0)
+ delete this;
+ return cRef;
+} // MDInternalRO::Release
+
+__checkReturn
+HRESULT MDInternalRO::QueryInterface(REFIID riid, void **ppUnk)
+{
+ *ppUnk = 0;
+
+ if (riid == IID_IUnknown)
+ *ppUnk = this; // ! QI for IID_IUnknown must return MDInternalRO. ConvertRO2RW() has dependency on this.
+ else if (riid == IID_IMDInternalImport)
+ *ppUnk = (IMDInternalImport *)this;
+ else if (riid == IID_IMDCommon)
+ *ppUnk = (IMDCommon *)this;
+ else
+ return E_NOINTERFACE;
+ AddRef();
+ return S_OK;
+} // MDInternalRO::QueryInterface
+
+
+//*****************************************************************************
+// Initialize
+//*****************************************************************************
+__checkReturn
+HRESULT MDInternalRO::Init(
+ LPVOID pData, // points to meta data section in memory
+ ULONG cbData) // count of bytes in pData
+{
+ m_tdModule = COR_GLOBAL_PARENT_TOKEN;
+
+ extern HRESULT _CallInitOnMemHelper(CLiteWeightStgdb<CMiniMd> *pStgdb, ULONG cbData, LPCVOID pData);
+
+ return _CallInitOnMemHelper(&m_LiteWeightStgdb, cbData, (BYTE*) pData);
+} // MDInternalRO::Init
+
+#ifndef DACCESS_COMPILE
+//*****************************************************************************
+// Given a scope, determine whether imported from a typelib.
+//*****************************************************************************
+__checkReturn
+HRESULT MDInternalRO::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);
+} // MDInternalRO::TranslateSigWithScope
+#endif // DACCESS_COMPILE
+
+__checkReturn
+HRESULT MDInternalRO::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_LiteWeightStgdb.m_MiniMd.GetTypeDefRefTokenInTypeSpec(tkTypeSpec, tkEnclosedToken);
+} // MDInternalRO::GetTypeDefRefTokenInTypeSpec
+
+#ifndef DACCESS_COMPILE
+//*****************************************************************************
+// Given a scope, return the number of tokens in a given table
+//*****************************************************************************
+ULONG MDInternalRO::GetCountWithTokenKind( // return hresult
+ DWORD tkKind) // [IN] pass in the kind of token.
+{
+ ULONG ulCount = m_LiteWeightStgdb.m_MiniMd.CommonGetRowCount(tkKind);
+ if (tkKind == mdtTypeDef)
+ {
+ // Remove global typedef from the count of typedefs (and handle the case where there is no global typedef)
+ if (ulCount > 0)
+ ulCount--;
+ }
+ return ulCount;
+} // MDInternalRO::GetCountWithTokenKind
+#endif //!DACCESS_COMPILE
+
+//*******************************************************************************
+// Enumerator helpers
+//*******************************************************************************
+
+
+//*****************************************************************************
+// enumerator init for typedef
+//*****************************************************************************
+__checkReturn
+HRESULT MDInternalRO::EnumTypeDefInit( // return hresult
+ HENUMInternal *phEnum) // [OUT] buffer to fill for enumerator data
+{
+ HRESULT hr = NOERROR;
+
+ _ASSERTE(phEnum);
+
+ memset(phEnum, 0, sizeof(HENUMInternal));
+ phEnum->m_tkKind = mdtTypeDef;
+ phEnum->m_EnumType = MDSimpleEnum;
+ phEnum->m_ulCount = m_LiteWeightStgdb.m_MiniMd.getCountTypeDefs();
+
+ // Skip over the global model typedef
+ //
+ // phEnum->u.m_ulCur : the current rid that is not yet enumerated
+ // phEnum->u.m_ulStart : the first rid that will be returned by enumerator
+ // phEnum->u.m_ulEnd : the last rid that will be returned by enumerator
+ phEnum->u.m_ulStart = phEnum->u.m_ulCur = 2;
+ phEnum->u.m_ulEnd = phEnum->m_ulCount + 1;
+ if (phEnum->m_ulCount > 0)
+ phEnum->m_ulCount --;
+
+ return hr;
+} // MDInternalRO::EnumTypeDefInit
+
+
+//*****************************************************************************
+// get the number of typedef in a scope
+//*****************************************************************************
+ULONG MDInternalRO::EnumTypeDefGetCount(
+ HENUMInternal *phEnum) // [IN] the enumerator to retrieve information
+{
+ _ASSERTE(phEnum->m_tkKind == mdtTypeDef);
+ return phEnum->m_ulCount;
+} // MDInternalRO::EnumTypeDefGetCount
+
+
+//*****************************************************************************
+// enumerator for typedef
+//*****************************************************************************
+bool MDInternalRO::EnumTypeDefNext( // return hresult
+ HENUMInternal *phEnum, // [IN] input enum
+ mdTypeDef *ptd) // [OUT] return token
+{
+ _ASSERTE(phEnum && ptd);
+
+ if (phEnum->u.m_ulCur >= phEnum->u.m_ulEnd)
+ return false;
+
+ *ptd = phEnum->u.m_ulCur++;
+ RidToToken(*ptd, mdtTypeDef);
+ return true;
+} // MDInternalRO::EnumTypeDefNext
+
+
+//*****************************************
+// Reset the enumerator to the beginning.
+//*****************************************
+void MDInternalRO::EnumTypeDefReset(
+ HENUMInternal *phEnum) // [IN] the enumerator to be reset
+{
+ _ASSERTE(phEnum);
+ _ASSERTE( phEnum->m_EnumType == MDSimpleEnum );
+
+ // not using CRCURSOR
+ phEnum->u.m_ulCur = phEnum->u.m_ulStart;
+} // MDInternalRO::EnumTypeDefReset
+
+
+//*****************************************
+// Close the enumerator. Only for read/write mode that we need to close the cursor.
+// Hopefully with readonly mode, it will be a no-op
+//*****************************************
+void MDInternalRO::EnumTypeDefClose(
+ HENUMInternal *phEnum) // [IN] the enumerator to be closed
+{
+ _ASSERTE( phEnum->m_EnumType == MDSimpleEnum );
+} // MDInternalRO::EnumTypeDefClose
+
+
+//*****************************************************************************
+// Enumerator init for MethodImpl. The second HENUMInternal* parameter is
+// only used for the R/W version of the MetaData.
+//*****************************************************************************
+__checkReturn
+HRESULT MDInternalRO::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 *phEnumDecl) // [OUT] buffer to fill for enumerator data for MethodDecl tokens.
+{
+ return EnumInit(TBL_MethodImpl << 24, td, phEnumBody);
+} // MDInternalRO::EnumMethodImplInit
+
+//*****************************************************************************
+// get the number of MethodImpls in a scope
+//*****************************************************************************
+ULONG MDInternalRO::EnumMethodImplGetCount(
+ HENUMInternal *phEnumBody, // [IN] MethodBody enumerator.
+ HENUMInternal *phEnumDecl) // [IN] MethodDecl enumerator.
+{
+ _ASSERTE(phEnumBody && ((phEnumBody->m_tkKind >> 24) == TBL_MethodImpl));
+ return phEnumBody->m_ulCount;
+} // MDInternalRO::EnumMethodImplGetCount
+
+
+//*****************************************************************************
+// enumerator for MethodImpl.
+//*****************************************************************************
+__checkReturn
+HRESULT
+MDInternalRO::EnumMethodImplNext( // return hresult
+ HENUMInternal *phEnumBody, // [IN] input enum for MethodBody
+ HENUMInternal *phEnumDecl, // [IN] input enum for MethodDecl
+ mdToken *ptkBody, // [OUT] return token for MethodBody
+ mdToken *ptkDecl) // [OUT] return token for MethodDecl
+{
+ HRESULT hr;
+ MethodImplRec *pRecord;
+
+ _ASSERTE(phEnumBody && ((phEnumBody->m_tkKind >> 24) == TBL_MethodImpl));
+ _ASSERTE(ptkBody && ptkDecl);
+
+ if (phEnumBody->u.m_ulCur >= phEnumBody->u.m_ulEnd)
+ {
+ return S_FALSE;
+ }
+
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodImplRecord(phEnumBody->u.m_ulCur, &pRecord));
+ *ptkBody = m_LiteWeightStgdb.m_MiniMd.getMethodBodyOfMethodImpl(pRecord);
+ *ptkDecl = m_LiteWeightStgdb.m_MiniMd.getMethodDeclarationOfMethodImpl(pRecord);
+ phEnumBody->u.m_ulCur++;
+
+ return S_OK;
+} // MDInternalRO::EnumMethodImplNext
+
+//*****************************************
+// Reset the enumerator to the beginning.
+//*****************************************
+void MDInternalRO::EnumMethodImplReset(
+ HENUMInternal *phEnumBody, // [IN] MethodBody enumerator.
+ HENUMInternal *phEnumDecl) // [IN] MethodDecl enumerator.
+{
+ _ASSERTE(phEnumBody && ((phEnumBody->m_tkKind >> 24) == TBL_MethodImpl));
+ _ASSERTE(phEnumBody->m_EnumType == MDSimpleEnum);
+
+ phEnumBody->u.m_ulCur = phEnumBody->u.m_ulStart;
+} // MDInternalRO::EnumMethodImplReset
+
+
+//*****************************************
+// Close the enumerator.
+//*****************************************
+void MDInternalRO::EnumMethodImplClose(
+ HENUMInternal *phEnumBody, // [IN] MethodBody enumerator.
+ HENUMInternal *phEnumDecl) // [IN] MethodDecl enumerator.
+{
+ _ASSERTE(phEnumBody && ((phEnumBody->m_tkKind >> 24) == TBL_MethodImpl));
+ _ASSERTE(phEnumBody->m_EnumType == MDSimpleEnum);
+} // MDInternalRO::EnumMethodImplClose
+
+
+//******************************************************************************
+// enumerator for global functions
+//******************************************************************************
+__checkReturn
+HRESULT MDInternalRO::EnumGlobalFunctionsInit( // return hresult
+ HENUMInternal *phEnum) // [OUT] buffer to fill for enumerator data
+{
+ return EnumInit(mdtMethodDef, m_tdModule, phEnum);
+}
+
+
+//******************************************************************************
+// enumerator for global Fields
+//******************************************************************************
+__checkReturn
+HRESULT MDInternalRO::EnumGlobalFieldsInit( // return hresult
+ HENUMInternal *phEnum) // [OUT] buffer to fill for enumerator data
+{
+ return EnumInit(mdtFieldDef, m_tdModule, phEnum);
+}
+
+
+//*****************************************
+// Enumerator initializer
+//*****************************************
+__checkReturn
+HRESULT MDInternalRO::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
+{
+ HRESULT hr = S_OK;
+ ULONG ulMax = 0;
+
+ // Vars for query.
+ _ASSERTE(phEnum);
+ HENUMInternal::ZeroEnum(phEnum);
+
+ // cache the tkKind and the scope
+ phEnum->m_tkKind = TypeFromToken(tkKind);
+
+ TypeDefRec *pRec;
+
+ phEnum->m_EnumType = MDSimpleEnum;
+
+ switch (TypeFromToken(tkKind))
+ {
+ case mdtFieldDef:
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetTypeDefRecord(RidFromToken(tkParent), &pRec));
+ phEnum->u.m_ulStart = m_LiteWeightStgdb.m_MiniMd.getFieldListOfTypeDef(pRec);
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.getEndFieldListOfTypeDef(RidFromToken(tkParent), &(phEnum->u.m_ulEnd)));
+ break;
+
+ case mdtMethodDef:
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetTypeDefRecord(RidFromToken(tkParent), &pRec));
+ phEnum->u.m_ulStart = m_LiteWeightStgdb.m_MiniMd.getMethodListOfTypeDef(pRec);
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.getEndMethodListOfTypeDef(RidFromToken(tkParent), &(phEnum->u.m_ulEnd)));
+ break;
+
+ case mdtGenericParam:
+ _ASSERTE(TypeFromToken(tkParent) == mdtTypeDef || TypeFromToken(tkParent) == mdtMethodDef);
+
+ if (TypeFromToken(tkParent) != mdtTypeDef && TypeFromToken(tkParent) != mdtMethodDef)
+ IfFailGo(CLDB_E_FILE_CORRUPT);
+
+ if (TypeFromToken(tkParent) == mdtTypeDef)
+ {
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.getGenericParamsForTypeDef(
+ RidFromToken(tkParent),
+ &phEnum->u.m_ulEnd,
+ &(phEnum->u.m_ulStart)));
+ }
+ else
+ {
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.getGenericParamsForMethodDef(
+ RidFromToken(tkParent),
+ &phEnum->u.m_ulEnd,
+ &(phEnum->u.m_ulStart)));
+ }
+ break;
+
+ case mdtGenericParamConstraint:
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.getGenericParamConstraintsForGenericParam(
+ RidFromToken(tkParent),
+ &phEnum->u.m_ulEnd,
+ &phEnum->u.m_ulStart));
+ break;
+
+ case mdtInterfaceImpl:
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.getInterfaceImplsForTypeDef(RidFromToken(tkParent), &phEnum->u.m_ulEnd, &phEnum->u.m_ulStart));
+ break;
+
+ case mdtProperty:
+ RID ridPropertyMap;
+ PropertyMapRec *pPropertyMapRec;
+
+ // get the starting/ending rid of properties of this typedef
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.FindPropertyMapFor(RidFromToken(tkParent), &ridPropertyMap));
+ if (!InvalidRid(ridPropertyMap))
+ {
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetPropertyMapRecord(ridPropertyMap, &pPropertyMapRec));
+ phEnum->u.m_ulStart = m_LiteWeightStgdb.m_MiniMd.getPropertyListOfPropertyMap(pPropertyMapRec);
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.getEndPropertyListOfPropertyMap(ridPropertyMap, &(phEnum->u.m_ulEnd)));
+ ulMax = m_LiteWeightStgdb.m_MiniMd.getCountPropertys() + 1;
+ if(phEnum->u.m_ulStart == 0) phEnum->u.m_ulStart = 1;
+ if(phEnum->u.m_ulEnd > ulMax) phEnum->u.m_ulEnd = ulMax;
+ if(phEnum->u.m_ulStart > phEnum->u.m_ulEnd) phEnum->u.m_ulStart = phEnum->u.m_ulEnd;
+ }
+ break;
+
+ case mdtEvent:
+ RID ridEventMap;
+ EventMapRec *pEventMapRec;
+
+ // get the starting/ending rid of events of this typedef
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.FindEventMapFor(RidFromToken(tkParent), &ridEventMap));
+ if (!InvalidRid(ridEventMap))
+ {
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetEventMapRecord(ridEventMap, &pEventMapRec));
+ phEnum->u.m_ulStart = m_LiteWeightStgdb.m_MiniMd.getEventListOfEventMap(pEventMapRec);
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.getEndEventListOfEventMap(ridEventMap, &(phEnum->u.m_ulEnd)));
+ ulMax = m_LiteWeightStgdb.m_MiniMd.getCountEvents() + 1;
+ if(phEnum->u.m_ulStart == 0) phEnum->u.m_ulStart = 1;
+ if(phEnum->u.m_ulEnd > ulMax) phEnum->u.m_ulEnd = ulMax;
+ if(phEnum->u.m_ulStart > phEnum->u.m_ulEnd) phEnum->u.m_ulStart = phEnum->u.m_ulEnd;
+ }
+ break;
+
+ case mdtParamDef:
+ _ASSERTE(TypeFromToken(tkParent) == mdtMethodDef);
+
+ MethodRec *pMethodRec;
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetMethodRecord(RidFromToken(tkParent), &pMethodRec));
+
+ // figure out the start rid and end rid of the parameter list of this methoddef
+ phEnum->u.m_ulStart = m_LiteWeightStgdb.m_MiniMd.getParamListOfMethod(pMethodRec);
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.getEndParamListOfMethod(RidFromToken(tkParent), &(phEnum->u.m_ulEnd)));
+ break;
+ case mdtCustomAttribute:
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.getCustomAttributeForToken(tkParent, &phEnum->u.m_ulEnd, &phEnum->u.m_ulStart));
+ break;
+ case mdtAssemblyRef:
+ _ASSERTE(IsNilToken(tkParent));
+ phEnum->u.m_ulStart = 1;
+ phEnum->u.m_ulEnd = m_LiteWeightStgdb.m_MiniMd.getCountAssemblyRefs() + 1;
+ break;
+ case mdtFile:
+ _ASSERTE(IsNilToken(tkParent));
+ phEnum->u.m_ulStart = 1;
+ phEnum->u.m_ulEnd = m_LiteWeightStgdb.m_MiniMd.getCountFiles() + 1;
+ break;
+ case mdtExportedType:
+ _ASSERTE(IsNilToken(tkParent));
+ phEnum->u.m_ulStart = 1;
+ phEnum->u.m_ulEnd = m_LiteWeightStgdb.m_MiniMd.getCountExportedTypes() + 1;
+ break;
+ case mdtManifestResource:
+ _ASSERTE(IsNilToken(tkParent));
+ phEnum->u.m_ulStart = 1;
+ phEnum->u.m_ulEnd = m_LiteWeightStgdb.m_MiniMd.getCountManifestResources() + 1;
+ break;
+ case mdtModuleRef:
+ _ASSERTE(IsNilToken(tkParent));
+ phEnum->u.m_ulStart = 1;
+ phEnum->u.m_ulEnd = m_LiteWeightStgdb.m_MiniMd.getCountModuleRefs() + 1;
+ break;
+ case (TBL_MethodImpl << 24):
+ _ASSERTE(! IsNilToken(tkParent));
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.getMethodImplsForClass(
+ RidFromToken(tkParent),
+ &phEnum->u.m_ulEnd,
+ &phEnum->u.m_ulStart));
+ break;
+ default:
+ _ASSERTE(!"ENUM INIT not implemented for the compressed format!");
+ IfFailGo(E_NOTIMPL);
+ break;
+ }
+
+ // If the count is negative, the metadata is corrupted somehow.
+ if (phEnum->u.m_ulEnd < phEnum->u.m_ulStart)
+ IfFailGo(CLDB_E_FILE_CORRUPT);
+
+ phEnum->m_ulCount = phEnum->u.m_ulEnd - phEnum->u.m_ulStart;
+ phEnum->u.m_ulCur = phEnum->u.m_ulStart;
+
+ErrExit:
+ // we are done
+ return hr;
+}
+
+
+//*****************************************
+// Enumerator initializer
+//*****************************************
+__checkReturn
+HRESULT MDInternalRO::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 = S_OK;
+
+ // Vars for query.
+ _ASSERTE(phEnum);
+ memset(phEnum, 0, sizeof(HENUMInternal));
+
+ // cache the tkKind and the scope
+ phEnum->m_tkKind = TypeFromToken(tkKind);
+ phEnum->m_EnumType = MDSimpleEnum;
+
+ switch (TypeFromToken(tkKind))
+ {
+ case mdtTypeRef:
+ phEnum->m_ulCount = m_LiteWeightStgdb.m_MiniMd.getCountTypeRefs();
+ break;
+
+ case mdtMemberRef:
+ phEnum->m_ulCount = m_LiteWeightStgdb.m_MiniMd.getCountMemberRefs();
+ break;
+
+ case mdtSignature:
+ phEnum->m_ulCount = m_LiteWeightStgdb.m_MiniMd.getCountStandAloneSigs();
+ break;
+
+ case mdtMethodDef:
+ phEnum->m_ulCount = m_LiteWeightStgdb.m_MiniMd.getCountMethods();
+ break;
+
+ case mdtMethodSpec:
+ phEnum->m_ulCount = m_LiteWeightStgdb.m_MiniMd.getCountMethodSpecs();
+ break;
+
+ case mdtFieldDef:
+ phEnum->m_ulCount = m_LiteWeightStgdb.m_MiniMd.getCountFields();
+ break;
+
+ case mdtTypeSpec:
+ phEnum->m_ulCount = m_LiteWeightStgdb.m_MiniMd.getCountTypeSpecs();
+ break;
+
+ case mdtAssemblyRef:
+ phEnum->m_ulCount = m_LiteWeightStgdb.m_MiniMd.getCountAssemblyRefs();
+ break;
+
+ case mdtModuleRef:
+ phEnum->m_ulCount = m_LiteWeightStgdb.m_MiniMd.getCountModuleRefs();
+ break;
+
+ case mdtTypeDef:
+ phEnum->m_ulCount = m_LiteWeightStgdb.m_MiniMd.getCountTypeDefs();
+ break;
+
+ case mdtFile:
+ phEnum->m_ulCount = m_LiteWeightStgdb.m_MiniMd.getCountFiles();
+ break;
+
+ default:
+ _ASSERTE(!"Bad token kind!");
+ break;
+ }
+ phEnum->u.m_ulStart = phEnum->u.m_ulCur = 1;
+ phEnum->u.m_ulEnd = phEnum->m_ulCount + 1;
+
+ // we are done
+ return hr;
+} // MDInternalRO::EnumAllInit
+
+
+//*****************************************
+// get the count
+//*****************************************
+ULONG MDInternalRO::EnumGetCount(
+ HENUMInternal *phEnum) // [IN] the enumerator to retrieve information
+{
+ _ASSERTE(phEnum);
+ return phEnum->m_ulCount;
+}
+
+//*****************************************
+// Get next value contained in the enumerator
+//*****************************************
+bool MDInternalRO::EnumNext(
+ HENUMInternal *phEnum, // [IN] the enumerator to retrieve information
+ mdToken *ptk) // [OUT] token to scope the search
+{
+ _ASSERTE(phEnum && ptk);
+ if (phEnum->u.m_ulCur >= phEnum->u.m_ulEnd)
+ return false;
+
+ if ( phEnum->m_EnumType == MDSimpleEnum )
+ {
+ *ptk = phEnum->u.m_ulCur | phEnum->m_tkKind;
+ phEnum->u.m_ulCur++;
+ }
+ else
+ {
+ TOKENLIST *pdalist = (TOKENLIST *)&(phEnum->m_cursor);
+
+ _ASSERTE( phEnum->m_EnumType == MDDynamicArrayEnum );
+ *ptk = *( pdalist->Get(phEnum->u.m_ulCur++) );
+ }
+ return true;
+} // MDInternalRO::EnumNext
+
+
+//*****************************************
+// Reset the enumerator to the beginning.
+//*****************************************
+void MDInternalRO::EnumReset(
+ HENUMInternal *phEnum) // [IN] the enumerator to be reset
+{
+ _ASSERTE(phEnum);
+ _ASSERTE( phEnum->m_EnumType == MDSimpleEnum || phEnum->m_EnumType == MDDynamicArrayEnum);
+
+ phEnum->u.m_ulCur = phEnum->u.m_ulStart;
+} // MDInternalRO::EnumReset
+
+
+//*****************************************
+// Close the enumerator. Only for read/write mode that we need to close the cursor.
+// Hopefully with readonly mode, it will be a no-op
+//*****************************************
+void MDInternalRO::EnumClose(
+ HENUMInternal *phEnum) // [IN] the enumerator to be closed
+{
+ _ASSERTE( phEnum->m_EnumType == MDSimpleEnum ||
+ phEnum->m_EnumType == MDDynamicArrayEnum ||
+ phEnum->m_EnumType == MDCustomEnum );
+ if (phEnum->m_EnumType == MDDynamicArrayEnum)
+ HENUMInternal::ClearEnum(phEnum);
+} // MDInternalRO::EnumClose
+
+
+//---------------------------------------------------------------------------------------
+//
+// Initialize enumerator of PermissionSets.
+//
+// Return Value:
+// CLDB_E_RECORD_NOTFOUND ... If record not found.
+// S_OK and empty enumeration ... If tkParent is nil token and Action is dclActionNil.
+//
+__checkReturn
+HRESULT
+MDInternalRO::EnumPermissionSetsInit(
+ mdToken tkParent, // [IN] Token to scope the search.
+ CorDeclSecurity Action, // [IN] Action to scope the search.
+ HENUMInternal *phEnum) // [OUT] Enumerator to fill.
+{
+ HRESULT hr = S_OK;
+
+ _ASSERTE(phEnum != NULL);
+ HENUMInternal::ZeroEnum(phEnum);
+
+ // cache the tkKind
+ phEnum->m_tkKind = mdtPermission;
+
+ DeclSecurityRec *pDecl;
+ RID ridCur;
+ RID ridEnd;
+
+ phEnum->m_EnumType = MDSimpleEnum;
+
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.getDeclSecurityForToken(tkParent, &ridEnd, &ridCur));
+ if (Action != dclActionNil)
+ {
+ for (; ridCur < ridEnd; ridCur++)
+ {
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetDeclSecurityRecord(ridCur, &pDecl));
+ if (Action == m_LiteWeightStgdb.m_MiniMd.getActionOfDeclSecurity(pDecl))
+ {
+ // found a match
+ phEnum->u.m_ulStart = phEnum->u.m_ulCur = ridCur;
+ phEnum->u.m_ulEnd = ridCur + 1;
+ phEnum->m_ulCount = 1;
+ goto ErrExit;
+ }
+ }
+ hr = CLDB_E_RECORD_NOTFOUND;
+ }
+ else
+ {
+ phEnum->u.m_ulStart = phEnum->u.m_ulCur = ridCur;
+ phEnum->u.m_ulEnd = ridEnd;
+ phEnum->m_ulCount = ridEnd - ridCur;
+ }
+
+ErrExit:
+ return hr;
+} // MDInternalRO::EnumPermissionSetInit
+
+
+//*****************************************
+// Enumerator initializer for CustomAttributes
+//*****************************************
+__checkReturn
+HRESULT MDInternalRO::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
+{
+ return m_LiteWeightStgdb.m_MiniMd.CommonEnumCustomAttributeByName(tkParent, szName, false, phEnum);
+} // MDInternalRO::EnumCustomAttributeByNameInit
+
+//*****************************************
+// Enumerator for CustomAttributes which doesn't
+// allocate any memory
+//*****************************************
+__checkReturn
+HRESULT MDInternalRO::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
+{
+ _ASSERTE(phEnum);
+
+ HRESULT hr;
+ ULONG ridStart, ridEnd; // Loop start and endpoints.
+
+ // Get the list of custom values for the parent object.
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getCustomAttributeForToken(tkParent, &ridEnd, &ridStart));
+ // If found none, done.
+ if (ridStart == 0)
+ goto NoMatch;
+
+ phEnum->m_EnumType = MDCustomEnum;
+ phEnum->m_tkKind = mdtCustomAttribute;
+ phEnum->u.m_ulStart = ridStart;
+ phEnum->u.m_ulEnd = ridEnd;
+ phEnum->u.m_ulCur = ridStart;
+
+ return S_OK;
+
+NoMatch:
+ return S_FALSE;
+} // MDInternalRO::SafeAndSlowEnumCustomAttributeByNameInit
+
+__checkReturn
+HRESULT MDInternalRO::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
+{
+ _ASSERTE(phEnum);
+ _ASSERTE(phEnum->m_EnumType == MDCustomEnum);
+ _ASSERTE(phEnum->m_tkKind == mdtCustomAttribute);
+
+ // Look for one with the given name.
+ for (; phEnum->u.m_ulCur < phEnum->u.m_ulEnd; ++phEnum->u.m_ulCur)
+ {
+ if (S_OK == m_LiteWeightStgdb.m_MiniMd.CompareCustomAttribute( tkParent, szName, phEnum->u.m_ulCur))
+ {
+ // If here, found a match.
+ *mdAttribute = TokenFromRid(phEnum->u.m_ulCur, mdtCustomAttribute);
+ phEnum->u.m_ulCur++;
+ return S_OK;
+ }
+ }
+ // No match...
+ return S_FALSE;
+} // MDInternalRO::SafeAndSlowEnumCustomAttributeByNameNext
+
+
+//*****************************************
+// 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
+HRESULT MDInternalRO::GetParentToken(
+ mdToken tkChild, // [IN] given child token
+ mdToken *ptkParent) // [OUT] returning parent
+{
+ HRESULT hr = NOERROR;
+
+ _ASSERTE(ptkParent);
+
+ switch (TypeFromToken(tkChild))
+ {
+ case mdtTypeDef:
+ hr = GetNestedClassProps(tkChild, ptkParent);
+ // If not found, the *ptkParent has to be left unchanged! (callers depend on that)
+ if (hr == CLDB_E_RECORD_NOTFOUND)
+ {
+ hr = S_OK;
+ }
+ break;
+
+ case mdtMethodDef:
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.FindParentOfMethod(RidFromToken(tkChild), (RID *)ptkParent));
+ RidToToken(*ptkParent, mdtTypeDef);
+ break;
+
+ case mdtMethodSpec:
+ {
+ MethodSpecRec *pRec;
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodSpecRecord(RidFromToken(tkChild), &pRec));
+ *ptkParent = m_LiteWeightStgdb.m_MiniMd.getMethodOfMethodSpec(pRec);
+ break;
+ }
+
+ case mdtFieldDef:
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.FindParentOfField(RidFromToken(tkChild), (RID *)ptkParent));
+ RidToToken(*ptkParent, mdtTypeDef);
+ break;
+
+ case mdtParamDef:
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.FindParentOfParam(RidFromToken(tkChild), (RID *)ptkParent));
+ RidToToken(*ptkParent, mdtMethodDef);
+ break;
+
+ case mdtMemberRef:
+ {
+ MemberRefRec *pRec;
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMemberRefRecord(RidFromToken(tkChild), &pRec));
+ *ptkParent = m_LiteWeightStgdb.m_MiniMd.getClassOfMemberRef(pRec);
+ break;
+ }
+
+ case mdtCustomAttribute:
+ {
+ CustomAttributeRec *pRec;
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetCustomAttributeRecord(RidFromToken(tkChild), &pRec));
+ *ptkParent = m_LiteWeightStgdb.m_MiniMd.getParentOfCustomAttribute(pRec);
+ break;
+ }
+
+ case mdtEvent:
+ hr = m_LiteWeightStgdb.m_MiniMd.FindParentOfEventHelper(tkChild, ptkParent);
+ break;
+
+ case mdtProperty:
+ hr = m_LiteWeightStgdb.m_MiniMd.FindParentOfPropertyHelper(tkChild, ptkParent);
+ break;
+
+ default:
+ _ASSERTE(!"NYI: for compressed format!");
+ break;
+ }
+ return hr;
+} // MDInternalRO::GetParentToken
+
+
+
+//*****************************************************************************
+// Get information about a CustomAttribute.
+//*****************************************************************************
+__checkReturn
+HRESULT
+MDInternalRO::GetCustomAttributeProps( // S_OK or error.
+ mdCustomAttribute at, // The attribute.
+ mdToken *ptkType) // Put attribute type here.
+{
+ HRESULT hr;
+ _ASSERTE(TypeFromToken(at) == mdtCustomAttribute);
+
+ // Do a linear search on compressed version as we do not want to
+ // depends on ICR.
+ //
+ CustomAttributeRec *pCustomAttributeRec;
+
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetCustomAttributeRecord(RidFromToken(at), &pCustomAttributeRec));
+ *ptkType = m_LiteWeightStgdb.m_MiniMd.getTypeOfCustomAttribute(pCustomAttributeRec);
+ return S_OK;
+} // MDInternalRO::GetCustomAttributeProps
+
+//*****************************************************************************
+// return custom value
+//*****************************************************************************
+__checkReturn
+HRESULT
+MDInternalRO::GetCustomAttributeAsBlob(
+ mdCustomAttribute cv, // [IN] given custom attribute token
+ void const **ppBlob, // [OUT] return the pointer to internal blob
+ ULONG *pcbSize) // [OUT] return the size of the blob
+{
+ HRESULT hr;
+ _ASSERTE(ppBlob && pcbSize && TypeFromToken(cv) == mdtCustomAttribute);
+
+ CustomAttributeRec *pCustomAttributeRec;
+
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetCustomAttributeRecord(RidFromToken(cv), &pCustomAttributeRec));
+
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getValueOfCustomAttribute(pCustomAttributeRec, (const BYTE **)ppBlob, pcbSize));
+ return S_OK;
+} // MDInternalRO::GetCustomAttributeAsBlob
+
+//*****************************************************************************
+// Helper function to lookup and retrieve a CustomAttribute.
+//*****************************************************************************
+__checkReturn
+HRESULT MDInternalRO::GetCustomAttributeByName( // S_OK or error.
+ mdToken tkObj, // [IN] Object with Custom Attribute.
+ LPCUTF8 szName, // [IN] Name of desired Custom Attribute.
+ __deref_out_bcount(*pcbData) const void **ppData, // [OUT] Put pointer to data here.
+ __out ULONG *pcbData) // [OUT] Put size of data here.
+{
+ return m_LiteWeightStgdb.m_MiniMd.CommonGetCustomAttributeByName(tkObj, szName, ppData, pcbData);
+} // MDInternalRO::GetCustomAttributeByName
+
+
+//*****************************************************************************
+// return the name of a custom attribute
+//*****************************************************************************
+__checkReturn
+HRESULT MDInternalRO::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.
+{
+ _ASSERTE(TypeFromToken(mdAttribute) == mdtCustomAttribute);
+
+ HRESULT hr = m_LiteWeightStgdb.m_MiniMd.CommonGetNameOfCustomAttribute(RidFromToken(mdAttribute), pszNamespace, pszName);
+ return (hr == S_FALSE) ? E_FAIL : hr;
+} // MDInternalRO::GetNameOfCustomAttribute
+
+//*****************************************************************************
+// return scope properties
+//*****************************************************************************
+__checkReturn
+HRESULT
+MDInternalRO::GetScopeProps(
+ LPCSTR *pszName, // [OUT] scope name
+ GUID *pmvid) // [OUT] version id
+{
+ HRESULT hr;
+
+ ModuleRec *pModuleRec;
+
+ // there is only one module record
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetModuleRecord(1, &pModuleRec));
+
+ if (pmvid != NULL)
+ {
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getMvidOfModule(pModuleRec, pmvid));
+ }
+ if (pszName != NULL)
+ {
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfModule(pModuleRec, pszName));
+ }
+
+ return S_OK;
+} // MDInternalRO::GetScopeProps
+
+
+//*****************************************************************************
+// Compare two signatures from the same scope. Varags signatures need to be
+// preprocessed so they only contain the fixed part.
+//*****************************************************************************
+BOOL MDInternalRO::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;
+}
+
+//*****************************************************************************
+// Find a given member in a TypeDef (typically a class).
+//*****************************************************************************
+__checkReturn
+HRESULT MDInternalRO::FindMethodDef( // S_OK or error.
+ mdTypeDef classdef, // The owning class of the member.
+ LPCSTR szName, // Name of the member in utf8.
+ PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of COM+ signature
+ ULONG cbSigBlob, // [IN] count of bytes in the signature blob
+ mdMethodDef *pmethoddef) // Put MemberDef token here.
+{
+
+ return FindMethodDefUsingCompare(classdef,
+ szName,
+ pvSigBlob,
+ cbSigBlob,
+ CompareSignatures,
+ NULL,
+ pmethoddef);
+}
+
+//*****************************************************************************
+// Find a given member in a TypeDef (typically a class).
+//*****************************************************************************
+__checkReturn
+HRESULT MDInternalRO::FindMethodDefUsingCompare( // S_OK or error.
+ mdTypeDef classdef, // The owning class of the member.
+ LPCSTR szName, // Name of the member in utf8.
+ PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of COM+ signature
+ ULONG cbSigBlob, // [IN] count of bytes in the signature blob
+ PSIGCOMPARE SigCompare, // [IN] Signature comparison routine
+ void* pSigArgs, // [IN] Additional arguments passed to signature compare
+ mdMethodDef *pmethoddef) // Put MemberDef token here.
+{
+ HRESULT hr = NOERROR;
+ PCCOR_SIGNATURE pvSigTemp = pvSigBlob;
+ CQuickBytes qbSig;
+
+ _ASSERTE(szName && pmethoddef);
+
+ // initialize the output parameter
+ *pmethoddef = mdMethodDefNil;
+
+ // check to see if this is a vararg signature
+ if ( isCallConv(CorSigUncompressCallingConv(pvSigTemp), IMAGE_CEE_CS_CALLCONV_VARARG) )
+ {
+ // Get the fix part of VARARG signature
+ IfFailGo( _GetFixedSigOfVarArg(pvSigBlob, cbSigBlob, &qbSig, &cbSigBlob) );
+ pvSigBlob = (PCCOR_SIGNATURE) qbSig.Ptr();
+ }
+
+ // Do a linear search on compressed version
+ //
+ RID ridMax;
+ MethodRec *pMethodRec;
+ LPCUTF8 szCurMethodName;
+ void const *pvCurMethodSig;
+ ULONG cbSig;
+ TypeDefRec *pRec;
+ RID ridStart;
+
+ // get the typedef record
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetTypeDefRecord(RidFromToken(classdef), &pRec));
+
+ // get the range of methoddef rids given the classdef
+ ridStart = m_LiteWeightStgdb.m_MiniMd.getMethodListOfTypeDef(pRec);
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.getEndMethodListOfTypeDef(RidFromToken(classdef), &ridMax));
+
+ // loop through each methoddef
+ for (; ridStart < ridMax; ridStart++)
+ {
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetMethodRecord(ridStart, &pMethodRec));
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.getNameOfMethod(pMethodRec, &szCurMethodName));
+ if (strcmp(szCurMethodName, szName) == 0)
+ {
+ // name match, now check the signature if specified.
+ if (cbSigBlob && SigCompare)
+ {
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.getSignatureOfMethod(pMethodRec, (PCCOR_SIGNATURE *)&pvCurMethodSig, &cbSig));
+ // Signature comparison is required
+ // Note that if pvSigBlob is vararg, we already preprocess it so that
+ // it only contains the fix part. Therefore, it still should be an exact
+ // match!!!.
+ //
+ if(SigCompare((PCCOR_SIGNATURE) pvCurMethodSig, cbSig, pvSigBlob, cbSigBlob, pSigArgs) == FALSE)
+ continue;
+ }
+ // Ignore PrivateScope methods.
+ if (IsMdPrivateScope(m_LiteWeightStgdb.m_MiniMd.getFlagsOfMethod(pMethodRec)))
+ continue;
+ // found the match
+ *pmethoddef = TokenFromRid(ridStart, mdtMethodDef);
+ goto ErrExit;
+ }
+ }
+ hr = CLDB_E_RECORD_NOTFOUND;
+
+ErrExit:
+ return hr;
+}
+
+//*****************************************************************************
+// Find a given param of a Method.
+//*****************************************************************************
+__checkReturn
+HRESULT MDInternalRO::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.
+{
+ HRESULT hr;
+ ParamRec *pParamRec;
+ RID ridStart, ridEnd;
+
+ _ASSERTE(TypeFromToken(md) == mdtMethodDef && pparamdef);
+
+ // get the methoddef record
+ MethodRec *pMethodRec;
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodRecord(RidFromToken(md), &pMethodRec));
+
+ // figure out the start rid and end rid of the parameter list of this methoddef
+ ridStart = m_LiteWeightStgdb.m_MiniMd.getParamListOfMethod(pMethodRec);
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getEndParamListOfMethod(RidFromToken(md), &ridEnd));
+
+ // Ensure that the paramList is valid. If the count is negative, the metadata
+ // is corrupted somehow. Thus, return CLDB_E_FILE_CORRUPT.
+ if (ridEnd < ridStart)
+ return CLDB_E_FILE_CORRUPT;
+
+ // loop through each param
+ //<TODO>@consider: parameters are sorted by sequence. Maybe a binary search?
+ //</TODO>
+ for (; ridStart < ridEnd; ridStart++)
+ {
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetParamRecord(ridStart, &pParamRec));
+ if (iSeq == m_LiteWeightStgdb.m_MiniMd.getSequenceOfParam(pParamRec))
+ {
+ // parameter has the sequence number matches what we are looking for
+ *pparamdef = TokenFromRid(ridStart, mdtParamDef);
+ return S_OK;
+ }
+ }
+ return CLDB_E_RECORD_NOTFOUND;
+}
+
+
+
+//*****************************************************************************
+// return a pointer which points to meta data's internal string
+// return the the type name in utf8
+//*****************************************************************************
+__checkReturn
+HRESULT
+MDInternalRO::GetNameOfTypeDef( // return hresult
+ mdTypeDef classdef, // given typedef
+ LPCSTR* pszname, // pointer to an internal UTF8 string
+ LPCSTR* psznamespace) // pointer to the namespace.
+{
+ HRESULT hr;
+
+ if (pszname != NULL)
+ {
+ *pszname = NULL;
+ }
+ if (psznamespace != NULL)
+ {
+ *psznamespace = NULL;
+ }
+
+ if (TypeFromToken(classdef) == mdtTypeDef)
+ {
+ TypeDefRec *pTypeDefRec;
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetTypeDefRecord(RidFromToken(classdef), &pTypeDefRec));
+
+ if (pszname != NULL)
+ {
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfTypeDef(pTypeDefRec, pszname));
+ }
+
+ if (psznamespace != NULL)
+ {
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNamespaceOfTypeDef(pTypeDefRec, psznamespace));
+ }
+ return S_OK;
+ }
+
+ _ASSERTE(!"Invalid argument(s) of GetNameOfTypeDef");
+ return CLDB_E_INTERNALERROR;
+} // MDInternalRO::GetNameOfTypeDef
+
+
+__checkReturn
+HRESULT MDInternalRO::GetIsDualOfTypeDef(// return hresult
+ mdTypeDef classdef, // given classdef
+ ULONG *pDual) // [OUT] return dual flag here.
+{
+ ULONG iFace=0; // Iface type.
+ HRESULT hr; // A result.
+
+ hr = GetIfaceTypeOfTypeDef(classdef, &iFace);
+ if (hr == S_OK)
+ *pDual = (iFace == ifDual);
+ else
+ *pDual = 1;
+
+ return hr;
+} // MDInternalRO::GetIsDualOfTypeDef
+
+__checkReturn
+HRESULT MDInternalRO::GetIfaceTypeOfTypeDef(
+ mdTypeDef classdef, // [IN] given classdef.
+ ULONG *pIface) // [OUT] 0=dual, 1=vtable, 2=dispinterface
+{
+ HRESULT hr; // A result.
+ const BYTE *pVal; // The custom value.
+ ULONG cbVal; // Size of the custom value.
+ ULONG ItfType = DEFAULT_COM_INTERFACE_TYPE; // Set the interface type to the default.
+
+ // If the value is not present, the class is assumed dual.
+ hr = GetCustomAttributeByName(classdef, INTEROP_INTERFACETYPE_TYPE, (const void**)&pVal, &cbVal);
+ if (hr == S_OK)
+ {
+ CustomAttributeParser cap(pVal, cbVal);
+ BYTE u1;
+ if (SUCCEEDED(cap.SkipProlog()) &&
+ SUCCEEDED(cap.GetU1(&u1)))
+ {
+ ItfType = u1;
+ }
+ if (ItfType >= ifLast)
+ ItfType = DEFAULT_COM_INTERFACE_TYPE;
+ }
+
+ // Set the return value.
+ *pIface = ItfType;
+
+ return hr;
+} // MDInternalRO::GetIfaceTypeOfTypeDef
+
+//*****************************************************************************
+// Given a methoddef, return a pointer to methoddef's name
+//*****************************************************************************
+__checkReturn
+HRESULT
+MDInternalRO::GetNameOfMethodDef(
+ mdMethodDef md,
+ LPCSTR *pszMethodName)
+{
+ HRESULT hr;
+ MethodRec *pMethodRec;
+ *pszMethodName = NULL;
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodRecord(RidFromToken(md), &pMethodRec));
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfMethod(pMethodRec, pszMethodName));
+ return S_OK;
+} // MDInternalRO::GetNameOfMethodDef
+
+//*****************************************************************************
+// Given a methoddef, return a pointer to methoddef's signature and methoddef's name
+//*****************************************************************************
+__checkReturn
+HRESULT
+MDInternalRO::GetNameAndSigOfMethodDef(
+ mdMethodDef methoddef, // [IN] given memberdef
+ PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to a blob value of COM+ signature
+ ULONG *pcbSigBlob, // [OUT] count of bytes in the signature blob
+ LPCSTR *pszMethodName)
+{
+ HRESULT hr;
+ // Output parameter should not be NULL
+ _ASSERTE(ppvSigBlob && pcbSigBlob);
+ _ASSERTE(TypeFromToken(methoddef) == mdtMethodDef);
+
+ MethodRec *pMethodRec;
+ *pszMethodName = NULL;
+ *ppvSigBlob = NULL;
+ *pcbSigBlob = 0;
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodRecord(RidFromToken(methoddef), &pMethodRec));
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getSignatureOfMethod(pMethodRec, (PCCOR_SIGNATURE *)ppvSigBlob, pcbSigBlob));
+
+ return GetNameOfMethodDef(methoddef, pszMethodName);
+} // MDInternalRO::GetNameAndSigOfMethodDef
+
+//*****************************************************************************
+// Given a FieldDef, return a pointer to FieldDef's name in UTF8
+//*****************************************************************************
+__checkReturn
+HRESULT
+MDInternalRO::GetNameOfFieldDef( // return hresult
+ mdFieldDef fd, // given field
+ LPCSTR *pszFieldName)
+{
+ HRESULT hr;
+ FieldRec *pFieldRec;
+ *pszFieldName = NULL;
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetFieldRecord(RidFromToken(fd), &pFieldRec));
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfField(pFieldRec, pszFieldName));
+ return S_OK;
+} // MDInternalRO::GetNameOfFieldDef
+
+
+//*****************************************************************************
+// Given a classdef, return the name and namespace of the typeref
+//*****************************************************************************
+__checkReturn
+HRESULT
+MDInternalRO::GetNameOfTypeRef( // return TypeDef's name
+ mdTypeRef classref, // [IN] given typeref
+ LPCSTR *psznamespace, // [OUT] return typeref name
+ LPCSTR *pszname) // [OUT] return typeref namespace
+
+{
+ _ASSERTE(TypeFromToken(classref) == mdtTypeRef);
+
+ HRESULT hr;
+ TypeRefRec *pTypeRefRec;
+
+ *psznamespace = NULL;
+ *pszname = NULL;
+
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetTypeRefRecord(RidFromToken(classref), &pTypeRefRec));
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNamespaceOfTypeRef(pTypeRefRec, psznamespace));
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfTypeRef(pTypeRefRec, pszname));
+ return S_OK;
+}
+
+//*****************************************************************************
+// return the resolutionscope of typeref
+//*****************************************************************************
+__checkReturn
+HRESULT
+MDInternalRO::GetResolutionScopeOfTypeRef(
+ mdTypeRef classref, // given classref
+ mdToken *ptkResolutionScope)
+{
+ _ASSERTE(TypeFromToken(classref) == mdtTypeRef && RidFromToken(classref));
+ HRESULT hr;
+
+ TypeRefRec *pTypeRefRec;
+
+ *ptkResolutionScope = mdTokenNil;
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetTypeRefRecord(RidFromToken(classref), &pTypeRefRec));
+ *ptkResolutionScope = m_LiteWeightStgdb.m_MiniMd.getResolutionScopeOfTypeRef(pTypeRefRec);
+ return S_OK;
+} // MDInternalRO::GetResolutionScopeOfTypeRef
+
+//*****************************************************************************
+// Given a name, find the corresponding TypeRef.
+//*****************************************************************************
+__checkReturn
+HRESULT MDInternalRO::FindTypeRefByName( // 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 = NOERROR;
+
+ _ASSERTE(ptk);
+
+ // initialize the output parameter
+ *ptk = mdTypeRefNil;
+
+ // Treat no namespace as empty string.
+ if (!szNamespace)
+ szNamespace = "";
+
+ // Do a linear search on compressed version as we do not want to
+ // depends on ICR.
+ //
+ ULONG cTypeRefRecs = m_LiteWeightStgdb.m_MiniMd.getCountTypeRefs();
+ TypeRefRec *pTypeRefRec;
+ LPCUTF8 szNamespaceTmp;
+ LPCUTF8 szNameTmp;
+ mdToken tkRes;
+
+ for (ULONG i = 1; i <= cTypeRefRecs; i++)
+ {
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetTypeRefRecord(i, &pTypeRefRec));
+ tkRes = m_LiteWeightStgdb.m_MiniMd.getResolutionScopeOfTypeRef(pTypeRefRec);
+
+ if (IsNilToken(tkRes))
+ {
+ if (!IsNilToken(tkResolutionScope))
+ continue;
+ }
+ else if (tkRes != tkResolutionScope)
+ continue;
+
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.getNamespaceOfTypeRef(pTypeRefRec, &szNamespaceTmp));
+ if (strcmp(szNamespace, szNamespaceTmp))
+ continue;
+
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.getNameOfTypeRef(pTypeRefRec, &szNameTmp));
+ if (!strcmp(szNameTmp, szName))
+ {
+ *ptk = TokenFromRid(i, mdtTypeRef);
+ goto ErrExit;
+ }
+ }
+
+ // cannot find the typedef
+ hr = CLDB_E_RECORD_NOTFOUND;
+ErrExit:
+ return hr;
+}
+
+//*****************************************************************************
+// return flags for a given class
+//*****************************************************************************
+__checkReturn
+HRESULT MDInternalRO::GetTypeDefProps(
+ mdTypeDef td, // given classdef
+ DWORD *pdwAttr, // return flags on class
+ mdToken *ptkExtends) // [OUT] Put base class TypeDef/TypeRef here.
+{
+ HRESULT hr;
+ TypeDefRec *pTypeDefRec;
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetTypeDefRecord(RidFromToken(td), &pTypeDefRec));
+
+ if (ptkExtends)
+ {
+ *ptkExtends = m_LiteWeightStgdb.m_MiniMd.getExtendsOfTypeDef(pTypeDefRec);
+ }
+ if (pdwAttr)
+ {
+ *pdwAttr = m_LiteWeightStgdb.m_MiniMd.getFlagsOfTypeDef(pTypeDefRec);
+ }
+
+ return S_OK;
+}
+
+
+//*****************************************************************************
+// return guid pointer to MetaData internal guid pool given a given class
+//*****************************************************************************
+__checkReturn
+HRESULT MDInternalRO::GetItemGuid( // return hresult
+ mdToken tkObj, // given item
+ CLSID *pGuid)
+{
+
+ HRESULT hr; // A result.
+ const BYTE *pBlob = NULL; // Blob with dispid.
+ ULONG cbBlob; // Length of blob.
+ int ix; // Loop control.
+
+ // Get the GUID, if any.
+ hr = GetCustomAttributeByName(tkObj, INTEROP_GUID_TYPE, (const void**)&pBlob, &cbBlob);
+ if (hr != S_FALSE)
+ {
+ // Should be in format. Total length == 41
+ // <0x0001><0x24>01234567-0123-0123-0123-001122334455<0x0000>
+ if ((cbBlob != 41) || (GET_UNALIGNED_VAL16(pBlob) != 1))
+ IfFailGo(E_INVALIDARG);
+
+ WCHAR wzBlob[40]; // Wide char format of guid.
+ for (ix=1; ix<=36; ++ix)
+ wzBlob[ix] = pBlob[ix+2];
+ wzBlob[0] = '{';
+ wzBlob[37] = '}';
+ wzBlob[38] = 0;
+ hr = IIDFromString(wzBlob, pGuid);
+ }
+ else
+ *pGuid = GUID_NULL;
+
+ErrExit:
+ return hr;
+} // MDInternalRO::GetItemGuid
+
+
+//*****************************************************************************
+// // get enclosing class of NestedClass
+//*****************************************************************************
+__checkReturn
+HRESULT MDInternalRO::GetNestedClassProps( // S_OK or error
+ mdTypeDef tkNestedClass, // [IN] NestedClass token.
+ mdTypeDef *ptkEnclosingClass) // [OUT] EnclosingClass token.
+{
+ HRESULT hr;
+ _ASSERTE(TypeFromToken(tkNestedClass) == mdtTypeDef && ptkEnclosingClass);
+
+ RID rid;
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.FindNestedClassFor(RidFromToken(tkNestedClass), &rid));
+
+ if (InvalidRid(rid))
+ {
+ return CLDB_E_RECORD_NOTFOUND;
+ }
+ else
+ {
+ NestedClassRec *pRecord;
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetNestedClassRecord(rid, &pRecord));
+ *ptkEnclosingClass = m_LiteWeightStgdb.m_MiniMd.getEnclosingClassOfNestedClass(pRecord);
+ return S_OK;
+ }
+}
+
+//*******************************************************************************
+// Get count of Nested classes given the enclosing class.
+//*******************************************************************************
+__checkReturn
+HRESULT
+MDInternalRO::GetCountNestedClasses( // return count of Nested classes.
+ mdTypeDef tkEnclosingClass, // [IN]Enclosing class.
+ ULONG *pcNestedClassesCount)
+{
+ HRESULT hr;
+ ULONG ulCount;
+ ULONG ulRetCount = 0;
+ NestedClassRec *pRecord;
+
+ _ASSERTE(TypeFromToken(tkEnclosingClass) == mdtTypeDef && !IsNilToken(tkEnclosingClass));
+
+ *pcNestedClassesCount = 0;
+
+ ulCount = m_LiteWeightStgdb.m_MiniMd.getCountNestedClasss();
+
+ for (ULONG i = 1; i <= ulCount; i++)
+ {
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetNestedClassRecord(i, &pRecord));
+ if (tkEnclosingClass == m_LiteWeightStgdb.m_MiniMd.getEnclosingClassOfNestedClass(pRecord))
+ ulRetCount++;
+ }
+ *pcNestedClassesCount = ulRetCount;
+ return S_OK;
+} // MDInternalRO::GetCountNestedClasses
+
+//*******************************************************************************
+// Return array of Nested classes given the enclosing class.
+//*******************************************************************************
+__checkReturn
+HRESULT
+MDInternalRO::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)
+{
+ HRESULT hr;
+ ULONG ulCount;
+ ULONG ulRetCount = 0;
+ NestedClassRec *pRecord;
+
+ _ASSERTE(TypeFromToken(tkEnclosingClass) == mdtTypeDef &&
+ !IsNilToken(tkEnclosingClass));
+
+ *pcNestedClasses = 0;
+
+ ulCount = m_LiteWeightStgdb.m_MiniMd.getCountNestedClasss();
+
+ for (ULONG i = 1; i <= ulCount; i++)
+ {
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetNestedClassRecord(i, &pRecord));
+ if (tkEnclosingClass == m_LiteWeightStgdb.m_MiniMd.getEnclosingClassOfNestedClass(pRecord))
+ {
+ if (ovadd_le(ulRetCount, 1, ulNestedClasses)) // ulRetCount is 0 based.
+ rNestedClasses[ulRetCount] = m_LiteWeightStgdb.m_MiniMd.getNestedClassOfNestedClass(pRecord);
+ ulRetCount++;
+ }
+ }
+ *pcNestedClasses = ulRetCount;
+ return S_OK;
+} // MDInternalRO::GetNestedClasses
+
+//*******************************************************************************
+// return the ModuleRef properties
+//*******************************************************************************
+__checkReturn
+HRESULT MDInternalRO::GetModuleRefProps( // return hresult
+ mdModuleRef mur, // [IN] moduleref token
+ LPCSTR *pszName) // [OUT] buffer to fill with the moduleref name
+{
+ _ASSERTE(TypeFromToken(mur) == mdtModuleRef);
+ _ASSERTE(pszName);
+
+ HRESULT hr;
+
+ // Is it a valid token?
+ if (!IsValidToken(mur))
+ {
+ *pszName = NULL; // Not every caller checks returned HRESULT, allow to fail fast in that case
+ return COR_E_BADIMAGEFORMAT; // Invalid Token
+ }
+
+ ModuleRefRec *pModuleRefRec;
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetModuleRefRecord(RidFromToken(mur), &pModuleRefRec));
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfModuleRef(pModuleRefRec, pszName));
+
+ return S_OK;
+}
+
+
+
+//*****************************************************************************
+// Given a scope and a methoddef, return a pointer to methoddef's signature
+//*****************************************************************************
+__checkReturn
+HRESULT
+MDInternalRO::GetSigOfMethodDef(
+ mdMethodDef methoddef, // given a methoddef
+ ULONG *pcbSigBlob, // [OUT] count of bytes in the signature blob
+ PCCOR_SIGNATURE *ppSig)
+{
+ // Output parameter should not be NULL
+ _ASSERTE(pcbSigBlob);
+ _ASSERTE(TypeFromToken(methoddef) == mdtMethodDef);
+
+ HRESULT hr;
+ MethodRec *pMethodRec;
+ *ppSig = NULL;
+ *pcbSigBlob = 0;
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodRecord(RidFromToken(methoddef), &pMethodRec));
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getSignatureOfMethod(pMethodRec, ppSig, pcbSigBlob));
+ return S_OK;
+} // MDInternalRO::GetSigOfMethodDef
+
+
+//*****************************************************************************
+// Given a scope and a fielddef, return a pointer to fielddef's signature
+//*****************************************************************************
+__checkReturn
+HRESULT
+MDInternalRO::GetSigOfFieldDef(
+ mdFieldDef fielddef, // given a methoddef
+ ULONG *pcbSigBlob, // [OUT] count of bytes in the signature blob
+ PCCOR_SIGNATURE *ppSig)
+{
+ _ASSERTE(pcbSigBlob);
+ _ASSERTE(TypeFromToken(fielddef) == mdtFieldDef);
+
+ HRESULT hr;
+ FieldRec *pFieldRec;
+ *ppSig = NULL;
+ *pcbSigBlob = 0;
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetFieldRecord(RidFromToken(fielddef), &pFieldRec));
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getSignatureOfField(pFieldRec, ppSig, pcbSigBlob));
+ return S_OK;
+} // MDInternalRO::GetSigOfFieldDef
+
+//*****************************************************************************
+// Get signature for the token (FieldDef, MethodDef, Signature, or TypeSpec).
+//*****************************************************************************
+__checkReturn
+HRESULT
+MDInternalRO::GetSigFromToken(
+ mdToken tk,
+ ULONG * pcbSig,
+ PCCOR_SIGNATURE * ppSig)
+{
+ HRESULT hr;
+
+ *ppSig = NULL;
+ *pcbSig = 0;
+ switch (TypeFromToken(tk))
+ {
+ case mdtSignature:
+ {
+ StandAloneSigRec * pRec;
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetStandAloneSigRecord(RidFromToken(tk), &pRec));
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getSignatureOfStandAloneSig(pRec, ppSig, pcbSig));
+ return S_OK;
+ }
+ case mdtTypeSpec:
+ {
+ TypeSpecRec * pRec;
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetTypeSpecRecord(RidFromToken(tk), &pRec));
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getSignatureOfTypeSpec(pRec, ppSig, pcbSig));
+ return S_OK;
+ }
+ case mdtMethodDef:
+ {
+ IfFailRet(GetSigOfMethodDef(tk, pcbSig, ppSig));
+ return S_OK;
+ }
+ case mdtFieldDef:
+ {
+ IfFailRet(GetSigOfFieldDef(tk, pcbSig, ppSig));
+ return S_OK;
+ }
+ }
+
+ // not a known token type.
+ *pcbSig = 0;
+ return META_E_INVALID_TOKEN_TYPE;
+} // MDInternalRO::GetSigFromToken
+
+
+//*****************************************************************************
+// Given methoddef, return the flags
+//*****************************************************************************
+__checkReturn
+HRESULT
+MDInternalRO::GetMethodDefProps(
+ mdMethodDef md,
+ DWORD *pdwFlags) // return mdPublic, mdAbstract, etc
+{
+ HRESULT hr;
+ MethodRec *pMethodRec;
+
+ *pdwFlags = (DWORD)-1;
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodRecord(RidFromToken(md), &pMethodRec));
+ *pdwFlags = m_LiteWeightStgdb.m_MiniMd.getFlagsOfMethod(pMethodRec);
+
+ return S_OK;
+} // MDInternalRO::GetMethodDefProps
+
+//*****************************************************************************
+// Given a scope and a methoddef/methodimpl, return RVA and impl flags
+//*****************************************************************************
+__checkReturn
+HRESULT MDInternalRO::GetMethodImplProps(
+ mdMethodDef tk, // [IN] MethodDef
+ ULONG *pulCodeRVA, // [OUT] CodeRVA
+ DWORD *pdwImplFlags) // [OUT] Impl. Flags
+{
+ HRESULT hr;
+ _ASSERTE(TypeFromToken(tk) == mdtMethodDef);
+
+ MethodRec *pMethodRec;
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodRecord(RidFromToken(tk), &pMethodRec));
+
+ if (pulCodeRVA)
+ {
+ *pulCodeRVA = m_LiteWeightStgdb.m_MiniMd.getRVAOfMethod(pMethodRec);
+ }
+
+ if (pdwImplFlags)
+ {
+ *pdwImplFlags = m_LiteWeightStgdb.m_MiniMd.getImplFlagsOfMethod(pMethodRec);
+ }
+
+ return S_OK;
+} // MDInternalRO::GetMethodImplProps
+
+
+//*****************************************************************************
+// return the field RVA
+//*****************************************************************************
+__checkReturn
+HRESULT MDInternalRO::GetFieldRVA(
+ mdToken fd, // [IN] FieldDef
+ ULONG *pulCodeRVA) // [OUT] CodeRVA
+{
+ HRESULT hr;
+ _ASSERTE(TypeFromToken(fd) == mdtFieldDef);
+ _ASSERTE(pulCodeRVA);
+
+ RID iRecord;
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.FindFieldRVAFor(RidFromToken(fd), &iRecord));
+
+ if (InvalidRid(iRecord))
+ {
+ if (pulCodeRVA)
+ *pulCodeRVA = 0;
+ return CLDB_E_RECORD_NOTFOUND;
+ }
+
+ FieldRVARec *pFieldRVARec;
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetFieldRVARecord(iRecord, &pFieldRVARec));
+
+ *pulCodeRVA = m_LiteWeightStgdb.m_MiniMd.getRVAOfFieldRVA(pFieldRVARec);
+ return NOERROR;
+}
+
+//*****************************************************************************
+// Given a fielddef, return the flags. Such as fdPublic, fdStatic, etc
+//*****************************************************************************
+__checkReturn
+HRESULT
+MDInternalRO::GetFieldDefProps(
+ mdFieldDef fd, // given memberdef
+ DWORD *pdwFlags) // [OUT] return fdPublic, fdPrive, etc flags
+{
+ HRESULT hr;
+ _ASSERTE(TypeFromToken(fd) == mdtFieldDef);
+
+ FieldRec *pFieldRec;
+
+ *pdwFlags = (DWORD)-1;
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetFieldRecord(RidFromToken(fd), &pFieldRec));
+ *pdwFlags = m_LiteWeightStgdb.m_MiniMd.getFlagsOfField(pFieldRec);
+
+ return S_OK;
+} // MDInternalRO::GetFieldDefProps
+
+//*****************************************************************************
+// return default value of a token(could be paramdef, fielddef, or property)
+//*****************************************************************************
+__checkReturn
+HRESULT MDInternalRO::GetDefaultValue( // return hresult
+ mdToken tk, // [IN] given FieldDef, ParamDef, or Property
+ MDDefaultValue *pMDDefaultValue) // [OUT] default value
+{
+ _ASSERTE(pMDDefaultValue);
+
+ HRESULT hr;
+ BYTE bType;
+ const VOID *pValue;
+ ULONG cbValue;
+ RID rid;
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.FindConstantFor(RidFromToken(tk), TypeFromToken(tk), &rid));
+ if (InvalidRid(rid))
+ {
+ pMDDefaultValue->m_bType = ELEMENT_TYPE_VOID;
+ return S_OK;
+ }
+ ConstantRec *pConstantRec;
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetConstantRecord(rid, &pConstantRec));
+
+ // get the type of constant value
+ bType = m_LiteWeightStgdb.m_MiniMd.getTypeOfConstant(pConstantRec);
+
+ // get the value blob
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getValueOfConstant(pConstantRec, reinterpret_cast<const BYTE **>(&pValue), &cbValue));
+ // convert it to our internal default value representation
+ hr = _FillMDDefaultValue(bType, pValue, cbValue, pMDDefaultValue);
+ return hr;
+} // MDInternalRO::GetDefaultValue
+
+//*****************************************************************************
+// Given a scope and a methoddef/fielddef, return the dispid
+//*****************************************************************************
+__checkReturn
+HRESULT MDInternalRO::GetDispIdOfMemberDef( // return hresult
+ mdToken tk, // given methoddef or fielddef
+ ULONG *pDispid) // Put the dispid here.
+{
+#ifdef FEATURE_COMINTEROP
+ HRESULT hr; // A result.
+ const BYTE *pBlob; // Blob with dispid.
+ ULONG cbBlob; // Length of blob.
+ UINT32 dispid; // temporary for dispid.
+
+ // Get the DISPID, if any.
+ _ASSERTE(pDispid);
+
+ *pDispid = DISPID_UNKNOWN;
+ hr = GetCustomAttributeByName(tk, INTEROP_DISPID_TYPE, (const void**)&pBlob, &cbBlob);
+ if (hr == S_OK)
+ {
+ CustomAttributeParser cap(pBlob, cbBlob);
+ IfFailGo(cap.SkipProlog());
+ IfFailGo(cap.GetU4(&dispid));
+ *pDispid = dispid;
+ }
+
+ErrExit:
+ return hr;
+#else // FEATURE_COMINTEROP
+ _ASSERTE(false);
+ return E_NOTIMPL;
+#endif // FEATURE_COMINTEROP
+} // MDInternalRO::GetDispIdOfMemberDef
+
+//*****************************************************************************
+// Given interfaceimpl, return the TypeRef/TypeDef and flags
+//*****************************************************************************
+__checkReturn
+HRESULT
+MDInternalRO::GetTypeOfInterfaceImpl( // return hresult
+ mdInterfaceImpl iiImpl, // given a interfaceimpl
+ mdToken *ptkType)
+{
+ HRESULT hr;
+ _ASSERTE(TypeFromToken(iiImpl) == mdtInterfaceImpl);
+
+ *ptkType = mdTypeDefNil;
+
+ InterfaceImplRec *pIIRec;
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetInterfaceImplRecord(RidFromToken(iiImpl), &pIIRec));
+ *ptkType = m_LiteWeightStgdb.m_MiniMd.getInterfaceOfInterfaceImpl(pIIRec);
+ return S_OK;
+} // MDInternalRO::GetTypeOfInterfaceImpl
+
+//*****************************************************************************
+// This routine gets the properties for the given MethodSpec token.
+//*****************************************************************************
+__checkReturn
+HRESULT MDInternalRO::GetMethodSpecProps( // S_OK or error.
+ 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 = NOERROR;
+ MethodSpecRec *pMethodSpecRec;
+
+ LOG((LOGMD, "MD RegMeta::GetMethodSpecProps(0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
+ mi, tkParent, ppvSigBlob, pcbSigBlob));
+
+ _ASSERTE(TypeFromToken(mi) == mdtMethodSpec);
+
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodSpecRecord(RidFromToken(mi), &pMethodSpecRec));
+
+ if (tkParent)
+ *tkParent = m_LiteWeightStgdb.m_MiniMd.getMethodOfMethodSpec(pMethodSpecRec);
+
+ if (ppvSigBlob || pcbSigBlob)
+ {
+ // caller wants signature information
+ PCCOR_SIGNATURE pvSigTmp;
+ ULONG cbSig;
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getInstantiationOfMethodSpec(pMethodSpecRec, &pvSigTmp, &cbSig));
+ if ( ppvSigBlob )
+ *ppvSigBlob = pvSigTmp;
+ if ( pcbSigBlob)
+ *pcbSigBlob = cbSig;
+ }
+
+
+ return hr;
+} // MDInternalRO::GetMethodSpecProps
+
+
+
+//*****************************************************************************
+// Given a classname, return the typedef
+//*****************************************************************************
+__checkReturn
+HRESULT
+MDInternalRO::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_LiteWeightStgdb.m_MiniMd.getCountTypeDefs();
+ TypeDefRec * pTypeDefRec;
+ LPCUTF8 szName;
+ LPCUTF8 szNamespace;
+ DWORD dwFlags;
+
+ // Get TypeDef of the tkEnclosingClass passed in
+ if (TypeFromToken(tkEnclosingClass) == mdtTypeRef)
+ {
+ TypeRefRec * pTypeRefRec;
+ mdToken tkResolutionScope;
+
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetTypeRefRecord(RidFromToken(tkEnclosingClass), &pTypeRefRec));
+ tkResolutionScope = m_LiteWeightStgdb.m_MiniMd.getResolutionScopeOfTypeRef(pTypeRefRec);
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNamespaceOfTypeRef(pTypeRefRec, &szNamespace));
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfTypeRef(pTypeRefRec, &szName));
+
+ // Update tkEnclosingClass to TypeDef
+ IfFailRet(FindTypeDef(
+ szNamespace,
+ szName,
+ (TypeFromToken(tkResolutionScope) == mdtTypeRef) ? tkResolutionScope : mdTokenNil,
+ &tkEnclosingClass));
+ _ASSERTE(TypeFromToken(tkEnclosingClass) == mdtTypeDef);
+ }
+
+ // Search for the TypeDef
+ for (ULONG i = 1; i <= cTypeDefRecs; i++)
+ {
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetTypeDefRecord(i, &pTypeDefRec));
+
+ dwFlags = m_LiteWeightStgdb.m_MiniMd.getFlagsOfTypeDef(pTypeDefRec);
+
+ 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);
+
+ RID iNestedClassRec;
+ NestedClassRec * pNestedClassRec;
+ mdTypeDef tkEnclosingClassTmp;
+
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.FindNestedClassFor(i, &iNestedClassRec));
+ if (InvalidRid(iNestedClassRec))
+ continue;
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetNestedClassRecord(iNestedClassRec, &pNestedClassRec));
+ tkEnclosingClassTmp = m_LiteWeightStgdb.m_MiniMd.getEnclosingClassOfNestedClass(pNestedClassRec);
+ if (tkEnclosingClass != tkEnclosingClassTmp)
+ continue;
+ }
+
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfTypeDef(pTypeDefRec, &szName));
+ if (strcmp(szTypeDefName, szName) == 0)
+ {
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNamespaceOfTypeDef(pTypeDefRec, &szNamespace));
+ if (strcmp(szTypeDefNamespace, szNamespace) == 0)
+ {
+ *ptkTypeDef = TokenFromRid(i, mdtTypeDef);
+ return S_OK;
+ }
+ }
+ }
+ // Cannot find the TypeDef by name
+ return CLDB_E_RECORD_NOTFOUND;
+} // MDInternalRO::FindTypeDef
+
+//*****************************************************************************
+// Given a memberref, return a pointer to memberref's name and signature
+//*****************************************************************************
+// Warning: Even when the return value is ok, *ppvSigBlob could be NULL if
+// the metadata is corrupted! (e.g. if CPackedLen::GetLength returned -1).
+// TODO: consider returning a HRESULT to make errors evident to the caller.
+//*****************************************************************************
+__checkReturn
+HRESULT
+MDInternalRO::GetNameAndSigOfMemberRef( // meberref's name
+ mdMemberRef memberref, // given a memberref
+ PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to a blob value of COM+ signature
+ ULONG *pcbSigBlob, // [OUT] count of bytes in the signature blob
+ LPCSTR *pszMemberRefName)
+{
+ _ASSERTE(TypeFromToken(memberref) == mdtMemberRef);
+
+ HRESULT hr;
+ MemberRefRec *pMemberRefRec;
+ *pszMemberRefName = NULL;
+ if (ppvSigBlob != NULL)
+ {
+ _ASSERTE(pcbSigBlob != NULL);
+ *ppvSigBlob = NULL;
+ *pcbSigBlob = 0;
+ }
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMemberRefRecord(RidFromToken(memberref), &pMemberRefRec));
+ if (ppvSigBlob != NULL)
+ {
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getSignatureOfMemberRef(pMemberRefRec, ppvSigBlob, pcbSigBlob));
+ }
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfMemberRef(pMemberRefRec, pszMemberRefName));
+ return S_OK;
+} // MDInternalRO::GetNameAndSigOfMemberRef
+
+//*****************************************************************************
+// Given a memberref, return parent token. It can be a TypeRef, ModuleRef, or a MethodDef
+//*****************************************************************************
+__checkReturn
+HRESULT
+MDInternalRO::GetParentOfMemberRef(
+ mdMemberRef memberref, // given a typedef
+ mdToken *ptkParent) // return the parent token
+{
+ HRESULT hr;
+ _ASSERTE(TypeFromToken(memberref) == mdtMemberRef);
+
+ MemberRefRec *pMemberRefRec;
+
+ *ptkParent = mdTokenNil;
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMemberRefRecord(RidFromToken(memberref), &pMemberRefRec));
+ *ptkParent = m_LiteWeightStgdb.m_MiniMd.getClassOfMemberRef(pMemberRefRec);
+
+ return S_OK;
+} // MDInternalRO::GetParentOfMemberRef
+
+//*****************************************************************************
+// return properties of a paramdef
+//*****************************************************************************/
+__checkReturn
+HRESULT
+MDInternalRO::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
+{
+ _ASSERTE(TypeFromToken(paramdef) == mdtParamDef);
+ HRESULT hr;
+ ParamRec *pParamRec;
+
+ *pszName = NULL;
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetParamRecord(RidFromToken(paramdef), &pParamRec));
+ if (pdwAttr != NULL)
+ {
+ *pdwAttr = m_LiteWeightStgdb.m_MiniMd.getFlagsOfParam(pParamRec);
+ }
+ if (pusSequence != NULL)
+ {
+ *pusSequence = m_LiteWeightStgdb.m_MiniMd.getSequenceOfParam(pParamRec);
+ }
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfParam(pParamRec, pszName));
+
+ return S_OK;
+} // MDInternalRO::GetParamDefProps
+
+//*****************************************************************************
+// Get property info for the method.
+//*****************************************************************************
+int MDInternalRO::CMethodSemanticsMapSearcher::Compare(
+ const CMethodSemanticsMap *psFirst,
+ const CMethodSemanticsMap *psSecond)
+{
+ if (psFirst->m_mdMethod < psSecond->m_mdMethod)
+ return -1;
+ if (psFirst->m_mdMethod > psSecond->m_mdMethod)
+ return 1;
+ return 0;
+} // MDInternalRO::CMethodSemanticsMapSearcher::Compare
+
+#ifndef DACCESS_COMPILE
+int MDInternalRO::CMethodSemanticsMapSorter::Compare(
+ CMethodSemanticsMap *psFirst,
+ CMethodSemanticsMap *psSecond)
+{
+ if (psFirst->m_mdMethod < psSecond->m_mdMethod)
+ return -1;
+ if (psFirst->m_mdMethod > psSecond->m_mdMethod)
+ return 1;
+ return 0;
+} // MDInternalRO::CMethodSemanticsMapSorter::Compare
+
+__checkReturn
+HRESULT MDInternalRO::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
+{
+ HRESULT hr;
+ MethodSemanticsRec *pSemantics; // A MethodSemantics record.
+ MethodSemanticsRec *pFound=0; // A MethodSemantics record that is a property for the desired function.
+ RID ridCur; // loop control.
+ RID ridMax; // Count of entries in table.
+ USHORT usSemantics = 0; // A method's semantics.
+ mdToken tk; // A method def.
+
+ ridMax = m_LiteWeightStgdb.m_MiniMd.getCountMethodSemantics();
+
+ // Lazy initialization of m_pMethodSemanticsMap
+ if ((ridMax > 10) && (m_pMethodSemanticsMap == NULL))
+ {
+ NewHolder<CMethodSemanticsMap> pMethodSemanticsMap = new (nothrow) CMethodSemanticsMap[ridMax];
+ if (pMethodSemanticsMap != NULL)
+ {
+ // Fill the table in MethodSemantics order.
+ for (ridCur = 1; ridCur <= ridMax; ridCur++)
+ {
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodSemanticsRecord(ridCur, &pSemantics));
+ tk = m_LiteWeightStgdb.m_MiniMd.getMethodOfMethodSemantics(pSemantics);
+ pMethodSemanticsMap[ridCur-1].m_mdMethod = tk;
+ pMethodSemanticsMap[ridCur-1].m_ridSemantics = ridCur;
+ }
+ // Sort to MethodDef order.
+ CMethodSemanticsMapSorter sorter(pMethodSemanticsMap, ridMax);
+ sorter.Sort();
+
+ if (InterlockedCompareExchangeT<CMethodSemanticsMap *>(
+ &m_pMethodSemanticsMap, pMethodSemanticsMap, NULL) == NULL)
+ { // The exchange did happen, supress of the allocated map
+ pMethodSemanticsMap.SuppressRelease();
+ }
+ }
+ }
+
+ // Use m_pMethodSemanticsMap if it has been built.
+ if (m_pMethodSemanticsMap != NULL)
+ {
+ CMethodSemanticsMapSearcher searcher(m_pMethodSemanticsMap, ridMax);
+ CMethodSemanticsMap target;
+ const CMethodSemanticsMap * pMatchedMethod;
+ target.m_mdMethod = md;
+ pMatchedMethod = searcher.Find(&target);
+
+ // Was there at least one match?
+ if (pMatchedMethod != NULL)
+ {
+ _ASSERTE(pMatchedMethod >= m_pMethodSemanticsMap);
+ _ASSERTE(pMatchedMethod < m_pMethodSemanticsMap+ridMax);
+ _ASSERTE(pMatchedMethod->m_mdMethod == md);
+
+ ridCur = pMatchedMethod->m_ridSemantics;
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodSemanticsRecord(ridCur, &pSemantics));
+ usSemantics = m_LiteWeightStgdb.m_MiniMd.getSemanticOfMethodSemantics(pSemantics);
+
+ // If the semantics record is a getter or setter for the method, that's what we want.
+ if (usSemantics == msGetter || usSemantics == msSetter)
+ pFound = pSemantics;
+ else
+ { // The semantics record was neither getter or setter. Because there can be
+ // multiple semantics records for a given method, look for other semantics
+ // records that match this record.
+ const CMethodSemanticsMap *pScan;
+ const CMethodSemanticsMap *pLo=m_pMethodSemanticsMap;
+ const CMethodSemanticsMap *pHi=pLo+ridMax-1;
+ for (pScan = pMatchedMethod-1; pScan >= pLo; --pScan)
+ {
+ if (pScan->m_mdMethod == md)
+ {
+ ridCur = pScan->m_ridSemantics;
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodSemanticsRecord(ridCur, &pSemantics));
+ usSemantics = m_LiteWeightStgdb.m_MiniMd.getSemanticOfMethodSemantics(pSemantics);
+
+ if (usSemantics == msGetter || usSemantics == msSetter)
+ {
+ pFound = pSemantics;
+ break;
+ }
+ }
+ else
+ break;
+ }
+
+ if (pFound == 0)
+ { // Not found looking down, try looking up.
+ for (pScan = pMatchedMethod+1; pScan <= pHi; ++pScan)
+ {
+ if (pScan->m_mdMethod == md)
+ {
+ ridCur = pScan->m_ridSemantics;
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodSemanticsRecord(ridCur, &pSemantics));
+ usSemantics = m_LiteWeightStgdb.m_MiniMd.getSemanticOfMethodSemantics(pSemantics);
+
+ if (usSemantics == msGetter || usSemantics == msSetter)
+ {
+ pFound = pSemantics;
+ break;
+ }
+ }
+ else
+ break;
+ }
+
+ }
+ }
+ }
+ }
+ else
+ { // Scan entire table.
+ for (ridCur = 1; ridCur <= ridMax; ridCur++)
+ {
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodSemanticsRecord(ridCur, &pSemantics));
+ if (md == m_LiteWeightStgdb.m_MiniMd.getMethodOfMethodSemantics(pSemantics))
+ { // The method matched, is this a property?
+ usSemantics = m_LiteWeightStgdb.m_MiniMd.getSemanticOfMethodSemantics(pSemantics);
+ if (usSemantics == msGetter || usSemantics == msSetter)
+ { // found a match.
+ pFound = pSemantics;
+ break;
+ }
+ }
+ }
+ }
+
+ // Did the search find anything?
+ if (pFound)
+ { // found a match. Fill out the output parameters
+ PropertyRec *pProperty;
+ mdProperty prop;
+ prop = m_LiteWeightStgdb.m_MiniMd.getAssociationOfMethodSemantics(pFound);
+
+ if (ppd)
+ *ppd = prop;
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetPropertyRecord(RidFromToken(prop), &pProperty));
+
+ if (pName != NULL)
+ {
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfProperty(pProperty, pName));
+ }
+
+ if (pSemantic)
+ *pSemantic = usSemantics;
+ return S_OK;
+ }
+ return S_FALSE;
+} // MDInternalRO::GetPropertyInfoForMethodDef
+#endif //!DACCESS_COMPILE
+
+//*****************************************************************************
+// return the pack size of a class
+//*****************************************************************************
+__checkReturn
+HRESULT MDInternalRO::GetClassPackSize(
+ mdTypeDef td, // [IN] give typedef
+ DWORD *pdwPackSize) // [OUT]
+{
+ HRESULT hr = NOERROR;
+
+ _ASSERTE(TypeFromToken(td) == mdtTypeDef && pdwPackSize);
+
+ ClassLayoutRec *pRec;
+ RID ridClassLayout;
+
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.FindClassLayoutFor(RidFromToken(td), &ridClassLayout));
+ if (InvalidRid(ridClassLayout))
+ {
+ hr = CLDB_E_RECORD_NOTFOUND;
+ goto ErrExit;
+ }
+
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetClassLayoutRecord(RidFromToken(ridClassLayout), &pRec));
+ *pdwPackSize = m_LiteWeightStgdb.m_MiniMd.getPackingSizeOfClassLayout(pRec);
+ErrExit:
+ return hr;
+} // MDInternalRO::GetClassPackSize
+
+
+//*****************************************************************************
+// return the total size of a value class
+//*****************************************************************************
+__checkReturn
+HRESULT MDInternalRO::GetClassTotalSize( // return error if a class does not have total size info
+ mdTypeDef td, // [IN] give typedef
+ ULONG *pulClassSize) // [OUT] return the total size of the class
+{
+ _ASSERTE(TypeFromToken(td) == mdtTypeDef && pulClassSize);
+
+ ClassLayoutRec *pRec;
+ HRESULT hr = NOERROR;
+ RID ridClassLayout;
+
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.FindClassLayoutFor(RidFromToken(td), &ridClassLayout));
+ if (InvalidRid(ridClassLayout))
+ {
+ hr = CLDB_E_RECORD_NOTFOUND;
+ goto ErrExit;
+ }
+
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetClassLayoutRecord(RidFromToken(ridClassLayout), &pRec));
+ *pulClassSize = m_LiteWeightStgdb.m_MiniMd.getClassSizeOfClassLayout(pRec);
+ErrExit:
+ return hr;
+} // MDInternalRO::GetClassTotalSize
+
+
+//*****************************************************************************
+// init the layout enumerator of a class
+//*****************************************************************************
+__checkReturn
+HRESULT MDInternalRO::GetClassLayoutInit(
+ mdTypeDef td, // [IN] give typedef
+ MD_CLASS_LAYOUT *pmdLayout) // [OUT] set up the status of query here
+{
+ HRESULT hr = NOERROR;
+ _ASSERTE(TypeFromToken(td) == mdtTypeDef);
+
+ // initialize the output parameter
+ _ASSERTE(pmdLayout);
+ memset(pmdLayout, 0, sizeof(MD_CLASS_LAYOUT));
+
+ TypeDefRec *pTypeDefRec;
+
+ // record for this typedef in TypeDef Table
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetTypeDefRecord(RidFromToken(td), &pTypeDefRec));
+
+ // find the starting and end field for this typedef
+ pmdLayout->m_ridFieldCur = m_LiteWeightStgdb.m_MiniMd.getFieldListOfTypeDef(pTypeDefRec);
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getEndFieldListOfTypeDef(RidFromToken(td), &(pmdLayout->m_ridFieldEnd)));
+ return hr;
+} // MDInternalRO::GetClassLayoutInit
+
+
+//*****************************************************************************
+// return the field offset for a given field
+//*****************************************************************************
+__checkReturn
+HRESULT MDInternalRO::GetFieldOffset(
+ mdFieldDef fd, // [IN] fielddef
+ ULONG *pulOffset) // [OUT] FieldOffset
+{
+ HRESULT hr = S_OK;
+ FieldLayoutRec *pRec;
+
+ _ASSERTE(pulOffset);
+
+ RID iLayout;
+
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.FindFieldLayoutFor(RidFromToken(fd), &iLayout));
+
+ if (InvalidRid(iLayout))
+ {
+ hr = S_FALSE;
+ goto ErrExit;
+ }
+
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetFieldLayoutRecord(iLayout, &pRec));
+ *pulOffset = m_LiteWeightStgdb.m_MiniMd.getOffSetOfFieldLayout(pRec);
+ _ASSERTE(*pulOffset != ULONG_MAX);
+
+ErrExit:
+ return hr;
+}
+
+
+//*****************************************************************************
+// enum the next the field layout
+//*****************************************************************************
+__checkReturn
+HRESULT MDInternalRO::GetClassLayoutNext(
+ MD_CLASS_LAYOUT *pLayout, // [IN|OUT] set up the status of query here
+ mdFieldDef *pfd, // [OUT] field def
+ ULONG *pulOffset) // [OUT] field offset or sequence
+{
+ HRESULT hr = S_OK;
+
+ _ASSERTE(pfd && pulOffset && pLayout);
+
+ RID iLayout2;
+ FieldLayoutRec *pRec;
+
+ // Make sure no one is messing with pLayout->m_ridFieldLayoutCur, since this doesn't
+ // mean anything if we are using FieldLayout table.
+ while (pLayout->m_ridFieldCur < pLayout->m_ridFieldEnd)
+ {
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.FindFieldLayoutFor(pLayout->m_ridFieldCur, &iLayout2));
+ pLayout->m_ridFieldCur++;
+ if (!InvalidRid(iLayout2))
+ {
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetFieldLayoutRecord(iLayout2, &pRec));
+ *pulOffset = m_LiteWeightStgdb.m_MiniMd.getOffSetOfFieldLayout(pRec);
+ _ASSERTE(*pulOffset != ULONG_MAX);
+ *pfd = TokenFromRid(pLayout->m_ridFieldCur - 1, mdtFieldDef);
+ goto ErrExit;
+ }
+ }
+
+ *pfd = mdFieldDefNil;
+ hr = S_FALSE;
+
+ // fall through
+
+ErrExit:
+ return hr;
+} // MDInternalRO::GetClassLayoutNext
+
+
+//*****************************************************************************
+// return the field's native type signature
+//*****************************************************************************
+__checkReturn
+HRESULT MDInternalRO::GetFieldMarshal( // return error if no native type associate with the token
+ mdToken tk, // [IN] given fielddef or paramdef
+ PCCOR_SIGNATURE *pSigNativeType, // [OUT] the native type signature
+ ULONG *pcbNativeType) // [OUT] the count of bytes of *ppvNativeType
+{
+ // output parameters have to be supplied
+ _ASSERTE(pcbNativeType);
+
+ RID rid;
+ FieldMarshalRec *pFieldMarshalRec;
+ HRESULT hr = NOERROR;
+
+ // find the row containing the marshal definition for tk
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.FindFieldMarshalFor(RidFromToken(tk), TypeFromToken(tk), &rid));
+ if (InvalidRid(rid))
+ {
+ *pSigNativeType = NULL;
+ *pcbNativeType = 0;
+ hr = CLDB_E_RECORD_NOTFOUND;
+ goto ErrExit;
+ }
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetFieldMarshalRecord(rid, &pFieldMarshalRec));
+
+ // get the native type
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.getNativeTypeOfFieldMarshal(pFieldMarshalRec, pSigNativeType, pcbNativeType));
+ErrExit:
+ return hr;
+} // MDInternalRO::GetFieldMarshal
+
+
+
+//*****************************************
+// property APIs
+//*****************************************
+
+//*****************************************************************************
+// Find property by name
+//*****************************************************************************
+__checkReturn
+HRESULT MDInternalRO::FindProperty(
+ mdTypeDef td, // [IN] given a typdef
+ LPCSTR szPropName, // [IN] property name
+ mdProperty *pProp) // [OUT] return property token
+{
+ HRESULT hr = NOERROR;
+
+ // output parameters have to be supplied
+ _ASSERTE(TypeFromToken(td) == mdtTypeDef && pProp);
+
+ PropertyMapRec *pRec;
+ PropertyRec *pProperty;
+ RID ridPropertyMap;
+ RID ridCur;
+ RID ridEnd;
+ LPCUTF8 szName;
+
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.FindPropertyMapFor(RidFromToken(td), &ridPropertyMap));
+ if (InvalidRid(ridPropertyMap))
+ {
+ // not found!
+ hr = CLDB_E_RECORD_NOTFOUND;
+ goto ErrExit;
+ }
+
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetPropertyMapRecord(ridPropertyMap, &pRec));
+
+ // get the starting/ending rid of properties of this typedef
+ ridCur = m_LiteWeightStgdb.m_MiniMd.getPropertyListOfPropertyMap(pRec);
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.getEndPropertyListOfPropertyMap(ridPropertyMap, &ridEnd));
+
+ for (; ridCur < ridEnd; ridCur ++)
+ {
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetPropertyRecord(ridCur, &pProperty));
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.getNameOfProperty(pProperty, &szName));
+ if (strcmp(szName, szPropName) ==0)
+ {
+ // Found the match. Set the output parameter and we are done.
+ *pProp = TokenFromRid(ridCur, mdtProperty);
+ goto ErrExit;
+ }
+ }
+
+ // not found
+ hr = CLDB_E_RECORD_NOTFOUND;
+ErrExit:
+ return hr;
+
+} // MDInternalRO::FindProperty
+
+
+
+//*****************************************************************************
+// return the properties of a property
+//*****************************************************************************
+__checkReturn
+HRESULT MDInternalRO::GetPropertyProps(
+ mdProperty prop, // [IN] property token
+ LPCSTR *pszProperty, // [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
+{
+ // output parameters have to be supplied
+ _ASSERTE(TypeFromToken(prop) == mdtProperty);
+
+ HRESULT hr;
+
+ PropertyRec *pProperty;
+ ULONG cbSig;
+
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetPropertyRecord(RidFromToken(prop), &pProperty));
+
+ // get name of the property
+ if (pszProperty != NULL)
+ {
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfProperty(pProperty, pszProperty));
+ }
+
+ // get the flags of property
+ if (pdwPropFlags)
+ *pdwPropFlags = m_LiteWeightStgdb.m_MiniMd.getPropFlagsOfProperty(pProperty);
+
+ // get the type of the property
+ if (ppvSig != NULL)
+ {
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getTypeOfProperty(pProperty, ppvSig, &cbSig));
+ if (pcbSig != NULL)
+ {
+ *pcbSig = cbSig;
+ }
+ }
+
+ return S_OK;
+} // MDInternalRO::GetPropertyProps
+
+
+//**********************************
+//
+// Event APIs
+//
+//**********************************
+
+//*****************************************************************************
+// return an event by given the name
+//*****************************************************************************
+__checkReturn
+HRESULT MDInternalRO::FindEvent(
+ mdTypeDef td, // [IN] given a typdef
+ LPCSTR szEventName, // [IN] event name
+ mdEvent *pEvent) // [OUT] return event token
+{
+ HRESULT hr = NOERROR;
+
+ // output parameters have to be supplied
+ _ASSERTE(TypeFromToken(td) == mdtTypeDef && pEvent);
+
+ EventMapRec *pRec;
+ EventRec *pEventRec;
+ RID ridEventMap;
+ RID ridCur;
+ RID ridEnd;
+ LPCUTF8 szName;
+
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.FindEventMapFor(RidFromToken(td), &ridEventMap));
+ if (InvalidRid(ridEventMap))
+ {
+ // not found!
+ hr = CLDB_E_RECORD_NOTFOUND;
+ goto ErrExit;
+ }
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetEventMapRecord(ridEventMap, &pRec));
+
+ // get the starting/ending rid of properties of this typedef
+ ridCur = m_LiteWeightStgdb.m_MiniMd.getEventListOfEventMap(pRec);
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.getEndEventListOfEventMap(ridEventMap, &ridEnd));
+
+ for (; ridCur < ridEnd; ridCur ++)
+ {
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetEventRecord(ridCur, &pEventRec));
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.getNameOfEvent(pEventRec, &szName));
+ if (strcmp(szName, szEventName) ==0)
+ {
+ // Found the match. Set the output parameter and we are done.
+ *pEvent = TokenFromRid(ridCur, mdtEvent);
+ goto ErrExit;
+ }
+ }
+
+ // not found
+ hr = CLDB_E_RECORD_NOTFOUND;
+ErrExit:
+ return hr;
+} // MDInternalRO::FindEvent
+
+
+//*****************************************************************************
+// return the properties of an event
+//*****************************************************************************
+__checkReturn
+HRESULT MDInternalRO::GetEventProps( // S_OK, S_FALSE, or error.
+ mdEvent ev, // [IN] event token
+ LPCSTR *pszEvent, // [OUT] Event name
+ DWORD *pdwEventFlags, // [OUT] Event flags.
+ mdToken *ptkEventType) // [OUT] EventType class
+{
+ // output parameters have to be supplied
+ _ASSERTE(TypeFromToken(ev) == mdtEvent);
+
+ HRESULT hr;
+ EventRec *pEvent;
+
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetEventRecord(RidFromToken(ev), &pEvent));
+ if (pszEvent != NULL)
+ {
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfEvent(pEvent, pszEvent));
+ }
+ if (pdwEventFlags)
+ *pdwEventFlags = m_LiteWeightStgdb.m_MiniMd.getEventFlagsOfEvent(pEvent);
+ if (ptkEventType)
+ *ptkEventType = m_LiteWeightStgdb.m_MiniMd.getEventTypeOfEvent(pEvent);
+
+ return S_OK;
+} // MDInternalRO::GetEventProps
+
+//*****************************************************************************
+// return the properties of a generic param
+//*****************************************************************************
+__checkReturn
+HRESULT MDInternalRO::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
+{
+ HRESULT hr = NOERROR;
+ GenericParamRec * pGenericParamRec = NULL;
+
+ // See if this version of the metadata can do Generics
+ if (!m_LiteWeightStgdb.m_MiniMd.SupportsGenerics())
+ IfFailGo(CLDB_E_INCOMPATIBLE);
+
+ _ASSERTE(TypeFromToken(rd) == mdtGenericParam);
+ if (TypeFromToken(rd) != mdtGenericParam)
+ {
+ IfFailGo(CLDB_E_FILE_CORRUPT);
+ }
+
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetGenericParamRecord(RidFromToken(rd), &pGenericParamRec));
+
+ if (pulSequence)
+ *pulSequence = m_LiteWeightStgdb.m_MiniMd.getNumberOfGenericParam(pGenericParamRec);
+ if (pdwAttr)
+ *pdwAttr = m_LiteWeightStgdb.m_MiniMd.getFlagsOfGenericParam(pGenericParamRec);
+ if (ptOwner)
+ *ptOwner = m_LiteWeightStgdb.m_MiniMd.getOwnerOfGenericParam(pGenericParamRec);
+ if (szName != NULL)
+ {
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.getNameOfGenericParam(pGenericParamRec, szName));
+ }
+ErrExit:
+ return hr;
+} // MDInternalRO::GetGenericParamProps
+
+//*****************************************************************************
+// This routine gets the properties for the given GenericParamConstraint token.
+//*****************************************************************************
+__checkReturn
+HRESULT MDInternalRO::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
+{
+ HRESULT hr = NOERROR;
+ GenericParamConstraintRec *pGPCRec;
+ RID ridRD = RidFromToken(rd);
+
+ // See if this version of the metadata can do Generics
+ if (!m_LiteWeightStgdb.m_MiniMd.SupportsGenerics())
+ IfFailGo(CLDB_E_INCOMPATIBLE);
+
+ if((TypeFromToken(rd) == mdtGenericParamConstraint) && (ridRD != 0))
+ {
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetGenericParamConstraintRecord(ridRD, &pGPCRec));
+
+ if (ptGenericParam)
+ *ptGenericParam = TokenFromRid(m_LiteWeightStgdb.m_MiniMd.getOwnerOfGenericParamConstraint(pGPCRec),mdtGenericParam);
+ if (ptkConstraintType)
+ *ptkConstraintType = m_LiteWeightStgdb.m_MiniMd.getConstraintOfGenericParamConstraint(pGPCRec);
+ }
+ else
+ hr = META_E_BAD_INPUT_PARAMETER;
+
+ErrExit:
+ return hr;
+} // MDInternalRO::GetGenericParamConstraintProps
+
+//*****************************************************************************
+// Find methoddef of a particular associate with a property or an event
+//*****************************************************************************
+__checkReturn
+HRESULT MDInternalRO::FindAssociate(
+ mdToken evprop, // [IN] given a property or event token
+ DWORD dwSemantics, // [IN] given a associate semantics(setter, getter, testdefault, reset)
+ mdMethodDef *pmd) // [OUT] return method def token
+{
+ HRESULT hr = NOERROR;
+
+ // output parameters have to be supplied
+ _ASSERTE(pmd);
+ _ASSERTE(TypeFromToken(evprop) == mdtEvent || TypeFromToken(evprop) == mdtProperty);
+
+ MethodSemanticsRec *pSemantics;
+ RID ridCur;
+ RID ridEnd;
+
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.getAssociatesForToken(evprop, &ridEnd, &ridCur));
+ for (; ridCur < ridEnd; ridCur++)
+ {
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetMethodSemanticsRecord(ridCur, &pSemantics));
+ if (dwSemantics == m_LiteWeightStgdb.m_MiniMd.getSemanticOfMethodSemantics(pSemantics))
+ {
+ // found a match
+ *pmd = m_LiteWeightStgdb.m_MiniMd.getMethodOfMethodSemantics(pSemantics);
+ goto ErrExit;
+ }
+ }
+
+ // not found
+ hr = CLDB_E_RECORD_NOTFOUND;
+ErrExit:
+ return hr;
+} // MDInternalRO::FindAssociate
+
+
+//*****************************************************************************
+// get counts of methodsemantics associated with a particular property/event
+//*****************************************************************************
+__checkReturn
+HRESULT MDInternalRO::EnumAssociateInit(
+ mdToken evprop, // [IN] given a property or an event token
+ HENUMInternal *phEnum) // [OUT] cursor to hold the query result
+{
+ HRESULT hr;
+ _ASSERTE(phEnum);
+
+ memset(phEnum, 0, sizeof(HENUMInternal));
+
+ // There is no token kind!!!
+ phEnum->m_tkKind = ULONG_MAX;
+
+ // output parameters have to be supplied
+ _ASSERTE(TypeFromToken(evprop) == mdtEvent || TypeFromToken(evprop) == mdtProperty);
+
+ phEnum->m_EnumType = MDSimpleEnum;
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getAssociatesForToken(evprop, &phEnum->u.m_ulEnd, &phEnum->u.m_ulStart));
+ phEnum->u.m_ulCur = phEnum->u.m_ulStart;
+ phEnum->m_ulCount = phEnum->u.m_ulEnd - phEnum->u.m_ulStart;
+
+ return S_OK;
+} // MDInternalRO::EnumAssociateInit
+
+
+//*****************************************************************************
+// get all methodsemantics associated with a particular property/event
+//*****************************************************************************
+__checkReturn
+HRESULT MDInternalRO::GetAllAssociates(
+ HENUMInternal *phEnum, // [OUT] cursor to hold the query result
+ ASSOCIATE_RECORD *pAssociateRec, // [OUT] struct to fill for output
+ ULONG cAssociateRec) // [IN] size of the buffer
+{
+ _ASSERTE(phEnum && pAssociateRec);
+
+ HRESULT hr;
+ MethodSemanticsRec *pSemantics;
+ RID ridCur;
+ _ASSERTE(cAssociateRec == phEnum->m_ulCount);
+
+ // Convert from row pointers to RIDs.
+ for (ridCur = phEnum->u.m_ulStart; ridCur < phEnum->u.m_ulEnd; ++ridCur)
+ {
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodSemanticsRecord(ridCur, &pSemantics));
+
+ pAssociateRec[ridCur-phEnum->u.m_ulStart].m_memberdef = m_LiteWeightStgdb.m_MiniMd.getMethodOfMethodSemantics(pSemantics);
+ pAssociateRec[ridCur-phEnum->u.m_ulStart].m_dwSemantics = m_LiteWeightStgdb.m_MiniMd.getSemanticOfMethodSemantics(pSemantics);
+ }
+
+ return S_OK;
+} // MDInternalRO::GetAllAssociates
+
+
+//*****************************************************************************
+// Get the Action and Permissions blob for a given PermissionSet.
+//*****************************************************************************
+__checkReturn
+HRESULT MDInternalRO::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.
+{
+ HRESULT hr;
+ _ASSERTE(TypeFromToken(pm) == mdtPermission);
+ _ASSERTE(pdwAction && ppvPermission && pcbPermission);
+
+ DeclSecurityRec *pPerm;
+
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetDeclSecurityRecord(RidFromToken(pm), &pPerm));
+ *pdwAction = m_LiteWeightStgdb.m_MiniMd.getActionOfDeclSecurity(pPerm);
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getPermissionSetOfDeclSecurity(pPerm, (const BYTE **)ppvPermission, pcbPermission));
+
+ return S_OK;
+} // MDInternalRO::GetPermissionSetProps
+
+//*****************************************************************************
+// Get the String given the String token.
+// Return a pointer to the string, or NULL in case of error.
+//*****************************************************************************
+__checkReturn
+HRESULT
+MDInternalRO::GetUserString( // Offset into the string blob heap.
+ mdString stk, // [IN] the string token.
+ ULONG *pcchStringSize, // [OUT] count of characters in the string.
+ BOOL *pfIs80Plus, // [OUT] specifies where there are extended characters >= 0x80.
+ LPCWSTR *pwszUserString)
+{
+ HRESULT hr;
+ LPWSTR wszTmp;
+
+ if (pfIs80Plus != NULL)
+ {
+ *pfIs80Plus = FALSE;
+ }
+ *pwszUserString = NULL;
+ *pcchStringSize = 0;
+
+ _ASSERTE(pcchStringSize != NULL);
+ MetaData::DataBlob userString;
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetUserString(RidFromToken(stk), &userString));
+
+ wszTmp = reinterpret_cast<LPWSTR>(userString.GetDataPointer());
+
+ *pcchStringSize = userString.GetSize() / sizeof(WCHAR);
+
+ if (userString.IsEmpty())
+ {
+ *pwszUserString = NULL;
+ return S_OK;
+ }
+
+ if (pfIs80Plus != NULL)
+ {
+ if (userString.GetSize() % sizeof(WCHAR) == 0)
+ {
+ *pfIs80Plus = TRUE; // no indicator, presume the worst
+ }
+ // Return the user string terminator (contains value fIs80Plus)
+ *pfIs80Plus = *(reinterpret_cast<PBYTE>(wszTmp + *pcchStringSize));
+ }
+
+ *pwszUserString = wszTmp;
+ return S_OK;
+} // MDInternalRO::GetUserString
+
+//*****************************************************************************
+// Return contents of Pinvoke given the forwarded member token.
+//*****************************************************************************
+__checkReturn
+HRESULT MDInternalRO::GetPinvokeMap(
+ mdToken tk, // [IN] FieldDef or MethodDef.
+ DWORD *pdwMappingFlags, // [OUT] Flags used for mapping.
+ LPCSTR *pszImportName, // [OUT] Import name.
+ mdModuleRef *pmrImportDLL) // [OUT] ModuleRef token for the target DLL.
+{
+ HRESULT hr;
+ ImplMapRec *pRecord;
+ RID iRecord;
+
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.FindImplMapFor(RidFromToken(tk), TypeFromToken(tk), &iRecord));
+ if (InvalidRid(iRecord))
+ {
+ return CLDB_E_RECORD_NOTFOUND;
+ }
+ else
+ {
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetImplMapRecord(iRecord, &pRecord));
+ }
+
+ if (pdwMappingFlags)
+ *pdwMappingFlags = m_LiteWeightStgdb.m_MiniMd.getMappingFlagsOfImplMap(pRecord);
+ if (pszImportName != NULL)
+ {
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getImportNameOfImplMap(pRecord, pszImportName));
+ }
+ if (pmrImportDLL)
+ *pmrImportDLL = m_LiteWeightStgdb.m_MiniMd.getImportScopeOfImplMap(pRecord);
+
+ return S_OK;
+} // MDInternalRO::GetPinvokeMap
+
+//*****************************************************************************
+// Get the properties for the given Assembly token.
+//*****************************************************************************
+__checkReturn
+HRESULT MDInternalRO::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.
+{
+ HRESULT hr;
+ AssemblyRec *pRecord;
+
+ _ASSERTE(TypeFromToken(mda) == mdtAssembly && RidFromToken(mda));
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetAssemblyRecord(RidFromToken(mda), &pRecord));
+
+ if (ppbPublicKey != NULL)
+ {
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getPublicKeyOfAssembly(pRecord, reinterpret_cast<const BYTE **>(ppbPublicKey), pcbPublicKey));
+ }
+ if (pulHashAlgId)
+ *pulHashAlgId = m_LiteWeightStgdb.m_MiniMd.getHashAlgIdOfAssembly(pRecord);
+ if (pszName != NULL)
+ {
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfAssembly(pRecord, pszName));
+ }
+ if (pMetaData)
+ {
+ pMetaData->usMajorVersion = m_LiteWeightStgdb.m_MiniMd.getMajorVersionOfAssembly(pRecord);
+ pMetaData->usMinorVersion = m_LiteWeightStgdb.m_MiniMd.getMinorVersionOfAssembly(pRecord);
+ pMetaData->usBuildNumber = m_LiteWeightStgdb.m_MiniMd.getBuildNumberOfAssembly(pRecord);
+ pMetaData->usRevisionNumber = m_LiteWeightStgdb.m_MiniMd.getRevisionNumberOfAssembly(pRecord);
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getLocaleOfAssembly(pRecord, &pMetaData->szLocale));
+ pMetaData->ulProcessor = 0;
+ pMetaData->ulOS = 0;
+ }
+ if (pdwAssemblyFlags)
+ {
+ *pdwAssemblyFlags = m_LiteWeightStgdb.m_MiniMd.getFlagsOfAssembly(pRecord);
+
+#ifdef FEATURE_WINDOWSPHONE
+ // Turn on the afPublicKey if PublicKey blob is not empty
+ DWORD cbPublicKey;
+ const BYTE *pbPublicKey;
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getPublicKeyOfAssembly(pRecord, &pbPublicKey, &cbPublicKey));
+ if (cbPublicKey != 0)
+ *pdwAssemblyFlags |= afPublicKey;
+#else
+ if (ppbPublicKey)
+ {
+ if (pcbPublicKey && *pcbPublicKey)
+ *pdwAssemblyFlags |= afPublicKey;
+ }
+ else
+ {
+#ifdef _DEBUG
+ // Assert that afPublicKey is set if PublicKey blob is not empty
+ DWORD cbPublicKey;
+ const BYTE *pPublicKey;
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getPublicKeyOfAssembly(pRecord, &pPublicKey, &cbPublicKey));
+ bool hasPublicKey = cbPublicKey != 0;
+ bool hasPublicKeyFlag = ( *pdwAssemblyFlags & afPublicKey ) != 0;
+ if(REGUTIL::GetConfigDWORD_DontUse_(CLRConfig::INTERNAL_AssertOnBadImageFormat, 0))
+ _ASSERTE( hasPublicKey == hasPublicKeyFlag );
+#endif
+ }
+#endif // FEATURE_WINDOWSPHONE
+ }
+
+ return S_OK;
+} // MDInternalRO::GetAssemblyProps
+
+//*****************************************************************************
+// Get the properties for the given AssemblyRef token.
+//*****************************************************************************
+__checkReturn
+HRESULT MDInternalRO::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;
+ AssemblyRefRec *pRecord;
+
+ _ASSERTE(TypeFromToken(mdar) == mdtAssemblyRef && RidFromToken(mdar));
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetAssemblyRefRecord(RidFromToken(mdar), &pRecord));
+
+ if (ppbPublicKeyOrToken != NULL)
+ {
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getPublicKeyOrTokenOfAssemblyRef(pRecord, reinterpret_cast<const BYTE **>(ppbPublicKeyOrToken), pcbPublicKeyOrToken));
+ }
+ if (pszName != NULL)
+ {
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfAssemblyRef(pRecord, pszName));
+ }
+ if (pMetaData)
+ {
+ pMetaData->usMajorVersion = m_LiteWeightStgdb.m_MiniMd.getMajorVersionOfAssemblyRef(pRecord);
+ pMetaData->usMinorVersion = m_LiteWeightStgdb.m_MiniMd.getMinorVersionOfAssemblyRef(pRecord);
+ pMetaData->usBuildNumber = m_LiteWeightStgdb.m_MiniMd.getBuildNumberOfAssemblyRef(pRecord);
+ pMetaData->usRevisionNumber = m_LiteWeightStgdb.m_MiniMd.getRevisionNumberOfAssemblyRef(pRecord);
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getLocaleOfAssemblyRef(pRecord, &pMetaData->szLocale));
+ pMetaData->ulProcessor = 0;
+ pMetaData->ulOS = 0;
+ }
+ if (ppbHashValue != NULL)
+ {
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getHashValueOfAssemblyRef(pRecord, reinterpret_cast<const BYTE **>(ppbHashValue), pcbHashValue));
+ }
+ if (pdwAssemblyRefFlags != NULL)
+ {
+ *pdwAssemblyRefFlags = m_LiteWeightStgdb.m_MiniMd.getFlagsOfAssemblyRef(pRecord);
+ }
+
+ return S_OK;
+} // MDInternalRO::GetAssemblyRefProps
+
+//*****************************************************************************
+// Get the properties for the given File token.
+//*****************************************************************************
+__checkReturn
+HRESULT MDInternalRO::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.
+{
+ HRESULT hr;
+ FileRec *pRecord;
+
+ _ASSERTE(TypeFromToken(mdf) == mdtFile && RidFromToken(mdf));
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetFileRecord(RidFromToken(mdf), &pRecord));
+
+ if (pszName != NULL)
+ {
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfFile(pRecord, pszName));
+ }
+ if (ppbHashValue != NULL)
+ {
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getHashValueOfFile(pRecord, reinterpret_cast<const BYTE **>(ppbHashValue), pcbHashValue));
+ }
+ if (pdwFileFlags != NULL)
+ {
+ *pdwFileFlags = m_LiteWeightStgdb.m_MiniMd.getFlagsOfFile(pRecord);
+ }
+
+ return S_OK;
+} // MDInternalRO::GetFileProps
+
+//*****************************************************************************
+// Get the properties for the given ExportedType token.
+//*****************************************************************************
+__checkReturn
+HRESULT MDInternalRO::GetExportedTypeProps(
+ mdExportedType mdct, // [IN] The ExportedType for which to get the properties.
+ LPCSTR *pszNamespace, // [OUT] Buffer to fill with namespace.
+ LPCSTR *pszName, // [OUT] Buffer to fill with 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;
+ ExportedTypeRec *pRecord;
+
+ _ASSERTE(TypeFromToken(mdct) == mdtExportedType && RidFromToken(mdct));
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetExportedTypeRecord(RidFromToken(mdct), &pRecord));
+
+ if (pszNamespace != NULL)
+ {
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getTypeNamespaceOfExportedType(pRecord, pszNamespace));
+ }
+ if (pszName != NULL)
+ {
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getTypeNameOfExportedType(pRecord, pszName));
+ }
+ if (ptkImplementation)
+ *ptkImplementation = m_LiteWeightStgdb.m_MiniMd.getImplementationOfExportedType(pRecord);
+ if (ptkTypeDef)
+ *ptkTypeDef = m_LiteWeightStgdb.m_MiniMd.getTypeDefIdOfExportedType(pRecord);
+ if (pdwExportedTypeFlags)
+ *pdwExportedTypeFlags = m_LiteWeightStgdb.m_MiniMd.getFlagsOfExportedType(pRecord);
+
+ return S_OK;
+} // MDInternalRO::GetExportedTypeProps
+
+//*****************************************************************************
+// Get the properties for the given Resource token.
+//*****************************************************************************
+__checkReturn
+HRESULT MDInternalRO::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.
+{
+ HRESULT hr;
+ ManifestResourceRec *pRecord;
+
+ _ASSERTE(TypeFromToken(mdmr) == mdtManifestResource && RidFromToken(mdmr));
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetManifestResourceRecord(RidFromToken(mdmr), &pRecord));
+
+ if (pszName != NULL)
+ {
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfManifestResource(pRecord, pszName));
+ }
+ if (ptkImplementation)
+ *ptkImplementation = m_LiteWeightStgdb.m_MiniMd.getImplementationOfManifestResource(pRecord);
+ if (pdwOffset)
+ *pdwOffset = m_LiteWeightStgdb.m_MiniMd.getOffsetOfManifestResource(pRecord);
+ if (pdwResourceFlags)
+ *pdwResourceFlags = m_LiteWeightStgdb.m_MiniMd.getFlagsOfManifestResource(pRecord);
+
+ return S_OK;
+} // MDInternalRO::GetManifestResourceProps
+
+//*****************************************************************************
+// Find the ExportedType given the name.
+//*****************************************************************************
+__checkReturn
+STDMETHODIMP MDInternalRO::FindExportedTypeByName( // S_OK or error
+ LPCSTR szNamespace, // [IN] Namespace of the ExportedType.
+ LPCSTR szName, // [IN] Name of the ExportedType.
+ mdExportedType tkEnclosingType, // [IN] Token for the Enclosing Type.
+ mdExportedType *pmct) // [OUT] Put ExportedType token here.
+{
+ IMetaModelCommon *pCommon = static_cast<IMetaModelCommon*>(&m_LiteWeightStgdb.m_MiniMd);
+ return pCommon->CommonFindExportedType(szNamespace, szName, tkEnclosingType, pmct);
+} // MDInternalRO::FindExportedTypeByName
+
+//*****************************************************************************
+// Find the ManifestResource given the name.
+//*****************************************************************************
+__checkReturn
+STDMETHODIMP MDInternalRO::FindManifestResourceByName( // S_OK or error
+ LPCSTR szName, // [IN] Name of the resource.
+ mdManifestResource *pmmr) // [OUT] Put ManifestResource token here.
+{
+ _ASSERTE(szName && pmmr);
+
+ HRESULT hr;
+ ManifestResourceRec *pRecord;
+ ULONG cRecords; // Count of records.
+ LPCUTF8 szNameTmp = 0; // Name obtained from the database.
+ ULONG i;
+
+ cRecords = m_LiteWeightStgdb.m_MiniMd.getCountManifestResources();
+
+ // Search for the ExportedType.
+ for (i = 1; i <= cRecords; i++)
+ {
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetManifestResourceRecord(i, &pRecord));
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfManifestResource(pRecord, &szNameTmp));
+ if (! strcmp(szName, szNameTmp))
+ {
+ *pmmr = TokenFromRid(i, mdtManifestResource);
+ return S_OK;
+ }
+ }
+ return CLDB_E_RECORD_NOTFOUND;
+} // MDInternalRO::FindManifestResourceByName
+
+//*****************************************************************************
+// Get the Assembly token from the given scope.
+//*****************************************************************************
+__checkReturn
+HRESULT MDInternalRO::GetAssemblyFromScope( // S_OK or error
+ mdAssembly *ptkAssembly) // [OUT] Put token here.
+{
+ _ASSERTE(ptkAssembly);
+
+ if (m_LiteWeightStgdb.m_MiniMd.getCountAssemblys())
+ {
+ *ptkAssembly = TokenFromRid(1, mdtAssembly);
+ return S_OK;
+ }
+ else
+ return CLDB_E_RECORD_NOTFOUND;
+} // MDInternalRO::GetAssemblyFromScope
+
+//*******************************************************************************
+// return properties regarding a TypeSpec
+//*******************************************************************************
+__checkReturn
+HRESULT MDInternalRO::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.
+{
+ HRESULT hr = NOERROR;
+
+ _ASSERTE(TypeFromToken(typespec) == mdtTypeSpec);
+ _ASSERTE(ppvSig && pcbSig);
+
+ if (!IsValidToken(typespec))
+ {
+ *ppvSig = NULL;
+ *pcbSig = 0;
+ return E_INVALIDARG;
+ }
+
+ TypeSpecRec *pRec;
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetTypeSpecRecord(RidFromToken(typespec), &pRec));
+
+ if (pRec == NULL)
+ {
+ *ppvSig = NULL;
+ *pcbSig = 0;
+ return CLDB_E_FILE_CORRUPT;
+ }
+
+ IfFailRet(m_LiteWeightStgdb.m_MiniMd.getSignatureOfTypeSpec(pRec, ppvSig, pcbSig));
+
+ return hr;
+} // MDInternalRO::GetTypeSpecFromToken
+
+//*****************************************************************************
+// 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
+HRESULT MDInternalRO::GetVersionString(
+ LPCSTR * pVer) // [OUT] Put version string here.
+{
+ HRESULT hr = NOERROR;
+
+ if (m_LiteWeightStgdb.m_pvMd != NULL)
+ {
+ // For convenience, get a pointer to the version string.
+ // @todo: get from alternate locations when there is no STOREAGESIGNATURE.
+ *pVer = reinterpret_cast<const char*>(reinterpret_cast<const STORAGESIGNATURE*>(m_LiteWeightStgdb.m_pvMd)->pVersion);
+ }
+ else
+ { // No string.
+ *pVer = NULL;
+ }
+
+ return hr;
+} // MDInternalRO::GetVersionString
+
+//*****************************************************************************
+// convert a text signature to com format
+//*****************************************************************************
+__checkReturn
+HRESULT MDInternalRO::ConvertTextSigToComSig(// Return hresult.
+ BOOL fCreateTrIfNotFound, // create typeref if not found or not
+ LPCSTR pSignature, // class file format signature
+ CQuickBytes *pqbNewSig, // [OUT] place holder for COM+ signature
+ ULONG *pcbCount) // [OUT] the result size of signature
+{
+ return E_NOTIMPL;
+} // MDInternalRO::ConvertTextSigToComSig
+
+
+//*****************************************************************************
+// determine if a token is valid or not
+//*****************************************************************************
+BOOL MDInternalRO::IsValidToken( // True or False.
+ mdToken tk) // [IN] Given token.
+{
+ RID rid = RidFromToken(tk);
+ if (rid == 0)
+ {
+ return FALSE;
+ }
+ switch (TypeFromToken(tk))
+ {
+ case mdtModule:
+ // can have only one module record
+ return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountModules());
+ case mdtTypeRef:
+ return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountTypeRefs());
+ case mdtTypeDef:
+ return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountTypeDefs());
+ case mdtFieldDef:
+ return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountFields());
+ case mdtMethodDef:
+ return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountMethods());
+ case mdtParamDef:
+ return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountParams());
+ case mdtInterfaceImpl:
+ return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountInterfaceImpls());
+ case mdtMemberRef:
+ return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountMemberRefs());
+ case mdtCustomAttribute:
+ return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountCustomAttributes());
+ case mdtPermission:
+ return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountDeclSecuritys());
+ case mdtSignature:
+ return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountStandAloneSigs());
+ case mdtEvent:
+ return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountEvents());
+ case mdtProperty:
+ return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountPropertys());
+ case mdtModuleRef:
+ return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountModuleRefs());
+ case mdtTypeSpec:
+ return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountTypeSpecs());
+ case mdtAssembly:
+ return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountAssemblys());
+ case mdtAssemblyRef:
+ return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountAssemblyRefs());
+ case mdtFile:
+ return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountFiles());
+ case mdtExportedType:
+ return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountExportedTypes());
+ case mdtManifestResource:
+ return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountManifestResources());
+ case mdtMethodSpec:
+ return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountMethodSpecs());
+ case mdtString:
+ // need to check the user string heap
+ return m_LiteWeightStgdb.m_MiniMd.m_UserStringHeap.IsValidIndex(rid);
+ default:
+/* Don't Assert here, this will break verifier tests.
+ _ASSERTE(!"Unknown token kind!");
+*/
+ return FALSE;
+ }
+} // MDInternalRO::IsValidToken
+
+mdModule MDInternalRO::GetModuleFromScope(void)
+{
+ return TokenFromRid(1, mdtModule);
+} // MDInternalRO::GetModuleFromScope
+
+//*****************************************************************************
+// Fill a variant given a MDDefaultValue
+// This routine will create a bstr if the ELEMENT_TYPE of default value is STRING
+//*****************************************************************************
+__checkReturn
+HRESULT _FillVariant(
+ MDDefaultValue *pMDDefaultValue,
+ VARIANT *pvar)
+{
+ HRESULT hr = NOERROR;
+
+ _ASSERTE(pMDDefaultValue);
+
+ switch (pMDDefaultValue->m_bType)
+ {
+ case ELEMENT_TYPE_BOOLEAN:
+ V_VT(pvar) = VT_BOOL;
+ V_BOOL(pvar) = pMDDefaultValue->m_bValue;
+ break;
+ case ELEMENT_TYPE_I1:
+ V_VT(pvar) = VT_I1;
+ V_I1(pvar) = pMDDefaultValue->m_cValue;
+ break;
+ case ELEMENT_TYPE_U1:
+ V_VT(pvar) = VT_UI1;
+ V_UI1(pvar) = pMDDefaultValue->m_byteValue;
+ break;
+ case ELEMENT_TYPE_I2:
+ V_VT(pvar) = VT_I2;
+ V_I2(pvar) = pMDDefaultValue->m_sValue;
+ break;
+ case ELEMENT_TYPE_U2:
+ case ELEMENT_TYPE_CHAR: // char is stored as UI2 internally
+ V_VT(pvar) = VT_UI2;
+ V_UI2(pvar) = pMDDefaultValue->m_usValue;
+ break;
+ case ELEMENT_TYPE_I4:
+ V_VT(pvar) = VT_I4;
+ V_I4(pvar) = pMDDefaultValue->m_lValue;
+ break;
+ case ELEMENT_TYPE_U4:
+ V_VT(pvar) = VT_UI4;
+ V_UI4(pvar) = pMDDefaultValue->m_ulValue;
+ break;
+ case ELEMENT_TYPE_R4:
+ V_VT(pvar) = VT_R4;
+ V_R4(pvar) = pMDDefaultValue->m_fltValue;
+ break;
+ case ELEMENT_TYPE_R8:
+ V_VT(pvar) = VT_R8;
+ V_R8(pvar) = pMDDefaultValue->m_dblValue;
+ break;
+ case ELEMENT_TYPE_STRING:
+ // allocated bstr here
+ V_BSTR(pvar) = ::SysAllocStringLen(pMDDefaultValue->m_wzValue, pMDDefaultValue->m_cbSize / sizeof(WCHAR));
+ if (V_BSTR(pvar) == NULL)
+ hr = E_OUTOFMEMORY;
+ V_VT(pvar) = VT_BSTR;
+ break;
+ case ELEMENT_TYPE_CLASS:
+ V_VT(pvar) = VT_UNKNOWN;
+ V_UNKNOWN(pvar) = pMDDefaultValue->m_unkValue;
+ break;
+ case ELEMENT_TYPE_I8:
+ V_VT(pvar) = VT_I8;
+ V_CY(pvar).int64 = pMDDefaultValue->m_llValue;
+ break;
+ case ELEMENT_TYPE_U8:
+ V_VT(pvar) = VT_UI8;
+ V_CY(pvar).int64 = pMDDefaultValue->m_ullValue;
+ break;
+ case ELEMENT_TYPE_VOID:
+ V_VT(pvar) = VT_EMPTY;
+ break;
+ default:
+ _ASSERTE(!"bad constant value type!");
+ }
+
+ return hr;
+} // _FillVariant
+
+
+//*****************************************************************************
+// Fill a variant given a MDDefaultValue
+// This routine will create a bstr if the ELEMENT_TYPE of default value is STRING
+//*****************************************************************************
+__checkReturn
+HRESULT _FillMDDefaultValue(
+ BYTE bType,
+ void const *pValue,
+ ULONG cbValue,
+ MDDefaultValue *pMDDefaultValue)
+{
+ HRESULT hr = NOERROR;
+
+ pMDDefaultValue->m_bType = bType;
+ pMDDefaultValue->m_cbSize = cbValue;
+ switch (bType)
+ {
+ case ELEMENT_TYPE_BOOLEAN:
+ if (cbValue < 1)
+ {
+ IfFailGo(CLDB_E_FILE_CORRUPT);
+ }
+ pMDDefaultValue->m_bValue = *((BYTE *) pValue);
+ break;
+ case ELEMENT_TYPE_I1:
+ if (cbValue < 1)
+ {
+ IfFailGo(CLDB_E_FILE_CORRUPT);
+ }
+ pMDDefaultValue->m_cValue = *((CHAR *) pValue);
+ break;
+ case ELEMENT_TYPE_U1:
+ if (cbValue < 1)
+ {
+ IfFailGo(CLDB_E_FILE_CORRUPT);
+ }
+ pMDDefaultValue->m_byteValue = *((BYTE *) pValue);
+ break;
+ case ELEMENT_TYPE_I2:
+ if (cbValue < 2)
+ {
+ IfFailGo(CLDB_E_FILE_CORRUPT);
+ }
+ pMDDefaultValue->m_sValue = GET_UNALIGNED_VAL16(pValue);
+ break;
+ case ELEMENT_TYPE_U2:
+ case ELEMENT_TYPE_CHAR:
+ if (cbValue < 2)
+ {
+ IfFailGo(CLDB_E_FILE_CORRUPT);
+ }
+ pMDDefaultValue->m_usValue = GET_UNALIGNED_VAL16(pValue);
+ break;
+ case ELEMENT_TYPE_I4:
+ if (cbValue < 4)
+ {
+ IfFailGo(CLDB_E_FILE_CORRUPT);
+ }
+ pMDDefaultValue->m_lValue = GET_UNALIGNED_VAL32(pValue);
+ break;
+ case ELEMENT_TYPE_U4:
+ if (cbValue < 4)
+ {
+ IfFailGo(CLDB_E_FILE_CORRUPT);
+ }
+ pMDDefaultValue->m_ulValue = GET_UNALIGNED_VAL32(pValue);
+ break;
+ case ELEMENT_TYPE_R4:
+ {
+ if (cbValue < 4)
+ {
+ IfFailGo(CLDB_E_FILE_CORRUPT);
+ }
+ __int32 Value = GET_UNALIGNED_VAL32(pValue);
+ pMDDefaultValue->m_fltValue = (float &)Value;
+ }
+ break;
+ case ELEMENT_TYPE_R8:
+ {
+ if (cbValue < 8)
+ {
+ IfFailGo(CLDB_E_FILE_CORRUPT);
+ }
+ __int64 Value = GET_UNALIGNED_VAL64(pValue);
+ pMDDefaultValue->m_dblValue = (double &) Value;
+ }
+ break;
+ case ELEMENT_TYPE_STRING:
+ if (cbValue == 0)
+ pValue = NULL;
+
+#if BIGENDIAN
+ {
+ // We need to allocate and swap the string if we're on a big endian
+ pMDDefaultValue->m_wzValue = new WCHAR[(cbValue + 1) / sizeof (WCHAR)];
+ _ASSERTE(FALSE); // Nothing ever free's this newly allocated array. Inserting assert so that if we ever actually
+ // use this code path, we'll fix it then. (Don't want to fix something I can't test.)
+ IfNullGo(pMDDefaultValue->m_wzValue);
+ memcpy(const_cast<WCHAR *>(pMDDefaultValue->m_wzValue), pValue, cbValue);
+ _ASSERTE(cbValue % sizeof(WCHAR) == 0);
+ SwapStringLength(const_cast<WCHAR *>(pMDDefaultValue->m_wzValue), cbValue / sizeof(WCHAR));
+ }
+#else
+ pMDDefaultValue->m_wzValue = (LPWSTR) pValue;
+#endif
+ break;
+ case ELEMENT_TYPE_CLASS:
+ //
+ // There is only a 4-byte quantity in the MetaData, and it must always
+ // be zero. So, we load an INT32 and zero-extend it to be pointer-sized.
+ //
+ if (cbValue < 4)
+ {
+ IfFailGo(CLDB_E_FILE_CORRUPT);
+ }
+ pMDDefaultValue->m_unkValue = (IUnknown *)(UINT_PTR)GET_UNALIGNED_VAL32(pValue);
+ if (pMDDefaultValue->m_unkValue != NULL)
+ {
+ _ASSERTE(!"Non-NULL objectref's are not supported as default values!");
+ IfFailGo(CLDB_E_FILE_CORRUPT);
+ }
+ break;
+ case ELEMENT_TYPE_I8:
+ if (cbValue < 8)
+ {
+ IfFailGo(CLDB_E_FILE_CORRUPT);
+ }
+ pMDDefaultValue->m_llValue = GET_UNALIGNED_VAL64(pValue);
+ break;
+ case ELEMENT_TYPE_U8:
+ if (cbValue < 8)
+ {
+ IfFailGo(CLDB_E_FILE_CORRUPT);
+ }
+ pMDDefaultValue->m_ullValue = GET_UNALIGNED_VAL64(pValue);
+ break;
+ case ELEMENT_TYPE_VOID:
+ break;
+ default:
+ _ASSERTE(!"BAD TYPE!");
+ IfFailGo(CLDB_E_FILE_CORRUPT);
+ break;
+ }
+ErrExit:
+ return hr;
+} // _FillMDDefaultValue
+
+//*****************************************************************************
+// Given a scope, return the table size and table ptr for a given index
+//*****************************************************************************
+__checkReturn
+HRESULT MDInternalRO::GetTableInfoWithIndex( // return size
+ ULONG index, // [IN] pass in the index
+ void **pTable, // [OUT] pointer to table at index
+ void **pTableSize) // [OUT] size of table at index
+{
+ _ASSERTE(!"NYI");
+ return E_NOTIMPL;
+} // MDInternalRO::GetTableInfoWithIndex
+
+
+
+//*****************************************************************************
+// Given a delta metadata byte stream, apply the changes to the current metadata
+// object returning the resulting metadata object in ppv
+//*****************************************************************************
+__checkReturn
+HRESULT MDInternalRO::ApplyEditAndContinue(
+ void *pDeltaMD, // [IN] the delta metadata
+ ULONG cbDeltaMD, // [IN] length of pData
+ IMDInternalImport **ppv) // [OUT] the resulting metadata interface
+{
+ _ASSERTE(pDeltaMD);
+ _ASSERTE(ppv);
+
+ HRESULT hr = E_FAIL;
+
+ IMDInternalImportENC *pDeltaMDImport = NULL;
+
+ IfFailGo(GetInternalWithRWFormat(pDeltaMD, cbDeltaMD, 0, IID_IMDInternalImportENC, (void**)&pDeltaMDImport));
+
+ *ppv = this;
+ IfFailGo(MDApplyEditAndContinue(ppv, pDeltaMDImport));
+
+ErrExit:
+ if (pDeltaMDImport)
+ pDeltaMDImport->Release();
+ return hr;
+}
+
+HRESULT MDInternalRO::GetRvaOffsetData(
+ 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.
+{
+ HRESULT hr = S_OK;
+ DWORD methodDefCount = *pMethodDefCount = m_LiteWeightStgdb.m_MiniMd.getCountMethods();
+ if (methodDefCount == 0)
+ *pFirstMethodRvaOffset = *pMethodDefRecordSize = 0;
+ else
+ {
+ MethodRec *pMethodRec;
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetMethodRecord(1, &pMethodRec));
+
+ // RVA is the first column of the MethodDef table, so the address of MethodRec is also address of RVA column.
+ if ((const BYTE *)m_LiteWeightStgdb.m_pvMd > (const BYTE *)pMethodRec)
+ {
+ Debug_ReportError("Stream header is not within MetaData block.");
+ IfFailGo(CLDB_E_FILE_CORRUPT);
+ }
+ *pFirstMethodRvaOffset = (DWORD)((const BYTE *)pMethodRec - (const BYTE *)m_LiteWeightStgdb.m_pvMd);
+ *pMethodDefRecordSize = m_LiteWeightStgdb.m_MiniMd._CBREC(Method);
+ }
+
+ {
+ DWORD fieldRvaCount = *pFieldRvaCount = m_LiteWeightStgdb.m_MiniMd.getCountFieldRVAs();
+ if (fieldRvaCount == 0)
+ *pFirstFieldRvaOffset = *pFieldRvaRecordSize = 0;
+ else
+ {
+
+ // orig
+ // FieldRVARec *pFieldRVARec = m_LiteWeightStgdb.m_MiniMd.getFieldRVA(1);
+ FieldRVARec *pFieldRVARec;
+ IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetFieldRVARecord(1, &pFieldRVARec));
+
+//FieldRVARec *pFieldRVARec;
+//mdToken fakeTok = 1;
+//RidToToken(&fakeTok, mdtFieldDef);
+//GetFieldRVA(fakeTok, &pFieldRVARec);
+ // RVA is the first column of the FieldRVA table, so the address of FieldRVARec is also address of RVA column.
+ if ((const BYTE *)m_LiteWeightStgdb.m_pvMd > (const BYTE *)pFieldRVARec)
+ {
+ Debug_ReportError("Stream header is not within MetaData block.");
+ IfFailGo(CLDB_E_FILE_CORRUPT);
+ }
+ *pFirstFieldRvaOffset = (DWORD)((const BYTE *)pFieldRVARec - (const BYTE *)m_LiteWeightStgdb.m_pvMd);
+ *pFieldRvaRecordSize = m_LiteWeightStgdb.m_MiniMd._CBREC(FieldRVA);
+ }
+ }
+ hr = S_OK;
+
+ErrExit:
+ return hr;
+}
+
+#endif //FEATURE_METADATA_INTERNAL_APIS
diff --git a/src/md/runtime/mdinternalro.h b/src/md/runtime/mdinternalro.h
new file mode 100644
index 0000000000..92e5393ffa
--- /dev/null
+++ b/src/md/runtime/mdinternalro.h
@@ -0,0 +1,849 @@
+// 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.
+//*****************************************************************************
+// MDInternalRO.h
+//
+
+//
+// Contains utility code for MD directory
+//
+//*****************************************************************************
+#ifndef __MDInternalRO__h__
+#define __MDInternalRO__h__
+
+#include "winmdinterfaces.h"
+
+#ifdef FEATURE_METADATA_INTERNAL_APIS
+
+class MDInternalRO : public IMDInternalImport, IMDCommon
+{
+public:
+
+ MDInternalRO();
+ virtual ~MDInternalRO();
+ __checkReturn
+ HRESULT Init(LPVOID pData, ULONG cbData);
+
+ // *** IUnknown methods ***
+ __checkReturn
+ STDMETHODIMP QueryInterface(REFIID riid, void** ppv);
+ STDMETHODIMP_(ULONG) AddRef(void);
+ STDMETHODIMP_(ULONG) Release(void);
+
+ __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
+ DAC_UNEXPECTED();
+
+
+ __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
+
+
+
+ STDMETHODIMP_(IMetaModelCommon*) GetMetaModelCommon()
+ {
+ return static_cast<IMetaModelCommon*>(&m_LiteWeightStgdb.m_MiniMd);
+ }
+
+ STDMETHODIMP_(IMetaModelCommonRO*) GetMetaModelCommonRO()
+ {
+ if (m_LiteWeightStgdb.m_MiniMd.IsWritable())
+ {
+ _ASSERTE(!"IMetaModelCommonRO methods cannot be used because this importer is writable.");
+ return NULL;
+ }
+ return static_cast<IMetaModelCommonRO*>(&m_LiteWeightStgdb.m_MiniMd);
+ }
+
+ __checkReturn
+ STDMETHODIMP SetOptimizeAccessForSpeed(
+ BOOL fOptSpeed)
+ {
+ // The metadata cache of hot items is an optional working-set optimization
+ // that has a large speed cost relative to direct table lookup
+ if (fOptSpeed)
+ { // We want to disable usage of hot data (e.g. in ngen compilation process)
+ m_LiteWeightStgdb.m_MiniMd.DisableHotDataUsage();
+ }
+ return S_OK;
+ }
+
+ //*****************************************************************************
+ // 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.
+ DAC_UNEXPECTED();
+
+ //*****************************************************************************
+ // enumerator for typedef
+ //*****************************************************************************
+ __checkReturn
+ STDMETHODIMP EnumTypeDefInit( // return hresult
+ HENUMInternal *phEnum); // [OUT] buffer to fill for enumerator data
+
+ STDMETHODIMP_(ULONG) EnumTypeDefGetCount(
+ HENUMInternal *phEnum); // [IN] the enumerator to retrieve information
+
+ STDMETHODIMP_(void) EnumTypeDefReset(
+ HENUMInternal *phEnum); // [IN] the enumerator to retrieve information
+
+ STDMETHODIMP_(bool) EnumTypeDefNext( // return hresult
+ HENUMInternal *phEnum, // [IN] input enum
+ mdTypeDef *ptd); // [OUT] return token
+
+ STDMETHODIMP_(void) EnumTypeDefClose(
+ HENUMInternal *phEnum); // [IN] the enumerator to retrieve information
+
+ //*****************************************************************************
+ // 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 *phEnumDecl); // [OUT] buffer to fill for enumerator data for MethodDecl tokens.
+
+ STDMETHODIMP_(ULONG) EnumMethodImplGetCount(
+ HENUMInternal *phEnumBody, // [IN] MethodBody enumerator.
+ HENUMInternal *phEnumDecl); // [IN] MethodDecl enumerator.
+
+ STDMETHODIMP_(void) EnumMethodImplReset(
+ HENUMInternal *phEnumBody, // [IN] MethodBody enumerator.
+ HENUMInternal *phEnumDecl); // [IN] MethodDecl enumerator.
+
+ __checkReturn
+ STDMETHODIMP EnumMethodImplNext( // return hresult
+ HENUMInternal *phEnumBody, // [IN] input enum for MethodBody
+ HENUMInternal *phEnumDecl, // [IN] input enum for MethodDecl
+ mdToken *ptkBody, // [OUT] return token for MethodBody
+ mdToken *ptkDecl); // [OUT] return token for MethodDecl
+
+ STDMETHODIMP_(void) EnumMethodImplClose(
+ HENUMInternal *phEnumBody, // [IN] MethodBody enumerator.
+ HENUMInternal *phEnumDecl); // [IN] MethodDecl enumerator.
+
+ //*****************************************
+ // Enumerator helpers for memberdef, memberref, interfaceimp,
+ // event, property, param, methodimpl
+ //*****************************************
+
+ __checkReturn
+ STDMETHODIMP EnumGlobalFunctionsInit( // return hresult
+ HENUMInternal *phEnum); // [OUT] buffer to fill for enumerator data
+
+ __checkReturn
+ STDMETHODIMP EnumGlobalFieldsInit( // return hresult
+ HENUMInternal *phEnum); // [OUT] buffer to fill for enumerator data
+
+ __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
+
+ __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
+
+ STDMETHODIMP_(bool) EnumNext(
+ HENUMInternal *phEnum, // [IN] the enumerator to retrieve information
+ mdToken *ptk); // [OUT] token to scope the search
+
+ STDMETHODIMP_(ULONG) EnumGetCount(
+ HENUMInternal *phEnum); // [IN] the enumerator to retrieve information
+
+ STDMETHODIMP_(void) EnumReset(
+ HENUMInternal *phEnum); // [IN] the enumerator to be reset
+
+ STDMETHODIMP_(void) EnumClose(
+ HENUMInternal *phEnum); // [IN] the enumerator to be closed
+
+ __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
+
+ __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
+
+ __checkReturn
+ STDMETHODIMP GetParentToken(
+ mdToken tkChild, // [IN] given child token
+ mdToken *ptkParent); // [OUT] returning parent
+
+ __checkReturn
+ STDMETHODIMP GetCustomAttributeProps(
+ mdCustomAttribute at, // [IN] The attribute.
+ mdToken *ptkType); // [OUT] Put attribute type here.
+
+ __checkReturn
+ STDMETHODIMP GetCustomAttributeAsBlob(
+ mdCustomAttribute cv, // [IN] given custom attribute token
+ void const **ppBlob, // [OUT] return the pointer to internal blob
+ ULONG *pcbSize); // [OUT] return the size of the blob
+
+ __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.
+
+ __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.
+
+ __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
+
+ __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
+
+ __checkReturn
+ STDMETHODIMP GetScopeProps(
+ LPCSTR *pszName, // [OUT] scope name
+ GUID *pmvid); // [OUT] version id
+
+ // 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 COM+ signature
+ ULONG cbSigBlob, // [IN] count of bytes in the signature blob
+ mdMethodDef *pmd); // [OUT] matching memberdef
+
+ // 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.
+
+ //*****************************************
+ //
+ // 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
+
+ __checkReturn
+ STDMETHODIMP GetIsDualOfTypeDef(
+ mdTypeDef classdef, // [IN] given classdef.
+ ULONG *pDual); // [OUT] return dual flag here.
+
+ __checkReturn
+ STDMETHODIMP GetIfaceTypeOfTypeDef(
+ mdTypeDef classdef, // [IN] given classdef.
+ ULONG *pIface); // [OUT] 0=dual, 1=vtable, 2=dispinterface
+
+ // get the name of either methoddef
+ __checkReturn
+ STDMETHODIMP GetNameOfMethodDef( // return the name of the memberdef in UTF8
+ mdMethodDef md, // given memberdef
+ LPCSTR *pszName);
+
+ __checkReturn
+ STDMETHODIMP GetNameAndSigOfMethodDef(
+ mdMethodDef methoddef, // [IN] given memberdef
+ PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to a blob value of COM+ signature
+ ULONG *pcbSigBlob, // [OUT] count of bytes in the signature blob
+ LPCSTR *pszName);
+
+ // return the name of a FieldDef
+ __checkReturn
+ STDMETHODIMP GetNameOfFieldDef(
+ mdFieldDef fd, // given memberdef
+ LPCSTR *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
+
+ // return the resolutionscope of typeref
+ __checkReturn
+ STDMETHODIMP GetResolutionScopeOfTypeRef(
+ mdTypeRef classref, // given classref
+ mdToken *ptkResolutionScope);
+
+ // return the typeref 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 the TypeDef properties
+ __checkReturn
+ STDMETHODIMP GetTypeDefProps( // return hresult
+ mdTypeDef classdef, // given classdef
+ DWORD *pdwAttr, // return flags on class, tdPublic, tdAbstract
+ mdToken *ptkExtends); // [OUT] Put base class TypeDef/TypeRef here.
+
+ // return the item's guid
+ __checkReturn
+ STDMETHODIMP GetItemGuid( // return hresult
+ mdToken tkObj, // [IN] given item.
+ CLSID *pGuid); // [OUT] Put guid here.
+
+ // get enclosing class of NestedClass.
+ __checkReturn
+ STDMETHODIMP GetNestedClassProps( // S_OK or error
+ mdTypeDef tkNestedClass, // [IN] NestedClass token.
+ mdTypeDef *ptkEnclosingClass); // [OUT] EnclosingClass token.
+
+ // Get count of Nested classes given the enclosing class.
+ __checkReturn
+ STDMETHODIMP GetCountNestedClasses( // return count of Nested classes.
+ mdTypeDef tkEnclosingClass, // [IN]Enclosing class.
+ ULONG *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 the ModuleRef properties
+ __checkReturn
+ STDMETHODIMP GetModuleRefProps(
+ mdModuleRef mur, // [IN] moduleref token
+ LPCSTR *pszName); // [OUT] buffer to fill with the moduleref name
+
+ //*****************************************
+ //
+ // GetSig* functions
+ //
+ //*****************************************
+ __checkReturn
+ STDMETHODIMP GetSigOfMethodDef(
+ mdMethodDef methoddef, // [IN] given memberdef
+ ULONG *pcbSigBlob, // [OUT] count of bytes in the signature blob
+ PCCOR_SIGNATURE *ppSig);
+
+ __checkReturn
+ STDMETHODIMP GetSigOfFieldDef(
+ mdMethodDef methoddef, // [IN] given memberdef
+ ULONG *pcbSigBlob, // [OUT] count of bytes in the signature blob
+ PCCOR_SIGNATURE *ppSig);
+
+ __checkReturn
+ STDMETHODIMP GetSigFromToken(
+ mdToken tk, // FieldDef, MethodDef, Signature or TypeSpec token
+ ULONG * pcbSig,
+ PCCOR_SIGNATURE * ppSig);
+
+
+
+ //*****************************************
+ // get method property
+ //*****************************************
+ __checkReturn
+ STDMETHODIMP GetMethodDefProps(
+ mdMethodDef md, // The method for which to get props.
+ DWORD *pdwFlags);
+
+ __checkReturn
+ STDMETHODIMP_(ULONG) GetMethodDefSlot(
+ mdMethodDef mb); // The method for which to get props.
+
+ //*****************************************
+ // return method implementation informaiton, like RVA and implflags
+ //*****************************************
+ __checkReturn
+ STDMETHODIMP GetMethodImplProps(
+ mdMethodDef tk, // [IN] MethodDef
+ ULONG *pulCodeRVA, // [OUT] CodeRVA
+ DWORD *pdwImplFlags); // [OUT] Impl. Flags
+
+ //*****************************************************************************
+ // return the field RVA
+ //*****************************************************************************
+ __checkReturn
+ STDMETHODIMP GetFieldRVA(
+ mdToken fd, // [IN] FieldDef
+ ULONG *pulCodeRVA); // [OUT] CodeRVA
+
+ //*****************************************************************************
+ // return the field offset for a given field
+ //*****************************************************************************
+ __checkReturn
+ STDMETHODIMP GetFieldOffset(
+ mdFieldDef fd, // [IN] fielddef
+ ULONG *pulOffset); // [OUT] FieldOffset
+
+ //*****************************************
+ // get field property
+ //*****************************************
+ __checkReturn
+ STDMETHODIMP GetFieldDefProps(
+ mdFieldDef fd, // [IN] given fielddef
+ DWORD *pdwFlags); // [OUT] return fdPublic, fdPrive, etc flags
+
+ //*****************************************************************************
+ // 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
+
+
+ //*****************************************
+ // 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 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 information about a generic method instantiation
+ //*****************************************
+ __checkReturn
+ 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
+
+ //*****************************************
+ // 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] TypeDef/TypeRef of enclosing class.
+ mdTypeDef *ptypedef); // [OUT] return typedef
+
+ __checkReturn
+ STDMETHODIMP FindTypeDefByGUID(
+ REFGUID guid, // guid to look up
+ mdTypeDef *ptypedef); // return typedef
+
+
+
+ //*****************************************
+ // 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 COM+ signature
+ ULONG *pcbSigBlob, // [OUT] count of bytes in the signature blob
+ LPCSTR *pszName);
+
+ //*****************************************************************************
+ // Given memberref, return the parent. It can be TypeRef, ModuleRef, MethodDef
+ //*****************************************************************************
+ __checkReturn
+ STDMETHODIMP GetParentOfMemberRef(
+ mdMemberRef memberref, // given memberref
+ mdToken *ptkParent); // return the parent token
+
+ __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
+
+ //******************************************
+ // property info for method.
+ //******************************************
+ __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
+ DAC_UNEXPECTED();
+
+ //*****************************************
+ // class layout/sequence information
+ //*****************************************
+ __checkReturn
+ STDMETHODIMP GetClassPackSize( // [OUT] return error if a class doesn't have packsize info
+ mdTypeDef td, // [IN] give typedef
+ ULONG *pdwPackSize); // [OUT] return the pack size of the class. 1, 2, 4, 8 or 16
+
+ __checkReturn
+ STDMETHODIMP GetClassTotalSize( // [OUT] return error if a class doesn't have total size info
+ mdTypeDef td, // [IN] give typedef
+ ULONG *pdwClassSize); // [OUT] return the total size of the class
+
+ __checkReturn
+ STDMETHODIMP GetClassLayoutInit(
+ mdTypeDef td, // [IN] give typedef
+ MD_CLASS_LAYOUT *pLayout); // [OUT] set up the status of query here
+
+ __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
+
+ //*****************************************
+ // 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
+
+
+ //*****************************************
+ // 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
+
+ __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
+
+ //**********************************
+ // Event APIs
+ //**********************************
+ __checkReturn
+ STDMETHODIMP FindEvent(
+ mdTypeDef td, // [IN] given a typdef
+ LPCSTR szEventName, // [IN] event name
+ mdEvent *pEvent); // [OUT] return event token
+
+ __checkReturn
+ STDMETHODIMP GetEventProps( // S_OK, S_FALSE, or error.
+ mdEvent ev, // [IN] event token
+ LPCSTR *pszEvent, // [OUT] Event name
+ DWORD *pdwEventFlags, // [OUT] Event flags.
+ mdToken *ptkEventType); // [OUT] EventType class
+
+ //**********************************
+ // 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
+
+ __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
+
+
+ //**********************************
+ // 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
+
+ __checkReturn
+ STDMETHODIMP EnumAssociateInit(
+ mdToken evprop, // [IN] given a property or an event token
+ HENUMInternal *phEnum); // [OUT] cursor to hold the query result
+
+ __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
+
+
+ //**********************************
+ // Get info about a PermissionSet.
+ //**********************************
+ __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.
+
+ //****************************************
+ // 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);
+
+ //*****************************************************************************
+ // p-invoke APIs.
+ //*****************************************************************************
+ __checkReturn
+ STDMETHODIMP GetPinvokeMap(
+ mdMethodDef tk, // [IN] FieldDef or MethodDef.
+ DWORD *pdwMappingFlags, // [OUT] Flags used for mapping.
+ LPCSTR *pszImportName, // [OUT] Import name.
+ mdModuleRef *pmrImportDLL); // [OUT] ModuleRef token for the target DLL.
+
+ //*****************************************************************************
+ // Assembly MetaData APIs.
+ //*****************************************************************************
+ __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.
+
+ __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.
+
+ __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.
+
+ __checkReturn
+ STDMETHODIMP GetExportedTypeProps(
+ mdExportedType mdct, // [IN] The ExportedType for which to get the properties.
+ LPCSTR *pszNamespace, // [OUT] Buffer to fill with namespace.
+ LPCSTR *pszName, // [OUT] Buffer to fill with name.
+ mdToken *ptkImplementation, // [OUT] mdFile or mdAssemblyRef that provides the ExportedType.
+ mdTypeDef *ptkTypeDef, // [OUT] TypeDef token within the file.
+ DWORD *pdwExportedTypeFlags); // [OUT] Flags.
+
+ __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.
+
+ __checkReturn
+ STDMETHODIMP FindExportedTypeByName( // S_OK or error
+ LPCSTR szNamespace, // [IN] Namespace of the ExportedType.
+ LPCSTR szName, // [IN] Name of the ExportedType.
+ mdExportedType tkEnclosingType, // [IN] Enclosing ExportedType.
+ mdExportedType *pmct); // [OUT] Put ExportedType token here.
+
+ __checkReturn
+ STDMETHODIMP FindManifestResourceByName(// S_OK or error
+ LPCSTR szName, // [IN] Name of the resource.
+ mdManifestResource *pmmr); // [OUT] Put ManifestResource token here.
+
+ __checkReturn
+ STDMETHODIMP GetAssemblyFromScope( // S_OK or error
+ mdAssembly *ptkAssembly); // [OUT] Put token here.
+
+ //***************************************************************************
+ // return properties regarding a TypeSpec
+ //***************************************************************************
+ __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.
+
+ //*****************************************************************************
+ // 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.
+
+
+ //*****************************************************************************
+ // 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 COM+ signature
+ ULONG *pcbCount); // [OUT] the result size of signature
+
+ __checkReturn
+ STDMETHODIMP SetUserContextData( // S_OK or E_NOTIMPL
+ IUnknown *pIUnk) // The user context.
+ { return E_NOTIMPL; }
+
+ STDMETHODIMP_(BOOL) IsValidToken( // True or False.
+ mdToken tk); // [IN] Given token.
+
+ STDMETHODIMP_(IUnknown *) GetCachedPublicInterface(BOOL fWithLock) { return NULL;} // return the cached public interface
+ __checkReturn
+ STDMETHODIMP SetCachedPublicInterface(IUnknown *pUnk) { return E_FAIL;} ;// return hresult
+ STDMETHODIMP_(UTSemReadWrite*) GetReaderWriterLock() {return NULL;} // return the reader writer lock
+ __checkReturn
+ STDMETHODIMP SetReaderWriterLock(UTSemReadWrite *pSem) { return NOERROR; }
+ STDMETHODIMP_(mdModule) GetModuleFromScope(void);
+
+ // Find a paticular method and pass in the signature comparison routine. Very
+ // helpful when the passed in signature does not come from the same scope.
+ __checkReturn
+ STDMETHODIMP FindMethodDefUsingCompare(
+ mdTypeDef classdef, // [IN] given typedef
+ LPCSTR szName, // [IN] member name
+ PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of COM+ signature
+ ULONG cbSigBlob, // [IN] count of bytes in the signature blob
+ PSIGCOMPARE pSignatureCompare, // [IN] Routine to compare signatures
+ void* pSignatureArgs, // [IN] Additional info to supply the compare function
+ mdMethodDef *pmd); // [OUT] matching memberdef
+
+
+ //*****************************************************************************
+ // return the table pointer and size for a given table index
+ //*****************************************************************************
+ __checkReturn
+ STDMETHODIMP GetTableInfoWithIndex(
+ ULONG index, // [IN] pass in the index
+ void **pTable, // [OUT] pointer to table at index
+ void **pTableSize); // [OUT] size of table at index
+
+ __checkReturn
+ STDMETHODIMP ApplyEditAndContinue(
+ void *pData, // [IN] the delta metadata
+ ULONG cbData, // [IN] length of pData
+ IMDInternalImport **ppv); // [OUT] the resulting metadata interface
+
+ STDMETHODIMP GetRvaOffsetData(
+ 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.
+ );
+
+ CLiteWeightStgdb<CMiniMd> m_LiteWeightStgdb;
+
+private:
+
+ struct CMethodSemanticsMap
+ {
+ mdToken m_mdMethod; // Method token.
+ RID m_ridSemantics; // RID of semantics record.
+ };
+ CMethodSemanticsMap *m_pMethodSemanticsMap; // Possible array of method semantics pointers, ordered by method token.
+
+#ifndef DACCESS_COMPILE
+ class CMethodSemanticsMapSorter : public CQuickSort<CMethodSemanticsMap>
+ {
+ public:
+ CMethodSemanticsMapSorter(CMethodSemanticsMap *pBase, int iCount) : CQuickSort<CMethodSemanticsMap>(pBase, iCount) {}
+ virtual int Compare(CMethodSemanticsMap *psFirst, CMethodSemanticsMap *psSecond);
+ };
+#endif //!DACCESS_COMPILE
+
+ class CMethodSemanticsMapSearcher : public CBinarySearch<CMethodSemanticsMap>
+ {
+ public:
+ CMethodSemanticsMapSearcher(const CMethodSemanticsMap *pBase, int iCount) : CBinarySearch<CMethodSemanticsMap>(pBase, iCount) {}
+ virtual int Compare(const CMethodSemanticsMap *psFirst, const CMethodSemanticsMap *psSecond);
+ };
+
+ static BOOL CompareSignatures(PCCOR_SIGNATURE pvFirstSigBlob, DWORD cbFirstSigBlob,
+ PCCOR_SIGNATURE pvSecondSigBlob, DWORD cbSecondSigBlob,
+ void* SigARguments);
+
+ mdTypeDef m_tdModule; // <Module> typedef value.
+ LONG m_cRefs; // Ref count.
+
+public:
+ STDMETHODIMP_(DWORD) GetMetadataStreamVersion()
+ {
+ return (DWORD)m_LiteWeightStgdb.m_MiniMd.m_Schema.m_minor |
+ ((DWORD)m_LiteWeightStgdb.m_MiniMd.m_Schema.m_major << 16);
+ };
+
+ STDMETHODIMP SetVerifiedByTrustedSource(// return hresult
+ BOOL fVerified)
+ {
+ m_LiteWeightStgdb.m_MiniMd.SetVerifiedByTrustedSource(fVerified);
+ return S_OK;
+ }
+}; // class MDInternalRO
+
+#endif //FEATURE_METADATA_INTERNAL_APIS
+
+#endif // __MDInternalRO__h__
diff --git a/src/md/runtime/metamodel.cpp b/src/md/runtime/metamodel.cpp
new file mode 100644
index 0000000000..293e5b6b5e
--- /dev/null
+++ b/src/md/runtime/metamodel.cpp
@@ -0,0 +1,1240 @@
+// 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.
+//*****************************************************************************
+// MetaModel.cpp -- Base portion of compressed COM+ metadata.
+//
+
+//
+//*****************************************************************************
+#include "stdafx.h"
+
+#include <metamodel.h>
+#include <corerror.h>
+#include <posterror.h>
+
+//*****************************************************************************
+// meta-meta model.
+//*****************************************************************************
+
+//-----------------------------------------------------------------------------
+// Start of column definitions.
+//-----------------------------------------------------------------------------
+// Column type, offset, size.
+#define SCHEMA_TABLE_START(tbl) static CMiniColDef r##tbl##Cols[] = {
+#define SCHEMA_ITEM_NOFIXED()
+#define SCHEMA_ITEM_ENTRY(col,typ) {typ, 0,0},
+#define SCHEMA_ITEM_ENTRY2(col,typ,ofs,siz) {typ, ofs, siz},
+#define SCHEMA_ITEM(tbl,typ,col) SCHEMA_ITEM_ENTRY2(col, i##typ, offsetof(tbl##Rec,m_##col), sizeof(((tbl##Rec*)(0))->m_##col))
+#define SCHEMA_ITEM_RID(tbl,col,tbl2) SCHEMA_ITEM_ENTRY(col,TBL_##tbl2)
+#define SCHEMA_ITEM_STRING(tbl,col) SCHEMA_ITEM_ENTRY(col,iSTRING)
+#define SCHEMA_ITEM_GUID(tbl,col) SCHEMA_ITEM_ENTRY(col,iGUID)
+#define SCHEMA_ITEM_BLOB(tbl,col) SCHEMA_ITEM_ENTRY(col,iBLOB)
+#define SCHEMA_ITEM_CDTKN(tbl,col,tkns) SCHEMA_ITEM_ENTRY(col,iCodedToken+(CDTKN_##tkns))
+#define SCHEMA_TABLE_END(tbl) };
+//-----------------------------------------------------------------------------
+#include "metamodelcolumndefs.h"
+//-----------------------------------------------------------------------------
+#undef SCHEMA_TABLE_START
+#undef SCHEMA_ITEM_NOFIXED
+#undef SCHEMA_ITEM_ENTRY
+#undef SCHEMA_ITEM_ENTRY2
+#undef SCHEMA_ITEM
+#undef SCHEMA_ITEM_RID
+#undef SCHEMA_ITEM_STRING
+#undef SCHEMA_ITEM_GUID
+#undef SCHEMA_ITEM_BLOB
+#undef SCHEMA_ITEM_CDTKN
+#undef SCHEMA_TABLE_END
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// Column names.
+#define SCHEMA_TABLE_START(tbl) static const char *r##tbl##ColNames[] = {
+#define SCHEMA_ITEM_NOFIXED()
+#define SCHEMA_ITEM_ENTRY(col,typ) #col,
+#define SCHEMA_ITEM_ENTRY2(col,typ,ofs,siz) #col,
+#define SCHEMA_ITEM(tbl,typ,col) SCHEMA_ITEM_ENTRY2(col, i##typ, offsetof(tbl##Rec,m_##col), sizeof(((tbl##Rec*)(0))->m_##col))
+#define SCHEMA_ITEM_RID(tbl,col,tbl2) SCHEMA_ITEM_ENTRY(col,TBL_##tbl2)
+#define SCHEMA_ITEM_STRING(tbl,col) SCHEMA_ITEM_ENTRY(col,iSTRING)
+#define SCHEMA_ITEM_GUID(tbl,col) SCHEMA_ITEM_ENTRY(col,iGUID)
+#define SCHEMA_ITEM_BLOB(tbl,col) SCHEMA_ITEM_ENTRY(col,iBLOB)
+#define SCHEMA_ITEM_CDTKN(tbl,col,tkns) SCHEMA_ITEM_ENTRY(col,iCodedToken+(CDTKN_##tkns))
+#define SCHEMA_TABLE_END(tbl) };
+//-----------------------------------------------------------------------------
+#include "metamodelcolumndefs.h"
+//-----------------------------------------------------------------------------
+#undef SCHEMA_TABLE_START
+#undef SCHEMA_ITEM_NOFIXED
+#undef SCHEMA_ITEM_ENTRY
+#undef SCHEMA_ITEM_ENTRY2
+#undef SCHEMA_ITEM
+#undef SCHEMA_ITEM_RID
+#undef SCHEMA_ITEM_STRING
+#undef SCHEMA_ITEM_GUID
+#undef SCHEMA_ITEM_BLOB
+#undef SCHEMA_ITEM_CDTKN
+#undef SCHEMA_TABLE_END
+
+//-----------------------------------------------------------------------------
+// End of column definitions.
+//-----------------------------------------------------------------------------
+
+// Define the array of Coded Token Definitions.
+#define MiniMdCodedToken(x) {lengthof(CMiniMdBase::mdt##x), CMiniMdBase::mdt##x, #x},
+const CCodedTokenDef g_CodedTokens [] = {
+ MiniMdCodedTokens()
+};
+#undef MiniMdCodedToken
+
+// Define the array of Table Definitions.
+#undef MiniMdTable
+#define MiniMdTable(x) { { r##x##Cols, lengthof(r##x##Cols), x##Rec::COL_KEY, 0 }, r##x##ColNames, #x},
+const CMiniTableDefEx g_Tables[TBL_COUNT] = {
+ MiniMdTables()
+};
+
+// Define a table descriptor for the obsolete v1.0 GenericParam table definition.
+const CMiniTableDefEx g_Table_GenericParamV1_1 = { { rGenericParamV1_1Cols, lengthof(rGenericParamV1_1Cols), GenericParamV1_1Rec::COL_KEY, 0 }, rGenericParamV1_1ColNames, "GenericParamV1_"};
+
+
+
+// Define the array of Ptr Tables. This is initialized to TBL_COUNT here.
+// The correct values will be set in the constructor for MiniMdRW.
+#undef MiniMdTable
+#define MiniMdTable(x) { TBL_COUNT, 0 },
+TblCol g_PtrTableIxs[TBL_COUNT] = {
+ MiniMdTables()
+};
+
+//*****************************************************************************
+// Initialize a new schema.
+//*****************************************************************************
+HRESULT
+CMiniMdSchema::InitNew(
+ MetadataVersion mdVersion)
+{
+ // Make sure the tables fit in the mask.
+ _ASSERTE((sizeof(m_maskvalid) * 8) > TBL_COUNT);
+
+ m_ulReserved = 0;
+
+ if(mdVersion == MDVersion1)
+ {
+ m_major = METAMODEL_MAJOR_VER_V1_0;
+ m_minor = METAMODEL_MINOR_VER_V1_0;
+ }
+ else if (mdVersion == MDVersion2)
+ {
+ m_major = METAMODEL_MAJOR_VER;
+ m_minor = METAMODEL_MINOR_VER;
+ }
+ else
+ {
+ return E_INVALIDARG;
+ }
+
+ m_heaps = 0;
+ m_rid = 0;
+ m_maskvalid = 0;
+ m_sorted = 0;
+ memset(m_cRecs, 0, sizeof(m_cRecs));
+ m_ulExtra = 0;
+
+ return S_OK;
+} // CMiniMdSchema::InitNew
+
+//*****************************************************************************
+// Compress a schema into a compressed version of the schema.
+//*****************************************************************************
+ULONG
+CMiniMdSchema::SaveTo(
+ void *pvData)
+{
+ ULONG ulData; // Bytes stored.
+ CMiniMdSchema *pDest = reinterpret_cast<CMiniMdSchema*>(pvData);
+ const unsigned __int64 one = 1;
+
+ // Make sure the tables fit in the mask.
+ _ASSERTE((sizeof(m_maskvalid) * 8) > TBL_COUNT);
+
+ // Set the flag for the extra data.
+#if defined(EXTRA_DATA)
+ if (m_ulExtra != 0)
+ {
+ m_heaps |= EXTRA_DATA;
+ }
+ else
+#endif // 0
+ {
+ m_heaps &= ~EXTRA_DATA;
+ }
+
+ // Minor version is preset when we instantiate the MiniMd.
+
+ // Make sure we're saving out a version that Beta1 version can read
+ _ASSERTE((m_major == METAMODEL_MAJOR_VER && m_minor == METAMODEL_MINOR_VER) ||
+ (m_major == METAMODEL_MAJOR_VER_B1 && m_minor == METAMODEL_MINOR_VER_B1) ||
+ (m_major == METAMODEL_MAJOR_VER_V1_0 && m_minor == METAMODEL_MINOR_VER_V1_0));
+
+ // Transfer the fixed fields.
+ *static_cast<CMiniMdSchemaBase*>(pDest) = *static_cast<CMiniMdSchemaBase*>(this);
+ static_cast<CMiniMdSchemaBase*>(pDest)->ConvertEndianness();
+ ulData = sizeof(CMiniMdSchemaBase);
+
+ // Transfer the variable fields.
+ m_maskvalid = 0;
+ for (int iSrc=0, iDst=0; iSrc<TBL_COUNT; ++iSrc)
+ {
+ if (m_cRecs[iSrc] != 0)
+ {
+ pDest->m_cRecs[iDst++] = VAL32(m_cRecs[iSrc]);
+ m_maskvalid |= (one << iSrc);
+ ulData += sizeof(m_cRecs[iSrc]);
+ }
+ }
+ // Refresh the mask.
+ pDest->m_maskvalid = VAL64(m_maskvalid);
+
+#if defined(EXTRA_DATA)
+ // Store the extra data.
+ if (m_ulExtra != 0)
+ {
+ *reinterpret_cast<ULONG*>(&pDest->m_cRecs[iDst]) = VAL32(m_ulExtra);
+ ulData += sizeof(ULONG);
+ }
+#endif // 0
+ return ulData;
+} // CMiniMdSchema::SaveTo
+
+//*****************************************************************************
+// Load a schema from a compressed version of the schema.
+// Returns count of bytes consumed. -1 if error.
+//*****************************************************************************
+ULONG
+CMiniMdSchema::LoadFrom(
+ const void *pvData, // Data to load from.
+ ULONG cbData) // Amount of data available.
+{
+ ULONG ulData; // Bytes consumed.
+
+ ulData = sizeof(CMiniMdSchemaBase);
+
+ // Be sure we can get the base part.
+ if (cbData < ulData)
+ return (ULONG)(-1);
+
+ // Transfer the fixed fields. The (void*) casts prevents the compiler
+ // from making bad assumptions about the alignment.
+ memcpy((void *)this, (void *)pvData, sizeof(CMiniMdSchemaBase));
+ static_cast<CMiniMdSchemaBase*>(this)->ConvertEndianness();
+
+ unsigned __int64 maskvalid = m_maskvalid;
+
+ // Transfer the variable fields.
+ memset(m_cRecs, 0, sizeof(m_cRecs));
+ int iDst;
+ for (iDst = 0; iDst < TBL_COUNT; ++iDst, maskvalid >>= 1)
+ {
+ if ((maskvalid & 1) != 0)
+ {
+ // Check integer overflow for: ulData + sizeof(UINT32)
+ ULONG ulDataTemp;
+ if (!ClrSafeInt<ULONG>::addition(ulData, sizeof(UINT32), ulDataTemp))
+ {
+ return (ULONG)(-1);
+ }
+ // Verify that the data is there before touching it.
+ if (cbData < (ulData + sizeof(UINT32)))
+ return (ULONG)(-1);
+
+ m_cRecs[iDst] = GET_UNALIGNED_VAL32((const BYTE *)pvData + ulData);
+ // It's safe to sum, because we checked integer overflow above
+ ulData += sizeof(UINT32);
+ }
+ }
+ // Also accumulate the sizes of any counters that we don't understand.
+ for (iDst = TBL_COUNT; (maskvalid != 0) && (iDst < ((int)sizeof(m_maskvalid) * 8)); ++iDst, maskvalid >>= 1)
+ {
+ if ((maskvalid & 1) != 0)
+ {
+ // Check integer overflow for: ulData += sizeof(UINT32);
+ if (!ClrSafeInt<ULONG>::addition(ulData, sizeof(UINT32), ulData))
+ {
+ return (ULONG)(-1);
+ }
+ // Did we go past end of buffer?
+ if (cbData < ulData)
+ {
+ return (ULONG)(-1);
+ }
+ }
+ }
+
+ // Retrieve the extra 4 bytes data.
+ if ((m_heaps & EXTRA_DATA) != 0)
+ {
+ // Check integer overflow for: ulData + sizeof(UINT32)
+ ULONG ulDataTemp;
+ if (!ClrSafeInt<ULONG>::addition(ulData, sizeof(UINT32), ulDataTemp))
+ {
+ return (ULONG)(-1);
+ }
+ // Verify that the 4 bytes data is there before touching it.
+ if (cbData < (ulData + sizeof(UINT32)))
+ return (ULONG)(-1);
+
+ m_ulExtra = GET_UNALIGNED_VAL32((const BYTE *)pvData + ulData);
+ // Check the size we used for buffer overflow verification above
+ ulData += sizeof(UINT32);
+ }
+
+ // Did we go past end of buffer?
+ if (cbData < ulData)
+ return (ULONG)(-1);
+
+ return ulData;
+} // CMiniMdSchema::LoadFrom
+
+
+const mdToken CMiniMdBase::mdtTypeDefOrRef[3] = {
+ mdtTypeDef,
+ mdtTypeRef,
+ mdtTypeSpec
+};
+
+// This array needs to be ordered the same as the source tables are processed (currently
+// {field, param, property}) for binary search.
+const mdToken CMiniMdBase::mdtHasConstant[3] = {
+ mdtFieldDef,
+ mdtParamDef,
+ mdtProperty
+};
+
+const mdToken CMiniMdBase::mdtHasCustomAttribute[24] = {
+ mdtMethodDef,
+ mdtFieldDef,
+ mdtTypeRef,
+ mdtTypeDef,
+ mdtParamDef,
+ mdtInterfaceImpl,
+ mdtMemberRef,
+ mdtModule,
+ mdtPermission,
+ mdtProperty,
+ mdtEvent,
+ mdtSignature,
+ mdtModuleRef,
+ mdtTypeSpec,
+ mdtAssembly,
+ mdtAssemblyRef,
+ mdtFile,
+ mdtExportedType,
+ mdtManifestResource,
+ mdtGenericParam,
+ mdtGenericParamConstraint,
+ mdtMethodSpec
+};
+
+const mdToken CMiniMdBase::mdtHasFieldMarshal[2] = {
+ mdtFieldDef,
+ mdtParamDef,
+};
+
+const mdToken CMiniMdBase::mdtHasDeclSecurity[3] = {
+ mdtTypeDef,
+ mdtMethodDef,
+ mdtAssembly
+};
+
+const mdToken CMiniMdBase::mdtMemberRefParent[5] = {
+ mdtTypeDef,
+ mdtTypeRef,
+ mdtModuleRef,
+ mdtMethodDef,
+ mdtTypeSpec
+};
+
+const mdToken CMiniMdBase::mdtHasSemantic[2] = {
+ mdtEvent,
+ mdtProperty,
+};
+
+const mdToken CMiniMdBase::mdtMethodDefOrRef[2] = {
+ mdtMethodDef,
+ mdtMemberRef
+};
+
+const mdToken CMiniMdBase::mdtMemberForwarded[2] = {
+ mdtFieldDef,
+ mdtMethodDef
+};
+
+const mdToken CMiniMdBase::mdtImplementation[3] = {
+ mdtFile,
+ mdtAssemblyRef,
+ mdtExportedType
+};
+
+const mdToken CMiniMdBase::mdtCustomAttributeType[5] = {
+ 0,
+ 0,
+ mdtMethodDef,
+ mdtMemberRef,
+ 0
+};
+
+const mdToken CMiniMdBase::mdtResolutionScope[4] = {
+ mdtModule,
+ mdtModuleRef,
+ mdtAssemblyRef,
+ mdtTypeRef
+};
+
+const mdToken CMiniMdBase::mdtTypeOrMethodDef[2] = {
+ mdtTypeDef,
+ mdtMethodDef
+};
+
+const int CMiniMdBase::m_cb[] = {0,1,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5};
+
+//*****************************************************************************
+// Function to encode a token into fewer bits. Looks up token type in array of types.
+//*****************************************************************************
+//<TODO>@consider whether this could be a binary search.</TODO>
+ULONG
+CMiniMdBase::encodeToken(
+ RID rid, // Rid to encode.
+ mdToken typ, // Token type to encode.
+ const mdToken rTokens[], // Table of valid token.
+ ULONG32 cTokens) // Size of the table.
+{
+ mdToken tk = TypeFromToken(typ);
+ size_t ix;
+ for (ix = 0; ix < cTokens; ++ix)
+ {
+ if (rTokens[ix] == tk)
+ break;
+ }
+ _ASSERTE(ix < cTokens);
+ if (ix >= cTokens)
+ return mdTokenNil;
+ //<TODO>@FUTURE: make compile-time calculation</TODO>
+ return (ULONG)((rid << m_cb[cTokens]) | ix);
+} // CMiniMd::encodeToken
+
+
+//*****************************************************************************
+// Helpers for populating the hard-coded schema.
+//*****************************************************************************
+inline BYTE cbRID(ULONG ixMax) { return ixMax > USHRT_MAX ? (BYTE) sizeof(ULONG) : (BYTE) sizeof(USHORT); }
+
+#define _CBTKN(cRecs,tkns) cbRID(cRecs << m_cb[lengthof(tkns)])
+
+//*****************************************************************************
+// Constructor.
+//*****************************************************************************
+CMiniMdBase::CMiniMdBase()
+{
+#undef MiniMdTable
+#define MiniMdTable(tbl) \
+ m_TableDefs[TBL_##tbl] = g_Tables[TBL_##tbl].m_Def; \
+ m_TableDefs[TBL_##tbl].m_pColDefs = BYTEARRAY_TO_COLDES(s_##tbl##Col);
+ MiniMdTables()
+
+ m_TblCount = TBL_COUNT;
+ _ASSERTE(TBL_COUNT == TBL_COUNT_V2); // v2 counts.
+
+ m_fVerifiedByTrustedSource = FALSE;
+
+ // Validator depends on the Table Ids and the Token Ids being identical.
+ // Catch it if this ever breaks.
+ _ASSERTE((TypeFromToken(mdtModule) >> 24) == TBL_Module);
+ _ASSERTE((TypeFromToken(mdtTypeRef) >> 24) == TBL_TypeRef);
+ _ASSERTE((TypeFromToken(mdtTypeDef) >> 24) == TBL_TypeDef);
+ _ASSERTE((TypeFromToken(mdtFieldDef) >> 24) == TBL_Field);
+ _ASSERTE((TypeFromToken(mdtMethodDef) >> 24) == TBL_Method);
+ _ASSERTE((TypeFromToken(mdtParamDef) >> 24) == TBL_Param);
+ _ASSERTE((TypeFromToken(mdtInterfaceImpl) >> 24) == TBL_InterfaceImpl);
+ _ASSERTE((TypeFromToken(mdtMemberRef) >> 24) == TBL_MemberRef);
+ _ASSERTE((TypeFromToken(mdtCustomAttribute) >> 24) == TBL_CustomAttribute);
+ _ASSERTE((TypeFromToken(mdtPermission) >> 24) == TBL_DeclSecurity);
+ _ASSERTE((TypeFromToken(mdtSignature) >> 24) == TBL_StandAloneSig);
+ _ASSERTE((TypeFromToken(mdtEvent) >> 24) == TBL_Event);
+ _ASSERTE((TypeFromToken(mdtProperty) >> 24) == TBL_Property);
+ _ASSERTE((TypeFromToken(mdtModuleRef) >> 24) == TBL_ModuleRef);
+ _ASSERTE((TypeFromToken(mdtTypeSpec) >> 24) == TBL_TypeSpec);
+ _ASSERTE((TypeFromToken(mdtAssembly) >> 24) == TBL_Assembly);
+ _ASSERTE((TypeFromToken(mdtAssemblyRef) >> 24) == TBL_AssemblyRef);
+ _ASSERTE((TypeFromToken(mdtFile) >> 24) == TBL_File);
+ _ASSERTE((TypeFromToken(mdtExportedType) >> 24) == TBL_ExportedType);
+ _ASSERTE((TypeFromToken(mdtManifestResource) >> 24) == TBL_ManifestResource);
+ _ASSERTE((TypeFromToken(mdtGenericParam) >> 24) == TBL_GenericParam);
+ _ASSERTE((TypeFromToken(mdtMethodSpec) >> 24) == TBL_MethodSpec);
+ _ASSERTE((TypeFromToken(mdtGenericParamConstraint) >> 24) == TBL_GenericParamConstraint);
+} // CMiniMdBase::CMiniMdBase
+
+
+//*****************************************************************************
+// Destructor.
+//*****************************************************************************
+CMiniMdBase::~CMiniMdBase()
+{
+ for (ULONG i = 0; i < m_TblCount; i++)
+ {
+ if ((m_TableDefs[i].m_pColDefs != NULL) && UsesAllocatedMemory(m_TableDefs[i].m_pColDefs))
+ {
+ delete[] COLDES_TO_BYTEARRAY(m_TableDefs[i].m_pColDefs);
+ m_TableDefs[i].m_pColDefs = NULL;
+ }
+ }
+} // CMiniMdBase::~CMiniMdBase
+
+//*****************************************************************************
+// Build the schema based on the header data provided.
+// Handle all supported versions, and adjust data structures appropriately.
+//*****************************************************************************
+HRESULT
+CMiniMdBase::SchemaPopulate(
+ const void *pvData, // Pointer to the buffer.
+ ULONG cbData, // Size of the buffer.
+ ULONG *pcbUsed) // Put size of the header here.
+{
+ HRESULT hr;
+ ULONG cb; // Bytes read for header.
+ ULONG cbTables; // Bytes needed for tables.
+ ULONG cbTotal; // Bytes read for header + needed for tables.
+
+ // Uncompress the schema from the buffer into our structures.
+ cb = m_Schema.LoadFrom(pvData, cbData);
+
+ if ((cb > cbData) || (cb == (ULONG)(-1)))
+ {
+ Debug_ReportError("Schema is not in MetaData block.");
+ return PostError(CLDB_E_FILE_CORRUPT);
+ }
+
+ // Is this the "native" version of the metadata for this runtime?
+ if ((m_Schema.m_major != METAMODEL_MAJOR_VER) || (m_Schema.m_minor != METAMODEL_MINOR_VER))
+ {
+ // No it's not. Is this an older version that we support?
+
+#ifndef FEATURE_METADATA_STANDALONE_WINRT
+ // Is this v1.0?
+ if ((m_Schema.m_major == METAMODEL_MAJOR_VER_V1_0) &&
+ (m_Schema.m_minor == METAMODEL_MINOR_VER_V1_0))
+ {
+ // Older version has fewer tables.
+ m_TblCount = TBL_COUNT_V1;
+ }
+ else if ((m_Schema.m_major == METAMODEL_MAJOR_VER_B1) &&
+ (m_Schema.m_minor == METAMODEL_MINOR_VER_B1))
+ {
+ // 1.1 had a different type of GenericParam table
+ m_TableDefs[TBL_GenericParam] = g_Table_GenericParamV1_1.m_Def;
+ m_TableDefs[TBL_GenericParam].m_pColDefs = BYTEARRAY_TO_COLDES(s_GenericParamCol);
+ }
+ else
+#endif //!FEATURE_METADATA_STANDALONE_WINRT
+ { // We don't support this version of the metadata
+ Debug_ReportError("Unsupported version of MetaData.");
+ return PostError(CLDB_E_FILE_OLDVER, m_Schema.m_major, m_Schema.m_minor);
+ }
+ }
+
+ // Populate the schema, based on the row counts and heap sizes.
+ IfFailRet(SchemaPopulate2(&cbTables));
+
+ // Check that header plus tables fits within the size given.
+ if (!ClrSafeInt<ULONG>::addition(cb, cbTables, cbTotal) || (cbTotal > cbData))
+ {
+ Debug_ReportError("Tables are not within MetaData block.");
+ return PostError(CLDB_E_FILE_CORRUPT);
+ }
+
+ *pcbUsed = cb;
+ return S_OK;
+} // CMiniMdBase::SchemaPopulate
+
+//*****************************************************************************
+// Initialize from another MD
+//*****************************************************************************
+HRESULT
+CMiniMdBase::SchemaPopulate(
+ const CMiniMdBase &that)
+{
+ HRESULT hr;
+ // Copy over the schema.
+ m_Schema = that.m_Schema;
+
+ // Adjust for prior versions.
+ if (m_Schema.m_major != METAMODEL_MAJOR_VER || m_Schema.m_minor != METAMODEL_MINOR_VER)
+ {
+ if ((m_Schema.m_major == METAMODEL_MAJOR_VER_V1_0) && (m_Schema.m_minor == METAMODEL_MINOR_VER_V1_0))
+ { // Older version has fewer tables.
+ m_TblCount = that.m_TblCount;
+ _ASSERTE(m_TblCount == TBL_COUNT_V1);
+ }
+ else if (m_Schema.m_major == METAMODEL_MAJOR_VER_B1 && m_Schema.m_minor == METAMODEL_MINOR_VER_B1)
+ {
+ // 1.1 had a different type of GenericParam table
+ m_TableDefs[TBL_GenericParam] = g_Table_GenericParamV1_1.m_Def;
+ m_TableDefs[TBL_GenericParam].m_pColDefs = BYTEARRAY_TO_COLDES(s_GenericParamCol);
+ }
+ // Is it a supported old version? This should never fail!
+ else
+ {
+ Debug_ReportError("Initializing on an unknown schema version");
+ return PostError(CLDB_E_FILE_OLDVER, m_Schema.m_major,m_Schema.m_minor);
+ }
+ }
+
+ IfFailRet(SchemaPopulate2(NULL));
+
+ return S_OK;
+} // CMiniMdBase::SchemaPopulate
+
+//*****************************************************************************
+// Iterate the tables, and fix the column sizes, based on size of data.
+//*****************************************************************************
+HRESULT CMiniMdBase::SchemaPopulate2(
+ ULONG *pcbTables, // [out, optional] Put size needed for tables here.
+ int bExtra) // Reserve an extra bit for rid columns?
+{
+ HRESULT hr; // A result.
+ ULONG cbTotal = 0; // Total size of all tables.
+
+ // How big are the various pool inidices?
+ m_iStringsMask = (m_Schema.m_heaps & CMiniMdSchema::HEAP_STRING_4) ? 0xffffffff : 0xffff;
+ m_iGuidsMask = (m_Schema.m_heaps & CMiniMdSchema::HEAP_GUID_4) ? 0xffffffff : 0xffff;
+ m_iBlobsMask = (m_Schema.m_heaps & CMiniMdSchema::HEAP_BLOB_4) ? 0xffffffff : 0xffff;
+
+ // Make extra bits exactly zero or one bit.
+ if (bExtra)
+ bExtra = 1;
+
+ // Until ENC, make extra bits exactly zero.
+ bExtra = 0;
+
+ // For each table...
+ for (int ixTbl = 0; ixTbl < (int)m_TblCount; ++ixTbl)
+ {
+ IfFailRet(InitColsForTable(m_Schema, ixTbl, &m_TableDefs[ixTbl], bExtra, TRUE));
+
+ // Accumulate size of this table.
+ // Check integer overflow for table size: USHORT * ULONG: m_TableDefs[ixTbl].m_cbRec * GetCountRecs(ixTbl)
+ ULONG cbTable;
+ if (!ClrSafeInt<ULONG>::multiply(m_TableDefs[ixTbl].m_cbRec, GetCountRecs(ixTbl), cbTable))
+ {
+ Debug_ReportError("Table is too large - size overflow.");
+ return PostError(CLDB_E_FILE_CORRUPT);
+ }
+ // Check integer overflow for all tables so far: cbTotal += cbTable
+ if (!ClrSafeInt<ULONG>::addition(cbTotal, cbTable, cbTotal))
+ {
+ Debug_ReportError("Tables are too large - size overflow.");
+ return PostError(CLDB_E_FILE_CORRUPT);
+ }
+ }
+ // Check that unused table (e.g. generic tables in v1 format) are empty
+ for (ULONG ixTbl = m_TblCount; ixTbl < TBL_COUNT; ixTbl++)
+ {
+ // All unused tables have to be empty - malicious assemblies can have v1 format version, but can
+ // contain non-empty v2-only tables, this will catch it and refuse to load such assemblies
+ if (GetCountRecs(ixTbl) != 0)
+ {
+ Debug_ReportError("Invalid table present - 2.0 table in v1.x image.");
+ return PostError(CLDB_E_FILE_CORRUPT);
+ }
+ }
+
+ // Let caller know sizes required.
+ if (pcbTables != NULL)
+ *pcbTables = cbTotal;
+
+ return S_OK;
+} // CMiniMdBase::SchemaPopulate2
+
+//*****************************************************************************
+// Get the template table definition for a given table.
+//*****************************************************************************
+const CMiniTableDef *
+CMiniMdBase::GetTableDefTemplate(
+ int ixTbl)
+{
+ const CMiniTableDef *pTemplate; // the return value.
+
+ // Return the table definition for the given table. Account for version of schema.
+ if ((m_Schema.m_major == METAMODEL_MAJOR_VER_B1) && (m_Schema.m_minor == METAMODEL_MINOR_VER_B1) && (ixTbl == TBL_GenericParam))
+ {
+ pTemplate = &g_Table_GenericParamV1_1.m_Def;
+ }
+ else
+ {
+ pTemplate = &g_Tables[ixTbl].m_Def;
+ }
+
+ return pTemplate;
+} // CMiniMdBase::GetTableDefTemplate
+
+//*****************************************************************************
+// Initialize the column defs for a table, based on their types and sizes.
+//*****************************************************************************
+HRESULT
+CMiniMdBase::InitColsForTable(
+ CMiniMdSchema &Schema, // Schema with sizes.
+ int ixTbl, // Index of table to init.
+ CMiniTableDef *pTable, // Table to init.
+ int bExtra, // Extra bits for rid column.
+ BOOL fUsePointers) // Should we have pTable point to it's Column Descriptors, or
+ // should we write the data into the structure
+{
+ const CMiniTableDef *pTemplate; // Template table definition.
+ CMiniColDef pCols[9]; // The col defs to init.
+ BYTE iOffset; // Running size of a record.
+ BYTE iSize; // Size of a field.
+ HRESULT hr = S_OK;
+
+ _ASSERTE((bExtra == 0) || (bExtra == 1));
+ _ASSERTE(NumItems(pCols) >= pTable->m_cCols);
+
+ bExtra = 0;//<TODO>@FUTURE: save in schema header. until then use 0.</TODO>
+
+ iOffset = 0;
+
+ pTemplate = GetTableDefTemplate(ixTbl);
+
+ PREFIX_ASSUME(pTemplate->m_pColDefs != NULL);
+
+ // For each column in the table...
+ for (ULONG ixCol = 0; ixCol < pTable->m_cCols; ++ixCol)
+ {
+ // Initialize from the template values (type, maybe offset, size).
+ pCols[ixCol] = pTemplate->m_pColDefs[ixCol];
+
+ // Is the field a RID into a table?
+ if (pCols[ixCol].m_Type <= iRidMax)
+ {
+ iSize = cbRID(Schema.m_cRecs[pCols[ixCol].m_Type] << bExtra);
+ }
+ else
+ // Is the field a coded token?
+ if (pCols[ixCol].m_Type <= iCodedTokenMax)
+ {
+ ULONG iCdTkn = pCols[ixCol].m_Type - iCodedToken;
+ ULONG cRecs = 0;
+
+ _ASSERTE(iCdTkn < lengthof(g_CodedTokens));
+ CCodedTokenDef const *pCTD = &g_CodedTokens[iCdTkn];
+
+ // Iterate the token list of this coded token.
+ for (ULONG ixToken=0; ixToken<pCTD->m_cTokens; ++ixToken)
+ { // Ignore string tokens.
+ if (pCTD->m_pTokens[ixToken] != mdtString)
+ {
+ // Get the table for the token.
+ ULONG nTokenTable = CMiniMdRW::GetTableForToken(pCTD->m_pTokens[ixToken]);
+ _ASSERTE(nTokenTable < TBL_COUNT);
+ // If largest token seen so far, remember it.
+ if (Schema.m_cRecs[nTokenTable] > cRecs)
+ cRecs = Schema.m_cRecs[nTokenTable];
+ }
+ }
+
+ iSize = cbRID(cRecs << (bExtra + m_cb[pCTD->m_cTokens]));
+
+ }
+ else
+ { // Fixed type.
+ switch (pCols[ixCol].m_Type)
+ {
+ case iBYTE:
+ iSize = 1;
+ _ASSERTE(pCols[ixCol].m_cbColumn == iSize);
+ _ASSERTE(pCols[ixCol].m_oColumn == iOffset);
+ break;
+ case iSHORT:
+ case iUSHORT:
+ iSize = 2;
+ _ASSERTE(pCols[ixCol].m_cbColumn == iSize);
+ _ASSERTE(pCols[ixCol].m_oColumn == iOffset);
+ break;
+ case iLONG:
+ case iULONG:
+ iSize = 4;
+ _ASSERTE(pCols[ixCol].m_cbColumn == iSize);
+ _ASSERTE(pCols[ixCol].m_oColumn == iOffset);
+ break;
+ case iSTRING:
+ iSize = (Schema.m_heaps & CMiniMdSchema::HEAP_STRING_4) ? 4 : 2;
+ break;
+ case iGUID:
+ iSize = (Schema.m_heaps & CMiniMdSchema::HEAP_GUID_4) ? 4 : 2;
+ break;
+ case iBLOB:
+ iSize = (Schema.m_heaps & CMiniMdSchema::HEAP_BLOB_4) ? 4 : 2;
+ break;
+ default:
+ _ASSERTE(!"Unexpected schema type");
+ iSize = 0;
+ break;
+ }
+ }
+
+ // Now save the size and offset.
+ pCols[ixCol].m_oColumn = iOffset;
+ pCols[ixCol].m_cbColumn = iSize;
+
+ // Align to 2 bytes.
+ iSize += iSize & 1;
+
+ iOffset += iSize;
+ }
+ // Record size of entire record.
+ pTable->m_cbRec = iOffset;
+
+ _ASSERTE(pTable->m_pColDefs != NULL);
+
+ // Can we write to the memory
+ if (!fUsePointers)
+ {
+ memcpy(pTable->m_pColDefs, pCols, sizeof(CMiniColDef)*pTable->m_cCols);
+ }
+ else
+ {
+ // We'll need to have pTable->m_pColDefs point to some data instead
+ hr = SetNewColumnDefinition(pTable, pCols, ixTbl);
+ }
+ // If no key, set to a distinct value.
+ if (pTable->m_iKey >= pTable->m_cCols)
+ pTable->m_iKey = (BYTE) -1;
+
+ return hr;
+} // CMiniMdBase::InitColsForTable
+
+//*****************************************************************************
+// Place a new Column Definition into the metadata.
+//*****************************************************************************
+HRESULT
+CMiniMdBase::SetNewColumnDefinition(
+ CMiniTableDef *pTable,
+ CMiniColDef *pCols,
+ DWORD ixTbl)
+{
+ // Look up the global cache to see if we can use a cached copy
+ if (UsesAllocatedMemory(pCols) ||
+ !FindSharedColDefs(pTable, pCols, ixTbl))
+ {
+ // See if we've already allocated memory for this item
+
+ if (!UsesAllocatedMemory(pTable->m_pColDefs))
+ {
+ // We don't have this column definition cached. Allocate new memory for it.
+ // Notice, we allocate one more byte than necessary, so we can 'mark' this chunk of memory
+ // as allocated so we can free it later.
+
+ BYTE *newMemory = new (nothrow) BYTE[(sizeof(CMiniColDef)*pTable->m_cCols)+1];
+
+ if (newMemory == NULL)
+ return E_OUTOFMEMORY;
+
+ // Mark the first byte in this as with the "allocated memory marker"
+ *newMemory = ALLOCATED_MEMORY_MARKER;
+
+ // Have the pointer point to the first Column Descriptor
+ pTable->m_pColDefs = BYTEARRAY_TO_COLDES(newMemory);
+ }
+
+ memcpy(pTable->m_pColDefs, pCols, sizeof(CMiniColDef)*pTable->m_cCols);
+ }
+
+ return S_OK;
+} // CMiniMdBase::SetNewColumnDefinition
+
+
+//*****************************************************************************
+// Get the count of records in a table. Virtual.
+//*****************************************************************************
+ULONG
+CMiniMdBase::GetCountRecs(
+ ULONG ixTbl)
+{
+ _ASSERTE(ixTbl < TBL_COUNT);
+ return m_Schema.m_cRecs[ixTbl];
+} // CMiniMdBase::GetCountRecs
+
+//*****************************************************************************
+// Search a table for multiple (adjacent) rows containing the given
+// key value. EG, InterfaceImpls all point back to the implementing class.
+//*****************************************************************************
+__checkReturn
+HRESULT
+CMiniMdBase::SearchTableForMultipleRows(
+ ULONG ixTbl, // Table to search.
+ CMiniColDef sColumn, // Sorted key column, containing search value.
+ ULONG ulTarget, // Target for search.
+ RID *pEnd, // [OPTIONAL, OUT]
+ RID *pFoundRid) // First RID found, or 0.
+{
+ HRESULT hr;
+ ULONG ridBegin; // RID of first entry.
+ ULONG ridEnd; // RID of first entry past last entry.
+
+ // Search for any entry in the table.
+ IfFailRet(vSearchTable(ixTbl, sColumn, ulTarget, &ridBegin));
+
+ // If nothing found, return invalid RID.
+ if (ridBegin == 0)
+ {
+ if (pEnd != NULL)
+ {
+ *pEnd = 0;
+ }
+ *pFoundRid = 0;
+ return S_OK;
+ }
+
+ // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ // If you change the rows touched while searching, please update
+ // CMiniMdRW::GetHotMetadataTokensSearchAware
+ // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+
+ // End will be at least one larger than found record.
+ ridEnd = ridBegin + 1;
+
+ // Search back to start of group.
+ for (;;)
+ {
+ void *pRow;
+ if (ridBegin <= 1)
+ {
+ break;
+ }
+ IfFailRet(vGetRow(ixTbl, ridBegin-1, &pRow));
+ if (getIX(pRow, sColumn) != ulTarget)
+ {
+ break;
+ }
+ --ridBegin;
+ }
+
+ // If desired, search forward to end of group.
+ if (pEnd != NULL)
+ {
+ for (;;)
+ {
+ void *pRow;
+ if (ridEnd > GetCountRecs(ixTbl))
+ {
+ break;
+ }
+ IfFailRet(vGetRow(ixTbl, ridEnd, &pRow));
+ if (getIX(pRow, sColumn) != ulTarget)
+ {
+ break;
+ }
+ ++ridEnd;
+ }
+ *pEnd = ridEnd;
+ }
+
+ *pFoundRid = ridBegin;
+ return S_OK;
+} // CMiniMdBase::SearchTableForMultipleRows
+
+
+#if BIGENDIAN
+// Endian Swaps the passed in blob representing a constant into the passed in StgPool
+HRESULT
+CMiniMdBase::SwapConstant(
+ const void *pBlobValue, // Original Value pointer
+ DWORD dwType, // Type of the constant
+ void *pConstant, // [Out] Location to store constant into
+ ULONG ValueLength) // [In] Length of constant
+{
+ HRESULT hr = NOERROR;
+
+ switch (dwType)
+ {
+ case ELEMENT_TYPE_BOOLEAN:
+ case ELEMENT_TYPE_I1:
+ case ELEMENT_TYPE_U1:
+ case ELEMENT_TYPE_VOID:
+ // Just return the value
+ *(BYTE *)pConstant = *(BYTE *)pBlobValue;
+ return NOERROR;
+
+ case ELEMENT_TYPE_I2:
+ case ELEMENT_TYPE_U2:
+ case ELEMENT_TYPE_CHAR:
+ _ASSERTE(ValueLength == 2);
+ *(SHORT *)pConstant = GET_UNALIGNED_VAL16(pBlobValue);
+ break;
+ case ELEMENT_TYPE_CLASS:
+ case ELEMENT_TYPE_I4:
+ case ELEMENT_TYPE_U4:
+ _ASSERTE(ValueLength == 4);
+ *(__int32 *)pConstant = GET_UNALIGNED_VAL32(pBlobValue);
+ break;
+ case ELEMENT_TYPE_R4:
+ {
+ __int32 Value = GET_UNALIGNED_VAL32(pBlobValue);
+ *(float *)pConstant = (float &)Value;
+ }
+ break;
+
+ case ELEMENT_TYPE_R8:
+ {
+ __int64 Value = GET_UNALIGNED_VAL64(pBlobValue);
+ *(double *)pConstant = (double &) Value;
+ }
+ break;
+
+ case ELEMENT_TYPE_I8:
+ case ELEMENT_TYPE_U8:
+ _ASSERTE(ValueLength == 8);
+ *(__int64 *)pConstant = GET_UNALIGNED_VAL64(pBlobValue);
+ break;
+ case ELEMENT_TYPE_STRING:
+ memcpy(pConstant, pBlobValue, ValueLength);
+ SwapStringLength((WCHAR *)pConstant, (ValueLength)/sizeof(WCHAR));
+ break;
+ default:
+ _ASSERTE(!"BAD TYPE!");
+ return E_INVALIDARG;
+ break;
+ }
+ return hr;
+} // CMiniMdBase::SwapConstant
+#endif //BIGENDIAN
+
+//*****************************************************************************
+// It is non-trivial to sort propertymap. VB is generating properties in
+// non-sorted order!!!
+//*****************************************************************************
+HRESULT
+CMiniMdBase::FindPropertyMapFor(
+ RID ridParent,
+ RID *pFoundRid)
+{
+ HRESULT hr;
+ ULONG i;
+ ULONG iCount;
+ void *pRec;
+ RID rid;
+
+ // If the table is sorted, use binary search. However we can only trust
+ // the sorted bit if we have verified it (see definition in MetaModel.h)
+ if (IsVerified() && m_Schema.IsSorted(TBL_PropertyMap))
+ {
+ return vSearchTable(TBL_PropertyMap,
+ _COLDEF(PropertyMap,Parent),
+ ridParent,
+ pFoundRid);
+ }
+ else
+ {
+ iCount = GetCountRecs(TBL_PropertyMap);
+
+ // loop through all LocalVar
+ for (i = 1; i <= iCount; i++)
+ {
+ IfFailRet(vGetRow(TBL_PropertyMap, i, &pRec));
+
+ // linear search for propertymap record
+ rid = getIX(pRec, _COLDEF(PropertyMap,Parent));
+ if (rid == ridParent)
+ {
+ *pFoundRid = i;
+ return S_OK;
+ }
+ }
+
+ *pFoundRid = 0;
+ return S_OK;
+ }
+
+} // CMiniMdBase::FindPropertyMapFor
+
+
+//*****************************************************************************
+// It is non-trivial to sort eventmap. VB is generating events in
+// non-sorted order!!!
+//*****************************************************************************
+__checkReturn
+HRESULT
+CMiniMdBase::FindEventMapFor(
+ RID ridParent,
+ RID *pFoundRid)
+{
+ HRESULT hr;
+ ULONG i;
+ ULONG iCount;
+ void *pRec;
+ RID rid;
+
+ // If the table is sorted, use binary search. However we can only trust
+ // the sorted bit if we have verified it (see definition in MetaModel.h)
+ if (IsVerified() && m_Schema.IsSorted(TBL_EventMap))
+ {
+ return vSearchTable(TBL_EventMap,
+ _COLDEF(EventMap,Parent),
+ ridParent,
+ pFoundRid);
+ }
+ else
+ {
+ iCount = GetCountRecs(TBL_EventMap);
+
+ // loop through all LocalVar
+ for (i = 1; i <= iCount; i++)
+ {
+ IfFailRet(vGetRow(TBL_EventMap, i, &pRec));
+
+ // linear search for propertymap record
+ rid = getIX(pRec, _COLDEF(EventMap,Parent));
+ if (rid == ridParent)
+ {
+ *pFoundRid = i;
+ return S_OK;
+ }
+ }
+
+ *pFoundRid = 0;
+ return S_OK;
+ }
+} // CMiniMdBase::FindEventMapFor
+
+
+//*****************************************************************************
+// Search for a custom value with a given type.
+//*****************************************************************************
+__checkReturn
+HRESULT
+CMiniMdBase::FindCustomAttributeFor(
+ RID rid, // The object's rid.
+ mdToken tkObj, // The object's type.
+ mdToken tkType, // Type of custom value.
+ RID *pFoundRid) // RID of custom value, or 0.
+{
+ HRESULT hr;
+ int ixFound; // index of some custom value row.
+ ULONG ulTarget = encodeToken(rid,tkObj,mdtHasCustomAttribute,lengthof(mdtHasCustomAttribute)); // encoded token representing target.
+ ULONG ixCur; // Current row being examined.
+ mdToken tkFound; // Type of some custom value row.
+ void *pCur; // A custom value entry.
+
+ // Search for any entry in CustomAttribute table. Convert to RID.
+ IfFailRet(vSearchTable(TBL_CustomAttribute, _COLDEF(CustomAttribute,Parent), ulTarget, (RID *)&ixFound));
+ if (ixFound == 0)
+ {
+ *pFoundRid = 0;
+ return S_OK;
+ }
+
+ // Found an entry that matches the item. Could be anywhere in a range of
+ // custom values for the item, somewhat at random. Search for a match
+ // on name. On entry to the first loop, we know the object is the desired
+ // one, so the object test is at the bottom.
+ ixCur = ixFound;
+ IfFailRet(vGetRow(TBL_CustomAttribute, ixCur, &pCur));
+ for(;;)
+ {
+ // Test the type of the current row.
+ tkFound = getIX(pCur, _COLDEF(CustomAttribute,Type));
+ tkFound = decodeToken(tkFound, mdtCustomAttributeType, lengthof(mdtCustomAttributeType));
+ if (tkFound == tkType)
+ {
+ *pFoundRid = ixCur;
+ return S_OK;
+ }
+ // Was this the last row of the CustomAttribute table?
+ if (ixCur == GetCountRecs(TBL_CustomAttribute))
+ break;
+ // No match, more rows, try for the next row.
+ ++ixCur;
+ // Get the row and see if it is for the same object.
+ IfFailRet(vGetRow(TBL_CustomAttribute, ixCur, &pCur));
+ if (getIX(pCur, _COLDEF(CustomAttribute,Parent)) != ulTarget)
+ break;
+ }
+ // Didn't find the name looking up. Try looking down.
+ ixCur = ixFound - 1;
+ for(;;)
+ {
+ // Run out of table yet?
+ if (ixCur == 0)
+ break;
+ // Get the row and see if it is for the same object.
+ IfFailRet(vGetRow(TBL_CustomAttribute, ixCur, &pCur));
+ // still looking at the same object?
+ if (getIX(pCur, _COLDEF(CustomAttribute,Parent)) != ulTarget)
+ break;
+ // Test the type of the current row.
+ tkFound = getIX(pCur, _COLDEF(CustomAttribute,Type));
+ tkFound = decodeToken(tkFound, mdtCustomAttributeType, lengthof(mdtCustomAttributeType));
+ if (tkFound == tkType)
+ {
+ *pFoundRid = ixCur;
+ return S_OK;
+ }
+ // No match, try for the previous row.
+ --ixCur;
+ }
+ // Didn't find anything.
+ *pFoundRid = 0;
+ return S_OK;
+} // CMiniMdBase::FindCustomAttributeFor
+
+//*****************************************************************************
+// See if we can find a globally shared Column Def Array for this table
+//*****************************************************************************
+BOOL
+CMiniMdBase::FindSharedColDefs(
+ CMiniTableDef *pTable,
+ CMiniColDef *pColsToMatch,
+ DWORD ixTbl)
+{
+ // The majority of the time, m_pColDefs will point to the correct Column Definition Array.
+ if (!memcmp(pTable->m_pColDefs, pColsToMatch, sizeof(CMiniColDef)*(pTable->m_cCols)))
+ return TRUE;
+
+ else
+ {
+ // m_pColDefs points to a set of Column Def Arrays, with the byte previous to it the number
+ // of column descriptors that we have.
+ CMiniColDef *pListOfColumnDefs = BYTEARRAY_TO_COLDES(s_TableColumnDescriptors[ixTbl]);
+
+ BYTE nNumColDes = *(s_TableColumnDescriptors[ixTbl]);
+
+ // Start at '1' since we already compared the first set of column definitions above.
+ for (int i = 1; i < nNumColDes; i++)
+ {
+ pListOfColumnDefs += pTable->m_cCols;
+
+ if (!memcmp(pListOfColumnDefs, pColsToMatch, sizeof(CMiniColDef)*(pTable->m_cCols)))
+ {
+ pTable->m_pColDefs = pListOfColumnDefs;
+ return TRUE;
+ }
+ }
+ }
+
+ // We weren't able to find a shared column definition
+ return FALSE;
+}// CMiniMdBase::FindSharedColDefs
+
+//*****************************************************************************
+// Determines where the Table Def's Column Definitions used shared memory or
+// allocated memory
+//*****************************************************************************
+BOOL
+CMiniMdBase::UsesAllocatedMemory(
+ CMiniColDef *pCols)
+{
+ BYTE *pMem = COLDES_TO_BYTEARRAY(pCols);
+
+ // If the byte preceding this pointer is -1, then we allocated it and it must be freed
+ return (*pMem == ALLOCATED_MEMORY_MARKER);
+}// CMiniMdBase::UsesAllocatedMemory
diff --git a/src/md/runtime/metamodelcolumndefs.h b/src/md/runtime/metamodelcolumndefs.h
new file mode 100644
index 0000000000..311ec97078
--- /dev/null
+++ b/src/md/runtime/metamodelcolumndefs.h
@@ -0,0 +1,401 @@
+// 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.
+//*****************************************************************************
+// MetaModelColumnDefs.h -- Table definitions for MetaData.
+//
+
+//
+//*****************************************************************************
+
+#if METAMODEL_MAJOR_VER != 2
+#if METAMODEL_MAJOR_VER != 1
+#error "METAMODEL_MAJOR_VER other than 1 or 2 is not implemented"
+#endif
+#endif
+ //
+ // These are used by #defining appropriately, then #including this file.
+ //
+ //-------------------------------------------------------------------------
+ //Module
+ SCHEMA_TABLE_START(Module)
+ SCHEMA_ITEM(Module, USHORT, Generation)
+ SCHEMA_ITEM_STRING(Module, Name)
+ SCHEMA_ITEM_GUID(Module, Mvid)
+ SCHEMA_ITEM_GUID(Module, EncId)
+ SCHEMA_ITEM_GUID(Module, EncBaseId)
+ SCHEMA_TABLE_END(Module)
+
+ //-------------------------------------------------------------------------
+ //TypeRef
+ SCHEMA_TABLE_START(TypeRef)
+ SCHEMA_ITEM_CDTKN(TypeRef, ResolutionScope, ResolutionScope)
+ SCHEMA_ITEM_STRING(TypeRef, Name)
+ SCHEMA_ITEM_STRING(TypeRef, Namespace)
+ SCHEMA_TABLE_END(TypeRef)
+
+ //-------------------------------------------------------------------------
+ // TypeDef
+ SCHEMA_TABLE_START(TypeDef)
+ SCHEMA_ITEM(TypeDef, ULONG, Flags)
+ SCHEMA_ITEM_STRING(TypeDef, Name)
+ SCHEMA_ITEM_STRING(TypeDef, Namespace)
+ SCHEMA_ITEM_CDTKN(TypeDef, Extends, TypeDefOrRef)
+ SCHEMA_ITEM_RID(TypeDef, FieldList, Field)
+ SCHEMA_ITEM_RID(TypeDef, MethodList, Method)
+ SCHEMA_TABLE_END(TypeDef)
+
+ //-------------------------------------------------------------------------
+ //FieldPtr
+ SCHEMA_TABLE_START(FieldPtr)
+ SCHEMA_ITEM_NOFIXED()
+ SCHEMA_ITEM_RID(FieldPtr, Field, Field)
+ SCHEMA_TABLE_END(FieldPtr)
+
+ //-------------------------------------------------------------------------
+ //Field
+ SCHEMA_TABLE_START(Field)
+ SCHEMA_ITEM(Field, USHORT, Flags)
+ SCHEMA_ITEM_STRING(Field,Name)
+ SCHEMA_ITEM_BLOB(Field,Signature)
+ SCHEMA_TABLE_END(Field)
+
+ //-------------------------------------------------------------------------
+ //MethodPtr
+ SCHEMA_TABLE_START(MethodPtr)
+ SCHEMA_ITEM_NOFIXED()
+ SCHEMA_ITEM_RID(MethodPtr, Method, Method)
+ SCHEMA_TABLE_END(MethodPtr)
+
+ //-------------------------------------------------------------------------
+ //Method
+ SCHEMA_TABLE_START(Method)
+ SCHEMA_ITEM(Method, ULONG, RVA)
+ SCHEMA_ITEM(Method, USHORT, ImplFlags)
+ SCHEMA_ITEM(Method, USHORT, Flags)
+ SCHEMA_ITEM_STRING(Method,Name)
+ SCHEMA_ITEM_BLOB(Method,Signature)
+ SCHEMA_ITEM_RID(Method,ParamList,Param)
+ SCHEMA_TABLE_END(Method)
+
+ //-------------------------------------------------------------------------
+ //ParamPtr
+ SCHEMA_TABLE_START(ParamPtr)
+ SCHEMA_ITEM_NOFIXED()
+ SCHEMA_ITEM_RID(ParamPtr, Param, Param)
+ SCHEMA_TABLE_END(ParamPtr)
+
+ //-------------------------------------------------------------------------
+ // Param
+ SCHEMA_TABLE_START(Param)
+ SCHEMA_ITEM(Param, USHORT, Flags)
+ SCHEMA_ITEM(Param, USHORT, Sequence)
+ SCHEMA_ITEM_STRING(Param,Name)
+ SCHEMA_TABLE_END(Param)
+
+ //-------------------------------------------------------------------------
+ //InterfaceImpl
+ SCHEMA_TABLE_START(InterfaceImpl)
+ SCHEMA_ITEM_RID(InterfaceImpl,Class,TypeDef)
+ SCHEMA_ITEM_CDTKN(InterfaceImpl,Interface,TypeDefOrRef)
+ SCHEMA_TABLE_END(InterfaceImpl)
+
+ //-------------------------------------------------------------------------
+ //MemberRef
+ SCHEMA_TABLE_START(MemberRef)
+ SCHEMA_ITEM_NOFIXED()
+ SCHEMA_ITEM_CDTKN(MemberRef,Class,MemberRefParent)
+ SCHEMA_ITEM_STRING(MemberRef,Name)
+ SCHEMA_ITEM_BLOB(MemberRef,Signature)
+ SCHEMA_TABLE_END(MemberRef)
+
+ //-------------------------------------------------------------------------
+ //Constant
+ SCHEMA_TABLE_START(Constant)
+ SCHEMA_ITEM(Constant, BYTE, Type)
+ SCHEMA_ITEM_CDTKN(Constant,Parent,HasConstant)
+ SCHEMA_ITEM_BLOB(Constant,Value)
+ SCHEMA_TABLE_END(Constant)
+
+ //-------------------------------------------------------------------------
+ //CustomAttribute
+ SCHEMA_TABLE_START(CustomAttribute)
+ SCHEMA_ITEM_NOFIXED()
+ SCHEMA_ITEM_CDTKN(CustomAttribute,Parent,HasCustomAttribute)
+ SCHEMA_ITEM_CDTKN(CustomAttribute,Type,CustomAttributeType)
+ SCHEMA_ITEM_BLOB(CustomAttribute,Value)
+ SCHEMA_TABLE_END(CustomAttribute)
+
+ //-------------------------------------------------------------------------
+ //FieldMarshal
+ SCHEMA_TABLE_START(FieldMarshal)
+ SCHEMA_ITEM_NOFIXED()
+ SCHEMA_ITEM_CDTKN(FieldMarshal,Parent,HasFieldMarshal)
+ SCHEMA_ITEM_BLOB(FieldMarshal,NativeType)
+ SCHEMA_TABLE_END(FieldMarshal)
+
+ //-------------------------------------------------------------------------
+ //DeclSecurity
+ SCHEMA_TABLE_START(DeclSecurity)
+ SCHEMA_ITEM(DeclSecurity, SHORT, Action)
+ SCHEMA_ITEM_CDTKN(DeclSecurity,Parent,HasDeclSecurity)
+ SCHEMA_ITEM_BLOB(DeclSecurity,PermissionSet)
+ SCHEMA_TABLE_END(DeclSecurity)
+
+ //-------------------------------------------------------------------------
+ //ClassLayout
+ SCHEMA_TABLE_START(ClassLayout)
+ SCHEMA_ITEM(ClassLayout, USHORT, PackingSize)
+ SCHEMA_ITEM(ClassLayout, ULONG, ClassSize)
+ SCHEMA_ITEM_RID(ClassLayout,Parent,TypeDef)
+ SCHEMA_TABLE_END(ClassLayout)
+
+ //-------------------------------------------------------------------------
+ //FieldLayout
+ SCHEMA_TABLE_START(FieldLayout)
+ SCHEMA_ITEM(FieldLayout, ULONG, OffSet)
+ SCHEMA_ITEM_RID(FieldLayout, Field, Field)
+ SCHEMA_TABLE_END(FieldLayout)
+
+ //-------------------------------------------------------------------------
+ //StandAloneSig
+ SCHEMA_TABLE_START(StandAloneSig)
+ SCHEMA_ITEM_NOFIXED()
+ SCHEMA_ITEM_BLOB(StandAloneSig,Signature)
+ SCHEMA_TABLE_END(StandAloneSig)
+
+ //-------------------------------------------------------------------------
+ //EventMap
+ SCHEMA_TABLE_START(EventMap)
+ SCHEMA_ITEM_NOFIXED()
+ SCHEMA_ITEM_RID(EventMap,Parent,TypeDef)
+ SCHEMA_ITEM_RID(EventMap,EventList,Event)
+ SCHEMA_TABLE_END(EventMap)
+
+ //-------------------------------------------------------------------------
+ //EventPtr
+ SCHEMA_TABLE_START(EventPtr)
+ SCHEMA_ITEM_NOFIXED()
+ SCHEMA_ITEM_RID(EventPtr, Event, Event)
+ SCHEMA_TABLE_END(EventPtr)
+
+ //-------------------------------------------------------------------------
+ //Event
+ SCHEMA_TABLE_START(Event)
+ SCHEMA_ITEM(Event, USHORT, EventFlags)
+ SCHEMA_ITEM_STRING(Event,Name)
+ SCHEMA_ITEM_CDTKN(Event,EventType,TypeDefOrRef)
+ SCHEMA_TABLE_END(Event)
+
+ //-------------------------------------------------------------------------
+ //PropertyMap
+ SCHEMA_TABLE_START(PropertyMap)
+ SCHEMA_ITEM_NOFIXED()
+ SCHEMA_ITEM_RID(PropertyMap,Parent,TypeDef)
+ SCHEMA_ITEM_RID(PropertyMap,PropertyList,Property)
+ SCHEMA_TABLE_END(PropertyMap)
+
+ //-------------------------------------------------------------------------
+ //PropertyPtr
+ SCHEMA_TABLE_START(PropertyPtr)
+ SCHEMA_ITEM_NOFIXED()
+ SCHEMA_ITEM_RID(PropertyPtr, Property, Property)
+ SCHEMA_TABLE_END(PropertyPtr)
+
+ //-------------------------------------------------------------------------
+ //Property
+ SCHEMA_TABLE_START(Property)
+ SCHEMA_ITEM(Property, USHORT, PropFlags)
+ SCHEMA_ITEM_STRING(Property,Name)
+ SCHEMA_ITEM_BLOB(Property,Type)
+ SCHEMA_TABLE_END(Property)
+
+ //-------------------------------------------------------------------------
+ //MethodSemantics
+ SCHEMA_TABLE_START(MethodSemantics)
+ SCHEMA_ITEM(MethodSemantics, USHORT, Semantic)
+ SCHEMA_ITEM_RID(MethodSemantics,Method,Method)
+ SCHEMA_ITEM_CDTKN(MethodSemantics,Association,HasSemantic)
+ SCHEMA_TABLE_END(MethodSemantics)
+
+ //-------------------------------------------------------------------------
+ //MethodImpl
+ SCHEMA_TABLE_START(MethodImpl)
+ SCHEMA_ITEM_RID(MethodImpl,Class,TypeDef)
+ SCHEMA_ITEM_CDTKN(MethodImpl,MethodBody,MethodDefOrRef)
+ SCHEMA_ITEM_CDTKN(MethodImpl, MethodDeclaration, MethodDefOrRef)
+ SCHEMA_TABLE_END(MethodImpl)
+
+ //-------------------------------------------------------------------------
+ //ModuleRef
+ SCHEMA_TABLE_START(ModuleRef)
+ SCHEMA_ITEM_NOFIXED()
+ SCHEMA_ITEM_STRING(ModuleRef, Name)
+ SCHEMA_TABLE_END(ModuleRef)
+
+ //-------------------------------------------------------------------------
+ // TypeSpec
+ SCHEMA_TABLE_START(TypeSpec)
+ SCHEMA_ITEM_NOFIXED()
+ SCHEMA_ITEM_BLOB(TypeSpec,Signature)
+ SCHEMA_TABLE_END(TypeSpec)
+
+ //-------------------------------------------------------------------------
+ // ENCLog
+ SCHEMA_TABLE_START(ENCLog)
+ SCHEMA_ITEM(ENCLog, ULONG, Token)
+ SCHEMA_ITEM(ENCLog, ULONG, FuncCode)
+ SCHEMA_TABLE_END(ENCLog)
+
+ //-------------------------------------------------------------------------
+ // ImplMap
+ SCHEMA_TABLE_START(ImplMap)
+ SCHEMA_ITEM(ImplMap, USHORT, MappingFlags)
+ SCHEMA_ITEM_CDTKN(ImplMap, MemberForwarded, MemberForwarded)
+ SCHEMA_ITEM_STRING(ImplMap, ImportName)
+ SCHEMA_ITEM_RID(ImplMap, ImportScope, ModuleRef)
+ SCHEMA_TABLE_END(ImplMap)
+
+ //-------------------------------------------------------------------------
+ // ENCMap
+ SCHEMA_TABLE_START(ENCMap)
+ SCHEMA_ITEM(ENCMap, ULONG, Token)
+ SCHEMA_TABLE_END(ENCMap)
+
+ //-------------------------------------------------------------------------
+ // FieldRVA
+ SCHEMA_TABLE_START(FieldRVA)
+ SCHEMA_ITEM(FieldRVA, ULONG, RVA)
+ SCHEMA_ITEM_RID(FieldRVA, Field, Field)
+ SCHEMA_TABLE_END(FieldRVA)
+
+ //-------------------------------------------------------------------------
+ // Assembly
+ SCHEMA_TABLE_START(Assembly)
+ SCHEMA_ITEM(Assembly, ULONG, HashAlgId)
+ SCHEMA_ITEM(Assembly, USHORT, MajorVersion)
+ SCHEMA_ITEM(Assembly, USHORT, MinorVersion)
+ SCHEMA_ITEM(Assembly, USHORT, BuildNumber)
+ SCHEMA_ITEM(Assembly, USHORT, RevisionNumber)
+ SCHEMA_ITEM(Assembly, ULONG, Flags)
+ SCHEMA_ITEM_BLOB(Assembly, PublicKey)
+ SCHEMA_ITEM_STRING(Assembly, Name)
+ SCHEMA_ITEM_STRING(Assembly, Locale)
+ SCHEMA_TABLE_END(Assembly)
+
+ //-------------------------------------------------------------------------
+ // AssemblyProcessor
+ SCHEMA_TABLE_START(AssemblyProcessor)
+ SCHEMA_ITEM(AssemblyProcessor, ULONG, Processor)
+ SCHEMA_TABLE_END(AssemblyProcessor)
+
+ //-------------------------------------------------------------------------
+ // AssemblyOS
+ SCHEMA_TABLE_START(AssemblyOS)
+ SCHEMA_ITEM(AssemblyOS, ULONG, OSPlatformId)
+ SCHEMA_ITEM(AssemblyOS, ULONG, OSMajorVersion)
+ SCHEMA_ITEM(AssemblyOS, ULONG, OSMinorVersion)
+ SCHEMA_TABLE_END(AssemblyOS)
+
+ //-------------------------------------------------------------------------
+ // AssemblyRef
+ SCHEMA_TABLE_START(AssemblyRef)
+ SCHEMA_ITEM(AssemblyRef, USHORT, MajorVersion)
+ SCHEMA_ITEM(AssemblyRef, USHORT, MinorVersion)
+ SCHEMA_ITEM(AssemblyRef, USHORT, BuildNumber)
+ SCHEMA_ITEM(AssemblyRef, USHORT, RevisionNumber)
+ SCHEMA_ITEM(AssemblyRef, ULONG, Flags)
+ SCHEMA_ITEM_BLOB(AssemblyRef, PublicKeyOrToken)
+ SCHEMA_ITEM_STRING(AssemblyRef, Name)
+ SCHEMA_ITEM_STRING(AssemblyRef, Locale)
+ SCHEMA_ITEM_BLOB(AssemblyRef, HashValue)
+ SCHEMA_TABLE_END(AssemblyRef)
+
+ //-------------------------------------------------------------------------
+ // AssemblyRefProcessor
+ SCHEMA_TABLE_START(AssemblyRefProcessor)
+ SCHEMA_ITEM(AssemblyRefProcessor, ULONG, Processor)
+ SCHEMA_ITEM_RID(AssemblyRefProcessor, AssemblyRef, AssemblyRef)
+ SCHEMA_TABLE_END(AssemblyRefProcessor)
+
+ //-------------------------------------------------------------------------
+ // AssemblyRefOS
+ SCHEMA_TABLE_START(AssemblyRefOS)
+ SCHEMA_ITEM(AssemblyRefOS, ULONG, OSPlatformId)
+ SCHEMA_ITEM(AssemblyRefOS, ULONG, OSMajorVersion)
+ SCHEMA_ITEM(AssemblyRefOS, ULONG, OSMinorVersion)
+ SCHEMA_ITEM_RID(AssemblyRefOS, AssemblyRef, AssemblyRef)
+ SCHEMA_TABLE_END(AssemblyRefOS)
+
+ //-------------------------------------------------------------------------
+ // File
+ SCHEMA_TABLE_START(File)
+ SCHEMA_ITEM(File, ULONG, Flags)
+ SCHEMA_ITEM_STRING(File, Name)
+ SCHEMA_ITEM_BLOB(File, HashValue)
+ SCHEMA_TABLE_END(File)
+
+ //-------------------------------------------------------------------------
+ // ExportedType
+ SCHEMA_TABLE_START(ExportedType)
+ SCHEMA_ITEM(ExportedType, ULONG, Flags)
+ SCHEMA_ITEM(ExportedType, ULONG, TypeDefId)
+ SCHEMA_ITEM_STRING(ExportedType, TypeName)
+ SCHEMA_ITEM_STRING(ExportedType, TypeNamespace)
+ SCHEMA_ITEM_CDTKN(ExportedType, Implementation, Implementation)
+ SCHEMA_TABLE_END(ExportedType)
+
+ //-------------------------------------------------------------------------
+ // ManifestResource
+ SCHEMA_TABLE_START(ManifestResource)
+ SCHEMA_ITEM(ManifestResource, ULONG, Offset)
+ SCHEMA_ITEM(ManifestResource, ULONG, Flags)
+ SCHEMA_ITEM_STRING(ManifestResource, Name)
+ SCHEMA_ITEM_CDTKN(ManifestResource, Implementation, Implementation)
+ SCHEMA_TABLE_END(ManifestResource)
+
+ //-------------------------------------------------------------------------
+ // NestedClass
+ SCHEMA_TABLE_START(NestedClass)
+ SCHEMA_ITEM_RID(NestedClass, NestedClass, TypeDef)
+ SCHEMA_ITEM_RID(NestedClass, EnclosingClass, TypeDef)
+ SCHEMA_TABLE_END(NestedClass)
+
+
+ //-------------------------------------------------------------------------
+ // GenericParam
+ SCHEMA_TABLE_START(GenericParam)
+ SCHEMA_ITEM(GenericParam, USHORT, Number)
+ SCHEMA_ITEM(GenericParam, USHORT, Flags)
+ SCHEMA_ITEM_CDTKN(GenericParam, Owner, TypeOrMethodDef)
+ SCHEMA_ITEM_STRING(GenericParam, Name)
+ SCHEMA_TABLE_END(GenericParam)
+
+ //-------------------------------------------------------------------------
+ // Transitional table for Metadata v1.1 for GenericParam
+ SCHEMA_TABLE_START(GenericParamV1_1)
+ SCHEMA_ITEM(GenericParam, USHORT, Number)
+ SCHEMA_ITEM(GenericParam, USHORT, Flags)
+ SCHEMA_ITEM_CDTKN(GenericParam, Owner, TypeOrMethodDef)
+ SCHEMA_ITEM_STRING(GenericParam, Name)
+ SCHEMA_ITEM_CDTKN(GenericParam, Kind, TypeDefOrRef)
+ SCHEMA_TABLE_END(GenericParam)
+
+
+
+ //-------------------------------------------------------------------------
+ //MethodSpec
+ SCHEMA_TABLE_START(MethodSpec)
+ SCHEMA_ITEM_NOFIXED()
+ SCHEMA_ITEM_CDTKN(MethodSpec, Method, MethodDefOrRef)
+ SCHEMA_ITEM_BLOB(MethodSpec, Instantiation)
+ SCHEMA_TABLE_END(MethodSpec)
+
+ //-------------------------------------------------------------------------
+ // GenericParamConstraint
+ SCHEMA_TABLE_START(GenericParamConstraint)
+ SCHEMA_ITEM_RID(GenericParamConstraint, Owner, GenericParam)
+ SCHEMA_ITEM_CDTKN(GenericParamConstraint, Constraint, TypeDefOrRef)
+ SCHEMA_TABLE_END(GenericParamConstraint)
+
+// eof ------------------------------------------------------------------------
diff --git a/src/md/runtime/metamodelro.cpp b/src/md/runtime/metamodelro.cpp
new file mode 100644
index 0000000000..0feb153a2f
--- /dev/null
+++ b/src/md/runtime/metamodelro.cpp
@@ -0,0 +1,444 @@
+// 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.
+//*****************************************************************************
+// MetaModelRO.cpp -- Read-only implementation of compressed COM+ metadata.
+//
+
+//
+//*****************************************************************************
+#include "stdafx.h"
+
+#include "metamodelro.h"
+#include <posterror.h>
+#include <corerror.h>
+#include "metadatatracker.h"
+
+//*****************************************************************************
+// Set the pointers to consecutive areas of a large buffer.
+//*****************************************************************************
+__checkReturn
+HRESULT
+CMiniMd::InitializeTables(
+ MetaData::DataBlob tablesData)
+{
+ HRESULT hr;
+
+ for (int i = 0; i < TBL_COUNT; i++)
+ {
+ // This table data
+ MetaData::DataBlob tableData;
+
+ S_UINT32 cbTableSize =
+ S_UINT32(m_TableDefs[i].m_cbRec) *
+ S_UINT32(m_Schema.m_cRecs[i]);
+ if (cbTableSize.IsOverflow())
+ {
+ Debug_ReportError("Table is too large - size overflow.");
+ return CLDB_E_FILE_CORRUPT;
+ }
+ if (!tablesData.GetDataOfSize(cbTableSize.Value(), &tableData))
+ {
+ Debug_ReportError("Table is not within MetaData tables block.");
+ return CLDB_E_FILE_CORRUPT;
+ }
+ _ASSERTE(cbTableSize.Value() == tableData.GetSize());
+
+ METADATATRACKER_ONLY(MetaDataTracker::NoteSection(
+ i,
+ tableData.GetDataPointer(),
+ tableData.GetSize(),
+ m_TableDefs[i].m_cbRec));
+
+ IfFailRet(m_Tables[i].Initialize(
+ m_TableDefs[i].m_cbRec,
+ tableData,
+ FALSE)); // fCopyData
+ }
+
+ return S_OK;
+} // CMiniMd::SetTablePointers
+
+//*****************************************************************************
+// Given a buffer that contains a MiniMd, init to read it.
+//*****************************************************************************
+HRESULT
+CMiniMd::InitOnMem(
+ void *pvBuf, // The buffer.
+ ULONG ulBufLen) // Size of the buffer..
+{
+ HRESULT hr = S_OK;
+ ULONG cbData;
+ BYTE *pBuf = reinterpret_cast<BYTE*>(pvBuf);
+
+ // Uncompress the schema from the buffer into our structures.
+ IfFailGo(SchemaPopulate(pvBuf, ulBufLen, &cbData));
+ PREFAST_ASSUME(cbData <= ulBufLen);
+
+ // There shouldn't be any pointer tables.
+ if ((m_Schema.m_cRecs[TBL_MethodPtr] != 0) || (m_Schema.m_cRecs[TBL_FieldPtr] != 0))
+ {
+ Debug_ReportError("MethodPtr and FieldPtr tables are not allowed in Read-Only format.");
+ return PostError(CLDB_E_FILE_CORRUPT);
+ }
+
+ // initialize the pointers to the rest of the data.
+ IfFailGo(InitializeTables(MetaData::DataBlob(pBuf + Align4(cbData), ulBufLen-cbData)));
+
+ErrExit:
+ return hr;
+} // CMiniMd::InitOnMem
+
+//*****************************************************************************
+// Validate cross-stream consistency.
+//*****************************************************************************
+HRESULT
+CMiniMd::PostInit(
+ int iLevel)
+{
+ return S_OK;
+} // CMiniMd::PostInit
+
+//*****************************************************************************
+// converting a ANSI heap string to unicode string to an output buffer
+//*****************************************************************************
+HRESULT
+CMiniMd::Impl_GetStringW(
+ ULONG ix,
+ __inout_ecount (cchBuffer) LPWSTR szOut,
+ ULONG cchBuffer,
+ ULONG *pcchBuffer)
+{
+ LPCSTR szString; // Single byte version.
+ int iSize; // Size of resulting string, in wide chars.
+ HRESULT hr = NOERROR;
+
+ IfFailGo(getString(ix, &szString));
+
+ if (*szString == 0)
+ {
+ // If emtpy string "", return pccBuffer 0
+ if ((szOut != NULL) && (cchBuffer != 0))
+ szOut[0] = W('\0');
+ if (pcchBuffer != NULL)
+ *pcchBuffer = 0;
+ goto ErrExit;
+ }
+ iSize = ::WszMultiByteToWideChar(CP_UTF8, 0, szString, -1, szOut, cchBuffer);
+ if (iSize == 0)
+ {
+ // What was the problem?
+ DWORD dwNT = GetLastError();
+
+ // Not truncation?
+ if (dwNT != ERROR_INSUFFICIENT_BUFFER)
+ IfFailGo(HRESULT_FROM_NT(dwNT));
+
+ // Truncation error; get the size required.
+ if (pcchBuffer != NULL)
+ *pcchBuffer = ::WszMultiByteToWideChar(CP_UTF8, 0, szString, -1, NULL, 0);
+
+ if ((szOut != NULL) && (cchBuffer > 0))
+ { // null-terminate the truncated output string
+ szOut[cchBuffer - 1] = W('\0');
+ }
+
+ hr = CLDB_S_TRUNCATION;
+ goto ErrExit;
+ }
+ if (pcchBuffer != NULL)
+ *pcchBuffer = iSize;
+
+ErrExit:
+ return hr;
+} // CMiniMd::Impl_GetStringW
+
+
+//*****************************************************************************
+// Given a table with a pointer (index) to a sequence of rows in another
+// table, get the RID of the end row. This is the STL-ish end; the first row
+// not in the list. Thus, for a list of 0 elements, the start and end will
+// be the same.
+//*****************************************************************************
+__checkReturn
+HRESULT
+CMiniMd::Impl_GetEndRidForColumn( // The End rid.
+ UINT32 nTableIndex,
+ RID nRowIndex,
+ CMiniColDef &def, // Column containing the RID into other table.
+ UINT32 nTargetTableIndex, // The other table.
+ RID *pEndRid)
+{
+ HRESULT hr;
+ _ASSERTE(nTableIndex < TBL_COUNT);
+ RID nLastRowIndex = m_Schema.m_cRecs[nTableIndex];
+
+ // Last rid in range from NEXT record, or count of table, if last record.
+ if (nRowIndex < nLastRowIndex)
+ {
+ BYTE *pRow;
+ IfFailRet(Impl_GetRow(nTableIndex, nRowIndex + 1, &pRow));
+ *pEndRid = getIX(pRow, def);
+ }
+ else // Convert count to 1-based rid.
+ {
+ if (nRowIndex != nLastRowIndex)
+ {
+ Debug_ReportError("Invalid table row index.");
+ IfFailRet(METADATA_E_INDEX_NOTFOUND);
+ }
+ _ASSERTE(nTargetTableIndex < TBL_COUNT);
+ *pEndRid = m_Schema.m_cRecs[nTargetTableIndex] + 1;
+ }
+
+ return S_OK;
+} // CMiniMd::Impl_GetEndRidForColumn
+
+
+//*****************************************************************************
+// return all found CAs in an enumerator
+//*****************************************************************************
+HRESULT
+CMiniMd::CommonEnumCustomAttributeByName(
+ mdToken tkObj, // [IN] Object with Custom Attribute.
+ LPCUTF8 szName, // [IN] Name of desired Custom Attribute.
+ bool fStopAtFirstFind, // [IN] just find the first one
+ HENUMInternal *phEnum) // enumerator to fill up
+{
+ HRESULT hr = S_OK;
+ HRESULT hrRet = S_FALSE; // Assume that we won't find any
+ ULONG ridStart, ridEnd; // Loop start and endpoints.
+
+ _ASSERTE(phEnum != NULL);
+
+ memset(phEnum, 0, sizeof(HENUMInternal));
+
+ HENUMInternal::InitDynamicArrayEnum(phEnum);
+
+ phEnum->m_tkKind = mdtCustomAttribute;
+
+ // Get the list of custom values for the parent object.
+
+ IfFailGo(getCustomAttributeForToken(tkObj, &ridEnd, &ridStart));
+ if (ridStart == 0)
+ return S_FALSE;
+
+ // Look for one with the given name.
+ for (; ridStart < ridEnd; ++ridStart)
+ {
+ IfFailGoto(CompareCustomAttribute( tkObj, szName, ridStart), ErrExit);
+ if (hr == S_OK)
+ {
+ // If here, found a match.
+ hrRet = S_OK;
+ IfFailGo(HENUMInternal::AddElementToEnum(
+ phEnum,
+ TokenFromRid(ridStart, mdtCustomAttribute)));
+ if (fStopAtFirstFind)
+ goto ErrExit;
+ }
+ }
+
+ErrExit:
+ if (FAILED(hr))
+ return hr;
+ return hrRet;
+} // CMiniMd::CommonEnumCustomAttributeByName
+
+
+//*****************************************************************************
+// Search a table for the row containing the given key value.
+// EG. Constant table has pointer back to Param or Field.
+//
+//*****************************************************************************
+__checkReturn
+HRESULT
+CMiniMd::vSearchTable(
+ ULONG ixTbl, // Table to search.
+ CMiniColDef sColumn, // Sorted key column, containing search value.
+ ULONG ulTarget, // Target for search.
+ RID *pRid) // RID of matching row, or 0.
+{
+ HRESULT hr;
+ void *pRow = NULL; // Row from a table.
+ ULONG val; // Value from a row.
+ int lo, mid, hi; // binary search indices.
+
+ // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ // If you change the rows touched while searching, please update
+ // CMiniMdRW::GetHotMetadataTokensSearchAware
+ // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+ // Start with entire table.
+ lo = 1;
+ hi = GetCountRecs(ixTbl);
+ // While there are rows in the range...
+ while (lo <= hi)
+ { // Look at the one in the middle.
+ mid = (lo + hi) / 2;
+ IfFailRet(getRow(ixTbl, mid, &pRow));
+ val = getIX_NoLogging(pRow, sColumn);
+ // If equal to the target, done.
+ if (val == ulTarget)
+ {
+ *pRid = mid;
+ METADATATRACKER_ONLY(MetaDataTracker::NoteSearch(pRow));
+ return S_OK;
+ }
+ // If middle item is too small, search the top half.
+ if (val < ulTarget)
+ lo = mid + 1;
+ else // but if middle is to big, search bottom half.
+ hi = mid - 1;
+ }
+ // Didn't find anything that matched.
+ *pRid = 0;
+
+ METADATATRACKER_ONLY(MetaDataTracker::NoteSearch(pRow));
+ return S_OK;
+} // CMiniMd::vSearchTable
+
+//*****************************************************************************
+// Search a table for the highest-RID row containing a value that is less than
+// or equal to the target value. EG. TypeDef points to first Field, but if
+// a TypeDef has no fields, it points to first field of next TypeDef.
+//*****************************************************************************
+__checkReturn
+HRESULT
+CMiniMd::vSearchTableNotGreater(
+ ULONG ixTbl, // Table to search.
+ CMiniColDef sColumn, // the column def containing search value
+ ULONG ulTarget, // target for search
+ RID *pRid) // RID of matching row, or 0
+{
+ HRESULT hr;
+ void *pRow = NULL; // Row from a table.
+ ULONG cRecs; // Rows in the table.
+ ULONG val = 0; // Value from a table.
+ ULONG lo, mid = 0, hi; // binary search indices.
+
+ cRecs = GetCountRecs(ixTbl);
+
+ // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ // If you change the rows touched while searching, please update
+ // CMiniMdRW::GetHotMetadataTokensSearchAware
+ // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+ // Start with entire table.
+ lo = 1;
+ hi = cRecs;
+ // If no recs, return.
+ if (lo > hi)
+ {
+ *pRid = 0;
+ return S_OK;
+ }
+ // While there are rows in the range...
+ while (lo <= hi)
+ { // Look at the one in the middle.
+ mid = (lo + hi) / 2;
+ IfFailRet(getRow(ixTbl, mid, &pRow));
+ val = getIX_NoLogging(pRow, sColumn);
+ // If equal to the target, done searching.
+ if (val == ulTarget)
+ break;
+ // If middle item is too small, search the top half.
+ if (val < ulTarget)
+ lo = mid + 1;
+ else // but if middle is to big, search bottom half.
+ hi = mid - 1;
+ }
+
+ METADATATRACKER_ONLY(MetaDataTracker::NoteSearch(pRow));
+
+ // May or may not have found anything that matched. Mid will be close, but may
+ // be to high or too low. It should point to the highest acceptable
+ // record.
+
+ // If the value is greater than the target, back up just until the value is
+ // less than or equal to the target. SHOULD only be one step.
+ if (val > ulTarget)
+ {
+ while (val > ulTarget)
+ {
+ // If there is nothing else to look at, we won't find it.
+ if (--mid < 1)
+ break;
+ IfFailRet(getRow(ixTbl, mid, &pRow));
+ val = getIX(pRow, sColumn);
+ }
+ }
+ else
+ {
+ // Value is less than or equal to the target. As long as the next
+ // record is also acceptable, move forward.
+ while (mid < cRecs)
+ {
+ // There is another record. Get its value.
+ IfFailRet(getRow(ixTbl, mid+1, &pRow));
+ val = getIX(pRow, sColumn);
+ // If that record is too high, stop.
+ if (val > ulTarget)
+ break;
+ mid++;
+ }
+ }
+
+ // Return the value that's just less than the target.
+ *pRid = mid;
+ return S_OK;
+} // CMiniMd::vSearchTableNotGreater
+
+//*****************************************************************************
+// return just the blob value of the first found CA matching the query.
+// returns S_FALSE if there is no match
+//*****************************************************************************
+HRESULT
+CMiniMd::CommonGetCustomAttributeByNameEx(
+ 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;
+
+ ULONG cbData;
+ CustomAttributeRec *pRec;
+
+ ULONG ridStart, ridEnd; // Loop start and endpoints.
+
+ // Get the list of custom values for the parent object.
+
+ IfFailGo(getCustomAttributeForToken(tkObj, &ridEnd, &ridStart));
+
+ hr = S_FALSE;
+ if (ridStart == 0)
+ {
+ goto ErrExit;
+ }
+
+ // Look for one with the given name.
+ for (; ridStart < ridEnd; ++ridStart)
+ {
+ IfFailGoto(CompareCustomAttribute( tkObj, szName, ridStart), ErrExit);
+ if (hr == S_OK)
+ {
+ if (ppData != NULL)
+ {
+ // now get the record out.
+ if (pcbData == NULL)
+ pcbData = &cbData;
+
+ IfFailGo(GetCustomAttributeRecord(ridStart, &pRec));
+ IfFailGo(getValueOfCustomAttribute(pRec, reinterpret_cast<const BYTE **>(ppData), pcbData));
+ if (ptkCA)
+ *ptkCA = TokenFromRid(mdtCustomAttribute, ridStart);
+ }
+ break;
+ }
+ }
+
+ErrExit:
+ return hr;
+} // CMiniMd::CommonGetCustomAttributeByName
diff --git a/src/md/runtime/recordpool.cpp b/src/md/runtime/recordpool.cpp
new file mode 100644
index 0000000000..da4bcbc9e9
--- /dev/null
+++ b/src/md/runtime/recordpool.cpp
@@ -0,0 +1,388 @@
+// 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.
+//*****************************************************************************
+// RecordPool.cpp -- Implementation of record heaps.
+//
+
+//
+//*****************************************************************************
+#include "stdafx.h"
+#include <recordpool.h>
+
+#define RECORDPOOL_GROW_FACTOR 8
+#define RECORDPOOL_GROW_MAX 2048
+#define RECORDPOOL_GROW_MINROWS 2
+#define RECORDPOOL_GROW_DEFAULTROWS 16
+
+HRESULT
+RecordPool::InitNew(
+ UINT32 cbRec, // Record size.
+ UINT32 cRecsInit) // Initial guess of count of record.
+{
+ HRESULT hr;
+ S_UINT32 cbGrow; // Initial grow size of the pool.
+
+ // Size of each record is fixed.
+ m_cbRec = cbRec;
+
+ if (cRecsInit > 0)
+ {
+ cbGrow = S_UINT32(cbRec) * S_UINT32(cRecsInit);
+ }
+ else
+ {
+ cbGrow = S_UINT32(cbRec) * S_UINT32(RECORDPOOL_GROW_DEFAULTROWS);
+ }
+ if (cbGrow.IsOverflow())
+ {
+ Debug_ReportInternalError("Growing record pool overflowed.");
+ return CLDB_E_INTERNALERROR;
+ }
+
+ m_ulGrowInc = cbGrow.Value();
+
+ IfFailRet(StgPool::InitNew());
+
+ // If there is an initial size for the record pool, grow to that now.
+ if (cRecsInit > 0)
+ {
+ if (!Grow(cbGrow.Value()))
+ return E_OUTOFMEMORY;
+ }
+
+ return S_OK;
+} // RecordPool::InitNew
+
+//*****************************************************************************
+// Load a Record heap from persisted memory. If a copy of the data is made
+// (so that it may be updated), then a new hash table is generated which can
+// be used to elminate duplicates with new Records.
+//*****************************************************************************
+HRESULT
+RecordPool::InitOnMem(
+ ULONG cbRec, // Record size.
+ void *pData, // Predefined data.
+ ULONG iSize, // Size of data.
+ BOOL fReadOnly) // true if append is forbidden.
+{
+ HRESULT hr;
+ m_cbRec = cbRec;
+
+ // Let base class init our memory structure.
+ IfFailRet(StgPool::InitOnMem(pData, iSize, fReadOnly));
+
+ // For init on existing mem case.
+ if ((pData != NULL) && (iSize != 0))
+ {
+ // If we are doing an update in place don't make a copy
+ // If we cannot update, then we don't need a hash table.
+ if (fReadOnly)
+ return S_OK;
+
+ // Other wise copy the memory to do the update
+ IfFailRet(TakeOwnershipOfInitMem());
+ }
+
+ return S_OK;
+} // RecordPool::InitOnMem
+
+//*****************************************************************************
+// Allocate memory if we don't have any, or grow what we have. If successful,
+// then at least iRequired bytes will be allocated.
+//*****************************************************************************
+bool RecordPool::Grow( // true if successful.
+ ULONG iRequired) // Min required bytes to allocate.
+{
+ // Allocate the memory.
+ if (!StgPool::Grow(iRequired))
+ return false;
+
+ // Zero the new memory.
+ memset(GetNextLocation(), 0, GetCbSegAvailable());
+
+ return true;
+} // bool RecordProol::Grow()
+
+//*****************************************************************************
+// The Record will be added to the pool. The index of the Record in the pool
+// is returned in *piIndex. If the Record is already in the pool, then the
+// index will be to the existing copy of the Record.
+//*****************************************************************************
+HRESULT
+RecordPool::AddRecord(
+ BYTE **ppRecord,
+ UINT32 *pnIndex) // Return 1-based index of Record here.
+{
+ _ASSERTE(pnIndex != NULL);
+
+ // Space on heap for new Record?
+ if (m_cbRec > GetCbSegAvailable())
+ {
+ if (!Grow(m_cbRec))
+ {
+ *ppRecord = NULL;
+ return E_OUTOFMEMORY;
+ }
+ }
+
+ // Records should be aligned on record boundaries.
+ _ASSERTE((GetNextOffset() % m_cbRec) == 0);
+
+ // Copy the Record to the heap.
+ *ppRecord = GetNextLocation();
+
+ // Give the 1-based index back to caller.
+ *pnIndex = (GetNextOffset() / m_cbRec) + 1;
+
+ // Update heap counters.
+ SegAllocate(m_cbRec);
+
+ return S_OK;
+} // RecordPool::AddRecord
+
+//*****************************************************************************
+// Insert a Record into the pool. The index of the Record before which to
+// insert is specified. Shifts all records down. Return a pointer to the
+// new record.
+//*****************************************************************************
+HRESULT
+RecordPool::InsertRecord(
+ UINT32 nIndex, // [IN] Insert record before this.
+ BYTE **ppRecord)
+{
+ HRESULT hr;
+ StgPoolSeg *pCurSeg; // Current segment.
+ StgPoolSeg *pPrevSeg; // Previous segment.
+ BYTE *pSegEnd; // Last record in a segment.
+ BYTE *pFrom; // A copy/move source.
+ ULONG cbMove; // Bytes to move.
+ BYTE *pNew; // New record.
+
+ // Notice the case of appending.
+ if (nIndex == (Count() + 1))
+ {
+ UINT32 nNewIndex_Ignore;
+ return AddRecord(ppRecord, &nNewIndex_Ignore);
+ }
+
+ // If past end or before beginning, invalid.
+ if ((nIndex > Count()) || (nIndex == 0))
+ {
+ Debug_ReportError("Invalid index passed for inserting record.");
+ return CLDB_E_INDEX_NOTFOUND;
+ }
+
+ // This code works by allocating a new record at the end.
+ // The last record is moved to the new end record.
+ // Working backwards through the chained segments,
+ // shift the segment by one record, so the empty record
+ // is at the start of the segment instead of the end.
+ // copy the last record of the previous segment to the
+ // newly emptied first record of the current segment.
+ // When the segment containing the insert point is finally
+ // reached, its last record is empty (from above loop), so
+ // shift from the insertion point to the end-1 by one record.
+
+ // Current last record.
+ pCurSeg = m_pCurSeg;
+ IfFailRet(GetRecord(Count(), &pSegEnd));
+ _ASSERTE(hr == S_OK);
+
+ // Add an empty record to the end of the heap.
+ {
+ UINT32 nLastRecordIndex_Ignore;
+ IfFailRet(AddRecord(&pNew, &nLastRecordIndex_Ignore));
+ }
+
+ // Copy the current last record to the new record.
+ memcpy(pNew, pSegEnd, m_cbRec);
+
+ // While the insert location is prior to the current segment,
+ while (nIndex < GetIndexForRecord(pCurSeg->m_pSegData))
+ {
+ // Shift the segment up by one record.
+ cbMove = (ULONG)(pSegEnd - pCurSeg->m_pSegData);
+ memmove(pCurSeg->m_pSegData + m_cbRec, pCurSeg->m_pSegData, cbMove);
+
+ // Find the previous segment.
+ pPrevSeg = this;
+ while (pPrevSeg->m_pNextSeg != pCurSeg)
+ {
+ pPrevSeg = pPrevSeg->m_pNextSeg;
+ }
+
+ // Copy the final record of the previous segment to the start of this one.
+ pSegEnd = pPrevSeg->m_pSegData+pPrevSeg->m_cbSegNext-m_cbRec;
+ memcpy(pCurSeg->m_pSegData, pSegEnd, m_cbRec);
+
+ // Make the previous segment the current segment.
+ pCurSeg = pPrevSeg;
+ }
+
+ // Shift at the insert location, forward by one.
+ IfFailRet(GetRecord(nIndex, &pFrom));
+ _ASSERTE(hr == S_OK);
+
+ cbMove = (ULONG)(pSegEnd - pFrom);
+ memmove(pFrom + m_cbRec, pFrom, cbMove);
+
+ *ppRecord = pFrom;
+
+ return S_OK;
+} // RecordPool::InsertRecord
+
+//*****************************************************************************
+// Return a pointer to a Record given an index previously handed out by
+// AddRecord or FindRecord.
+//*****************************************************************************
+HRESULT
+RecordPool::GetRecord(
+ UINT32 nIndex, // 1-based index of Record in pool.
+ BYTE **ppRecord)
+{
+ MetaData::DataBlob record;
+
+ if (nIndex == 0)
+ {
+ Debug_ReportError("Invalid index 0 passed.");
+ *ppRecord = NULL;
+ return CLDB_E_INDEX_NOTFOUND;
+ }
+
+ // Convert to 0-based internal form, defer to implementation.
+ HRESULT hr = GetData((nIndex - 1) * m_cbRec, &record);
+ if (FAILED(hr))
+ {
+ *ppRecord = NULL;
+ return hr;
+ }
+ _ASSERTE(record.ContainsData(m_cbRec));
+ *ppRecord = record.GetDataPointer();
+
+ return hr;
+} // RecordPool::GetRecord
+
+//*****************************************************************************
+// Return the first record in a pool, and set up a context for fast
+// iterating through the pool. Note that this scheme does pretty minimal
+// error checking.
+//*****************************************************************************
+void *RecordPool::GetFirstRecord( // Pointer to Record in pool.
+ void **pContext) // Store context here.
+{
+ StgPoolSeg **ppSeg = reinterpret_cast<StgPoolSeg**>(pContext);
+
+ *ppSeg = static_cast<StgPoolSeg*>(this);
+ return (*ppSeg)->m_pSegData;
+} // void *RecordPool::GetFirstRecord()
+
+//*****************************************************************************
+// Given a pointer to a record, return a pointer to the next record.
+// Note that this scheme does pretty minimal error checking. In particular,
+// this will let the caller walk off of the end of valid data in the last
+// segment.
+//*****************************************************************************
+void *RecordPool::GetNextRecord( // Pointer to Record in pool.
+ void *pRecord, // Current record.
+ void **pContext) // Stored context here.
+{
+ BYTE *pbRec = reinterpret_cast<BYTE*>(pRecord);
+ StgPoolSeg **ppSeg = reinterpret_cast<StgPoolSeg**>(pContext);
+
+ // Get the next record.
+ pbRec += m_cbRec;
+
+ // Is the next record outside of the current segment?
+ if (static_cast<ULONG>(pbRec - (*ppSeg)->m_pSegData) >= (*ppSeg)->m_cbSegSize)
+ {
+ // Better be exactly one past current segment.
+ _ASSERTE(static_cast<ULONG>(pbRec - (*ppSeg)->m_pSegData) == (*ppSeg)->m_cbSegSize);
+ // Switch the context pointer.
+ *ppSeg = (*ppSeg)->m_pNextSeg;
+ // Next record is start of next segment.
+ if (*ppSeg)
+ return (*ppSeg)->m_pSegData;
+ else
+ return 0;
+ }
+
+ return pbRec;
+} // void *RecordPool::GetNextRecord()
+
+//*****************************************************************************
+// Given a pointer to a record, determine the index corresponding to the
+// record.
+//*****************************************************************************
+ULONG RecordPool::GetIndexForRecord( // 1-based index of Record in pool.
+ const void *pvRecord) // Pointer to Record in pool.
+{
+ ULONG iPrev = 0; // cumulative index of previous segments.
+ const StgPoolSeg *pSeg = this;
+ const BYTE *pRecord = reinterpret_cast<const BYTE*>(pvRecord);
+ const BYTE *pSegData = NULL;
+ ULONG ulSegSize;
+ for (;;)
+ { // Does the current segment contain the record?
+ pSegData = pSeg->GetSegData();
+ ulSegSize = pSeg->GetSegSize();
+ if (pRecord >= pSegData && pRecord < pSegData + ulSegSize)
+ { // The pointer should be to the start of a record.
+ _ASSERTE(((pRecord - pSegData) % m_cbRec) == 0);
+ return (ULONG)(1 + iPrev + (pRecord - pSegData) / m_cbRec);
+ }
+ _ASSERTE((ulSegSize % m_cbRec) == 0);
+ iPrev += ulSegSize / m_cbRec;
+ pSeg = pSeg->GetNextSeg();
+ // If out of data, didn't find the record.
+ if (pSeg == 0)
+ return 0;
+ }
+} // ULONG RecordPool::GetIndexForRecord()
+
+//*****************************************************************************
+// Given a purported pointer to a record, determine if the pointer is valid.
+//*****************************************************************************
+int RecordPool::IsValidPointerForRecord(// true or false.
+ const void *pvRecord) // Pointer to Record in pool.
+{
+ const StgPoolSeg *pSeg;
+ const BYTE *pRecord = reinterpret_cast<const BYTE*>(pvRecord);
+ const BYTE *pSegData = NULL;
+ for (pSeg = this; (pSeg); pSeg = pSeg->GetNextSeg())
+ { // Does the current segment contain the record?
+ pSegData = pSeg->GetSegData();
+ if ((pRecord >= pSegData) && (pRecord < pSegData + pSeg->GetSegSize()))
+ { // The pointer should be to the start of a record.
+ return (((pRecord - pSegData) % m_cbRec) == 0);
+ }
+ _ASSERTE((pSeg->GetSegSize() % m_cbRec) == 0);
+ }
+ return 0;
+} // int RecordPool::IsValidPointerForRecord()
+
+//*****************************************************************************
+// Replace the contents of this pool with those from another pool. The other
+// pool loses ownership of the memory.
+//*****************************************************************************
+HRESULT RecordPool::ReplaceContents(
+ RecordPool *pOther) // The other record pool.
+{
+ // Release any memory currently held.
+ Uninit();
+
+ // Grab the new data.
+ *this = *pOther;
+
+ // If the other pool's curseg pointed to itself, make this pool point to itself.
+ if (pOther->m_pCurSeg == pOther)
+ m_pCurSeg = this;
+
+ // Fix the other pool so it won't free the memory that this one
+ // just hijacked.
+ pOther->m_pSegData = (BYTE*)m_zeros;
+ pOther->m_pNextSeg = 0;
+ pOther->Uninit();
+
+ return S_OK;
+} // HRESULT RecordPool::ReplaceContents()
diff --git a/src/md/runtime/stdafx.cpp b/src/md/runtime/stdafx.cpp
new file mode 100644
index 0000000000..ff341e19a7
--- /dev/null
+++ b/src/md/runtime/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/runtime/stdafx.h b/src/md/runtime/stdafx.h
new file mode 100644
index 0000000000..061551a832
--- /dev/null
+++ b/src/md/runtime/stdafx.h
@@ -0,0 +1,24 @@
+// 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 "mdcommon.h"
+
+#endif // __STDAFX_H_
diff --git a/src/md/runtime/wks/.gitmirror b/src/md/runtime/wks/.gitmirror
new file mode 100644
index 0000000000..f507630f94
--- /dev/null
+++ b/src/md/runtime/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/runtime/wks/CMakeLists.txt b/src/md/runtime/wks/CMakeLists.txt
new file mode 100644
index 0000000000..9a1f72ed25
--- /dev/null
+++ b/src/md/runtime/wks/CMakeLists.txt
@@ -0,0 +1,5 @@
+include(../../md_wks.cmake)
+
+add_precompiled_header(stdafx.h ../stdafx.cpp MDRUNTIME_SOURCES)
+add_library_clr(mdruntime_wks ${MDRUNTIME_SOURCES})
+
diff --git a/src/md/runtime/wks/MDRuntime.nativeproj b/src/md/runtime/wks/MDRuntime.nativeproj
new file mode 100644
index 0000000000..bc95bf65f2
--- /dev/null
+++ b/src/md/runtime/wks/MDRuntime.nativeproj
@@ -0,0 +1,19 @@
+<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>
+ </PropertyGroup>
+
+ <!--Import the settings-->
+ <Import Project="$(_NTDRIVE)$(_NTROOT)\ndp\clr\src\MD\Runtime\Runtime.settings.targets" />
+
+ <!--Leaf project Properties-->
+ <PropertyGroup>
+ <BuildCoreBinaries>true</BuildCoreBinaries>
+ <BuildSysBinaries>true</BuildSysBinaries>
+ <OutputName>MDRuntime</OutputName>
+ </PropertyGroup>
+
+ <!--Import the targets-->
+ <Import Project="$(_NTDRIVE)$(_NTROOT)\ndp\clr\clr.targets" />
+</Project>