summaryrefslogtreecommitdiff
path: root/src/md/compiler/assemblymd.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/md/compiler/assemblymd.cpp')
-rw-r--r--src/md/compiler/assemblymd.cpp758
1 files changed, 758 insertions, 0 deletions
diff --git a/src/md/compiler/assemblymd.cpp b/src/md/compiler/assemblymd.cpp
new file mode 100644
index 0000000000..8c0a22af4d
--- /dev/null
+++ b/src/md/compiler/assemblymd.cpp
@@ -0,0 +1,758 @@
+// 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.
+//*****************************************************************************
+// AssemblyMD.cpp
+//
+
+//
+// Implementation for the assembly meta data import code (code:IMetaDataAssemblyImport).
+//
+//*****************************************************************************
+#include "stdafx.h"
+#include "regmeta.h"
+#include "mdutil.h"
+#include "rwutil.h"
+#include "mdlog.h"
+#include "importhelper.h"
+
+#include <strongname.h>
+
+#ifdef _MSC_VER
+#pragma warning(disable: 4102)
+#endif
+
+//*******************************************************************************
+// Get the properties for the given Assembly token.
+//*******************************************************************************
+STDMETHODIMP RegMeta::GetAssemblyProps( // S_OK or error.
+ mdAssembly mda, // [IN] The Assembly for which to get the properties.
+ const void **ppbPublicKey, // [OUT] Pointer to the public key.
+ ULONG *pcbPublicKey, // [OUT] Count of bytes in the public key.
+ ULONG *pulHashAlgId, // [OUT] Hash Algorithm.
+ __out_ecount_part_opt(cchName, *pchName) LPWSTR szName, // [OUT] Buffer to fill with 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 = S_OK;
+
+ BEGIN_ENTRYPOINT_NOTHROW;
+
+ AssemblyRec *pRecord;
+ CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd);
+
+ LOG((LOGMD, "RegMeta::GetAssemblyProps(0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
+ mda, ppbPublicKey, pcbPublicKey, pulHashAlgId, szName, cchName, pchName, pMetaData,
+ pdwAssemblyFlags));
+
+ START_MD_PERF();
+ LOCKREAD();
+
+ _ASSERTE(TypeFromToken(mda) == mdtAssembly && RidFromToken(mda));
+ IfFailGo(pMiniMd->GetAssemblyRecord(RidFromToken(mda), &pRecord));
+
+ if (ppbPublicKey != NULL)
+ {
+ IfFailGo(pMiniMd->getPublicKeyOfAssembly(pRecord, (const BYTE **)ppbPublicKey, pcbPublicKey));
+ }
+ if (pulHashAlgId)
+ *pulHashAlgId = pMiniMd->getHashAlgIdOfAssembly(pRecord);
+ if (pMetaData)
+ {
+ pMetaData->usMajorVersion = pMiniMd->getMajorVersionOfAssembly(pRecord);
+ pMetaData->usMinorVersion = pMiniMd->getMinorVersionOfAssembly(pRecord);
+ pMetaData->usBuildNumber = pMiniMd->getBuildNumberOfAssembly(pRecord);
+ pMetaData->usRevisionNumber = pMiniMd->getRevisionNumberOfAssembly(pRecord);
+ IfFailGo(pMiniMd->getLocaleOfAssembly(pRecord, pMetaData->szLocale,
+ pMetaData->cbLocale, &pMetaData->cbLocale));
+ pMetaData->ulProcessor = 0;
+ pMetaData->ulOS = 0;
+ }
+ if (pdwAssemblyFlags)
+ {
+ *pdwAssemblyFlags = pMiniMd->getFlagsOfAssembly(pRecord);
+
+#ifdef FEATURE_WINDOWSPHONE
+ // Turn on the afPublicKey if PublicKey blob is not empty
+ DWORD cbPublicKey;
+ const BYTE *pbPublicKey;
+ IfFailGo(pMiniMd->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 *pbPublicKey;
+ IfFailGo(pMiniMd->getPublicKeyOfAssembly(pRecord, &pbPublicKey, &cbPublicKey));
+ bool hasPublicKey = cbPublicKey != 0;
+ bool hasPublicKeyFlag = ( *pdwAssemblyFlags & afPublicKey ) != 0;
+ _ASSERTE( hasPublicKey == hasPublicKeyFlag );
+#endif
+ }
+#endif // FEATURE_WINDOWSPHONE
+ }
+ // This call has to be last to set 'hr', so CLDB_S_TRUNCATION is not rewritten with S_OK
+ if (szName || pchName)
+ IfFailGo(pMiniMd->getNameOfAssembly(pRecord, szName, cchName, pchName));
+ErrExit:
+
+ STOP_MD_PERF(GetAssemblyProps);
+
+ END_ENTRYPOINT_NOTHROW;
+
+ return hr;
+} // RegMeta::GetAssemblyProps
+
+//*******************************************************************************
+// Get the properties for the given AssemblyRef token.
+//*******************************************************************************
+STDMETHODIMP RegMeta::GetAssemblyRefProps( // S_OK or error.
+ mdAssemblyRef mdar, // [IN] The AssemblyRef for which to get the properties.
+ const void **ppbPublicKeyOrToken, // [OUT] Pointer to the public key or token.
+ ULONG *pcbPublicKeyOrToken, // [OUT] Count of bytes in the public key or token.
+ __out_ecount_part_opt(cchName, *pchName) LPWSTR szName, // [OUT] Buffer to fill with name.
+ ULONG cchName, // [IN] Size of buffer in wide chars.
+ ULONG *pchName, // [OUT] Actual # of wide chars in name.
+ ASSEMBLYMETADATA *pMetaData, // [OUT] Assembly MetaData.
+ const void **ppbHashValue, // [OUT] Hash blob.
+ ULONG *pcbHashValue, // [OUT] Count of bytes in the hash blob.
+ DWORD *pdwAssemblyRefFlags) // [OUT] Flags.
+{
+ HRESULT hr = S_OK;
+
+ BEGIN_ENTRYPOINT_NOTHROW;
+
+ AssemblyRefRec *pRecord;
+ CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd);
+
+ LOG((LOGMD, "RegMeta::GetAssemblyRefProps(0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
+ mdar, ppbPublicKeyOrToken, pcbPublicKeyOrToken, szName, cchName,
+ pchName, pMetaData, ppbHashValue, pdwAssemblyRefFlags));
+
+ START_MD_PERF();
+ LOCKREAD();
+
+ _ASSERTE(TypeFromToken(mdar) == mdtAssemblyRef && RidFromToken(mdar));
+ IfFailGo(pMiniMd->GetAssemblyRefRecord(RidFromToken(mdar), &pRecord));
+
+ if (ppbPublicKeyOrToken != NULL)
+ {
+ IfFailGo(pMiniMd->getPublicKeyOrTokenOfAssemblyRef(pRecord, (const BYTE **)ppbPublicKeyOrToken, pcbPublicKeyOrToken));
+ }
+ if (pMetaData)
+ {
+ pMetaData->usMajorVersion = pMiniMd->getMajorVersionOfAssemblyRef(pRecord);
+ pMetaData->usMinorVersion = pMiniMd->getMinorVersionOfAssemblyRef(pRecord);
+ pMetaData->usBuildNumber = pMiniMd->getBuildNumberOfAssemblyRef(pRecord);
+ pMetaData->usRevisionNumber = pMiniMd->getRevisionNumberOfAssemblyRef(pRecord);
+ IfFailGo(pMiniMd->getLocaleOfAssemblyRef(pRecord, pMetaData->szLocale,
+ pMetaData->cbLocale, &pMetaData->cbLocale));
+ pMetaData->ulProcessor = 0;
+ pMetaData->ulOS = 0;
+ }
+ if (ppbHashValue != NULL)
+ {
+ IfFailGo(pMiniMd->getHashValueOfAssemblyRef(pRecord, (const BYTE **)ppbHashValue, pcbHashValue));
+ }
+ if (pdwAssemblyRefFlags)
+ *pdwAssemblyRefFlags = pMiniMd->getFlagsOfAssemblyRef(pRecord);
+ // This call has to be last to set 'hr', so CLDB_S_TRUNCATION is not rewritten with S_OK
+ if (szName || pchName)
+ IfFailGo(pMiniMd->getNameOfAssemblyRef(pRecord, szName, cchName, pchName));
+ErrExit:
+
+ STOP_MD_PERF(GetAssemblyRefProps);
+ END_ENTRYPOINT_NOTHROW;
+
+ return hr;
+} // RegMeta::GetAssemblyRefProps
+
+//*******************************************************************************
+// Get the properties for the given File token.
+//*******************************************************************************
+STDMETHODIMP RegMeta::GetFileProps( // S_OK or error.
+ mdFile mdf, // [IN] The File for which to get the properties.
+ __out_ecount_part_opt(cchName, *pchName) LPWSTR szName, // [OUT] Buffer to fill with name.
+ ULONG cchName, // [IN] Size of buffer in wide chars.
+ ULONG *pchName, // [OUT] Actual # of wide chars in name.
+ const void **ppbHashValue, // [OUT] Pointer to the Hash Value Blob.
+ ULONG *pcbHashValue, // [OUT] Count of bytes in the Hash Value Blob.
+ DWORD *pdwFileFlags) // [OUT] Flags.
+{
+ HRESULT hr = S_OK;
+
+ BEGIN_ENTRYPOINT_NOTHROW;
+
+ FileRec *pRecord;
+ CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd);
+
+ LOG((LOGMD, "RegMeta::GetFileProps(%#08x, %#08x, %#08x, %#08x, %#08x, %#08x, %#08x)\n",
+ mdf, szName, cchName, pchName, ppbHashValue, pcbHashValue, pdwFileFlags));
+
+ START_MD_PERF();
+ LOCKREAD();
+
+ _ASSERTE(TypeFromToken(mdf) == mdtFile && RidFromToken(mdf));
+ IfFailGo(pMiniMd->GetFileRecord(RidFromToken(mdf), &pRecord));
+
+ if (ppbHashValue != NULL)
+ {
+ IfFailGo(pMiniMd->getHashValueOfFile(pRecord, (const BYTE **)ppbHashValue, pcbHashValue));
+ }
+ if (pdwFileFlags != NULL)
+ *pdwFileFlags = pMiniMd->getFlagsOfFile(pRecord);
+ // This call has to be last to set 'hr', so CLDB_S_TRUNCATION is not rewritten with S_OK
+ if ((szName != NULL) || (pchName != NULL))
+ {
+ IfFailGo(pMiniMd->getNameOfFile(pRecord, szName, cchName, pchName));
+ }
+
+ErrExit:
+ STOP_MD_PERF(GetFileProps);
+ END_ENTRYPOINT_NOTHROW;
+
+ return hr;
+} // RegMeta::GetFileProps
+
+//*******************************************************************************
+// Get the properties for the given ExportedType token.
+//*******************************************************************************
+STDMETHODIMP RegMeta::GetExportedTypeProps( // S_OK or error.
+ mdExportedType mdct, // [IN] The ExportedType for which to get the properties.
+ __out_ecount_part_opt(cchName, *pchName) LPWSTR szName, // [OUT] Buffer to fill with name.
+ ULONG cchName, // [IN] Size of buffer in wide chars.
+ ULONG *pchName, // [OUT] Actual # of wide chars in name.
+ mdToken *ptkImplementation, // [OUT] mdFile or mdAssemblyRef that provides the ExportedType.
+ mdTypeDef *ptkTypeDef, // [OUT] TypeDef token within the file.
+ DWORD *pdwExportedTypeFlags) // [OUT] Flags.
+{
+ HRESULT hr = S_OK; // A result.
+
+ BEGIN_ENTRYPOINT_NOTHROW;
+
+ ExportedTypeRec *pRecord; // The exported type.
+ CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd);
+ int bTruncation=0; // Was there name truncation?
+
+ LOG((LOGMD, "RegMeta::GetExportedTypeProps(%#08x, %#08x, %#08x, %#08x, %#08x, %#08x, %#08x)\n",
+ mdct, szName, cchName, pchName,
+ ptkImplementation, ptkTypeDef, pdwExportedTypeFlags));
+
+ START_MD_PERF();
+ LOCKREAD();
+
+ _ASSERTE(TypeFromToken(mdct) == mdtExportedType && RidFromToken(mdct));
+ IfFailGo(pMiniMd->GetExportedTypeRecord(RidFromToken(mdct), &pRecord));
+
+ if (szName || pchName)
+ {
+ LPCSTR szTypeNamespace;
+ LPCSTR szTypeName;
+
+ IfFailGo(pMiniMd->getTypeNamespaceOfExportedType(pRecord, &szTypeNamespace));
+ PREFIX_ASSUME(szTypeNamespace != NULL);
+ MAKE_WIDEPTR_FROMUTF8_NOTHROW(wzTypeNamespace, szTypeNamespace);
+ IfNullGo(wzTypeNamespace);
+
+ IfFailGo(pMiniMd->getTypeNameOfExportedType(pRecord, &szTypeName));
+ _ASSERTE(*szTypeName);
+ MAKE_WIDEPTR_FROMUTF8_NOTHROW(wzTypeName, szTypeName);
+ IfNullGo(wzTypeName);
+
+ if (szName)
+ bTruncation = ! (ns::MakePath(szName, cchName, wzTypeNamespace, wzTypeName));
+ if (pchName)
+ {
+ if (bTruncation || !szName)
+ *pchName = ns::GetFullLength(wzTypeNamespace, wzTypeName);
+ else
+ *pchName = (ULONG)(wcslen(szName) + 1);
+ }
+ }
+ if (ptkImplementation)
+ *ptkImplementation = pMiniMd->getImplementationOfExportedType(pRecord);
+ if (ptkTypeDef)
+ *ptkTypeDef = pMiniMd->getTypeDefIdOfExportedType(pRecord);
+ if (pdwExportedTypeFlags)
+ *pdwExportedTypeFlags = pMiniMd->getFlagsOfExportedType(pRecord);
+
+ if (bTruncation && hr == S_OK)
+ {
+ if ((szName != NULL) && (cchName > 0))
+ { // null-terminate the truncated output string
+ szName[cchName - 1] = W('\0');
+ }
+ hr = CLDB_S_TRUNCATION;
+ }
+
+ErrExit:
+ STOP_MD_PERF(GetExportedTypeProps);
+ END_ENTRYPOINT_NOTHROW;
+
+ return hr;
+} // RegMeta::GetExportedTypeProps
+
+//*******************************************************************************
+// Get the properties for the given Resource token.
+//*******************************************************************************
+STDMETHODIMP RegMeta::GetManifestResourceProps( // S_OK or error.
+ mdManifestResource mdmr, // [IN] The ManifestResource for which to get the properties.
+ __out_ecount_part_opt(cchName, *pchName)LPWSTR szName, // [OUT] Buffer to fill with name.
+ ULONG cchName, // [IN] Size of buffer in wide chars.
+ ULONG *pchName, // [OUT] Actual # of wide chars in name.
+ mdToken *ptkImplementation, // [OUT] mdFile or mdAssemblyRef that provides the ExportedType.
+ DWORD *pdwOffset, // [OUT] Offset to the beginning of the resource within the file.
+ DWORD *pdwResourceFlags) // [OUT] Flags.
+{
+ HRESULT hr = S_OK;
+
+ BEGIN_ENTRYPOINT_NOTHROW;
+
+ ManifestResourceRec *pRecord;
+ CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd);
+
+ LOG((LOGMD, "RegMeta::GetManifestResourceProps("
+ "%#08x, %#08x, %#08x, %#08x, %#08x, %#08x, %#08x)\n",
+ mdmr, szName, cchName, pchName,
+ ptkImplementation, pdwOffset,
+ pdwResourceFlags));
+
+ START_MD_PERF();
+ LOCKREAD();
+
+ _ASSERTE(TypeFromToken(mdmr) == mdtManifestResource && RidFromToken(mdmr));
+ IfFailGo(pMiniMd->GetManifestResourceRecord(RidFromToken(mdmr), &pRecord));
+
+ if (ptkImplementation)
+ *ptkImplementation = pMiniMd->getImplementationOfManifestResource(pRecord);
+ if (pdwOffset)
+ *pdwOffset = pMiniMd->getOffsetOfManifestResource(pRecord);
+ if (pdwResourceFlags)
+ *pdwResourceFlags = pMiniMd->getFlagsOfManifestResource(pRecord);
+ // This call has to be last to set 'hr', so CLDB_S_TRUNCATION is not rewritten with S_OK
+ if (szName || pchName)
+ IfFailGo(pMiniMd->getNameOfManifestResource(pRecord, szName, cchName, pchName));
+ErrExit:
+
+ STOP_MD_PERF(GetManifestResourceProps);
+ END_ENTRYPOINT_NOTHROW;
+
+ return hr;
+} // RegMeta::GetManifestResourceProps
+
+
+//*******************************************************************************
+// Enumerating through all of the AssemblyRefs.
+//*******************************************************************************
+STDMETHODIMP RegMeta::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.
+{
+ HRESULT hr = NOERROR;
+
+ BEGIN_ENTRYPOINT_NOTHROW;
+
+ HENUMInternal **ppmdEnum = reinterpret_cast<HENUMInternal **> (phEnum);
+ HENUMInternal *pEnum;
+
+ LOG((LOGMD, "MD RegMeta::EnumAssemblyRefs(%#08x, %#08x, %#08x, %#08x)\n",
+ phEnum, rAssemblyRefs, cMax, pcTokens));
+ START_MD_PERF();
+
+ LOCKREAD();
+
+ if (*ppmdEnum == 0)
+ {
+ // instantiate a new ENUM.
+ CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd);
+
+ // create the enumerator.
+ IfFailGo(HENUMInternal::CreateSimpleEnum(
+ mdtAssemblyRef,
+ 1,
+ pMiniMd->getCountAssemblyRefs() + 1,
+ &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);
+
+ STOP_MD_PERF(EnumAssemblyRefs);
+
+ END_ENTRYPOINT_NOTHROW;
+
+ return hr;
+} // RegMeta::EnumAssemblyRefs
+
+//*******************************************************************************
+// Enumerating through all of the Files.
+//*******************************************************************************
+STDMETHODIMP RegMeta::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.
+{
+ HRESULT hr = NOERROR;
+
+ BEGIN_ENTRYPOINT_NOTHROW;
+
+ HENUMInternal **ppmdEnum = reinterpret_cast<HENUMInternal **> (phEnum);
+ HENUMInternal *pEnum;
+
+ LOG((LOGMD, "MD RegMeta::EnumFiles(%#08x, %#08x, %#08x, %#08x)\n",
+ phEnum, rFiles, cMax, pcTokens));
+ START_MD_PERF();
+ LOCKREAD();
+
+ if (*ppmdEnum == 0)
+ {
+ // instantiate a new ENUM.
+ CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd);
+
+ // create the enumerator.
+ IfFailGo(HENUMInternal::CreateSimpleEnum(
+ mdtFile,
+ 1,
+ pMiniMd->getCountFiles() + 1,
+ &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);
+
+ STOP_MD_PERF(EnumFiles);
+ END_ENTRYPOINT_NOTHROW;
+
+ return hr;
+} // RegMeta::EnumFiles
+
+//*******************************************************************************
+// Enumerating through all of the ExportedTypes.
+//*******************************************************************************
+STDMETHODIMP RegMeta::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.
+{
+ HRESULT hr = NOERROR;
+
+ BEGIN_ENTRYPOINT_NOTHROW;
+
+ HENUMInternal **ppmdEnum = reinterpret_cast<HENUMInternal **> (phEnum);
+ HENUMInternal *pEnum;
+
+ LOG((LOGMD, "MD RegMeta::EnumExportedTypes(%#08x, %#08x, %#08x, %#08x)\n",
+ phEnum, rExportedTypes, cMax, pcTokens));
+
+ START_MD_PERF();
+ LOCKREAD();
+
+ if (*ppmdEnum == 0)
+ {
+ // instantiate a new ENUM.
+ CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd);
+
+ if (pMiniMd->HasDelete() &&
+ ((m_OptionValue.m_ImportOption & MDImportOptionAllExportedTypes) == 0))
+ {
+ IfFailGo( HENUMInternal::CreateDynamicArrayEnum( mdtExportedType, &pEnum) );
+
+ // add all Types to the dynamic array if name is not _Delete
+ for (ULONG index = 1; index <= pMiniMd->getCountExportedTypes(); index ++ )
+ {
+ ExportedTypeRec *pRec;
+ IfFailGo(pMiniMd->GetExportedTypeRecord(index, &pRec));
+ LPCSTR szTypeName;
+ IfFailGo(pMiniMd->getTypeNameOfExportedType(pRec, &szTypeName));
+ if (IsDeletedName(szTypeName))
+ {
+ continue;
+ }
+ IfFailGo( HENUMInternal::AddElementToEnum(pEnum, TokenFromRid(index, mdtExportedType) ) );
+ }
+ }
+ else
+ {
+ // create the enumerator.
+ IfFailGo(HENUMInternal::CreateSimpleEnum(
+ mdtExportedType,
+ 1,
+ pMiniMd->getCountExportedTypes() + 1,
+ &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, rExportedTypes, pcTokens));
+ErrExit:
+ HENUMInternal::DestroyEnumIfEmpty(ppmdEnum);
+
+ STOP_MD_PERF(EnumExportedTypes);
+ END_ENTRYPOINT_NOTHROW;
+
+ return hr;
+} // RegMeta::EnumExportedTypes
+
+//*******************************************************************************
+// Enumerating through all of the Resources.
+//*******************************************************************************
+STDMETHODIMP RegMeta::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.
+{
+ HRESULT hr = NOERROR;
+
+ BEGIN_ENTRYPOINT_NOTHROW;
+
+ HENUMInternal **ppmdEnum = reinterpret_cast<HENUMInternal **> (phEnum);
+ HENUMInternal *pEnum;
+
+ LOG((LOGMD, "MD RegMeta::EnumManifestResources(%#08x, %#08x, %#08x, %#08x)\n",
+ phEnum, rManifestResources, cMax, pcTokens));
+
+ START_MD_PERF();
+ LOCKREAD();
+
+ if (*ppmdEnum == 0)
+ {
+ // instantiate a new ENUM.
+ CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd);
+
+ // create the enumerator.
+ IfFailGo(HENUMInternal::CreateSimpleEnum(
+ mdtManifestResource,
+ 1,
+ pMiniMd->getCountManifestResources() + 1,
+ &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, rManifestResources, pcTokens));
+ErrExit:
+ HENUMInternal::DestroyEnumIfEmpty(ppmdEnum);
+
+ STOP_MD_PERF(EnumManifestResources);
+ END_ENTRYPOINT_NOTHROW;
+
+ return hr;
+} // RegMeta::EnumManifestResources
+
+//*******************************************************************************
+// Get the Assembly token for the given scope..
+//*******************************************************************************
+STDMETHODIMP RegMeta::GetAssemblyFromScope( // S_OK or error
+ mdAssembly *ptkAssembly) // [OUT] Put token here.
+{
+ HRESULT hr = NOERROR;
+ CMiniMdRW *pMiniMd = NULL;
+
+ BEGIN_ENTRYPOINT_NOTHROW;
+
+ LOG((LOGMD, "MD RegMeta::GetAssemblyFromScope(%#08x)\n", ptkAssembly));
+ START_MD_PERF();
+ LOCKREAD();
+ _ASSERTE(ptkAssembly);
+
+ pMiniMd = &(m_pStgdb->m_MiniMd);
+ if (pMiniMd->getCountAssemblys())
+ {
+ *ptkAssembly = TokenFromRid(1, mdtAssembly);
+ }
+ else
+ {
+ IfFailGo( CLDB_E_RECORD_NOTFOUND );
+ }
+ErrExit:
+ STOP_MD_PERF(GetAssemblyFromScope);
+ END_ENTRYPOINT_NOTHROW;
+
+ return hr;
+} // RegMeta::GetAssemblyFromScope
+
+//*******************************************************************************
+// Find the ExportedType given the name.
+//*******************************************************************************
+STDMETHODIMP RegMeta::FindExportedTypeByName( // S_OK or error
+ LPCWSTR szName, // [IN] Name of the ExportedType.
+ mdExportedType tkEnclosingType, // [IN] Enclosing ExportedType.
+ mdExportedType *ptkExportedType) // [OUT] Put the ExportedType token here.
+{
+ HRESULT hr = S_OK; // A result.
+
+ BEGIN_ENTRYPOINT_NOTHROW;
+
+ CMiniMdRW *pMiniMd = NULL;
+ LPSTR szNameUTF8 = NULL;
+
+ LOG((LOGMD, "MD RegMeta::FindExportedTypeByName(%S, %#08x, %#08x)\n",
+ MDSTR(szName), tkEnclosingType, ptkExportedType));
+
+ START_MD_PERF();
+ LOCKREAD();
+
+
+ // Validate name for prefix.
+ if (!szName)
+ IfFailGo(E_INVALIDARG);
+
+ _ASSERTE(szName && ptkExportedType);
+
+ pMiniMd = &(m_pStgdb->m_MiniMd);
+ UTF8STR(szName, szNameUTF8);
+ LPCSTR szTypeName;
+ LPCSTR szTypeNamespace;
+
+ ns::SplitInline(szNameUTF8, szTypeNamespace, szTypeName);
+
+ IfFailGo(ImportHelper::FindExportedType(pMiniMd,
+ szTypeNamespace,
+ szTypeName,
+ tkEnclosingType,
+ ptkExportedType));
+ErrExit:
+ STOP_MD_PERF(FindExportedTypeByName);
+ END_ENTRYPOINT_NOTHROW;
+
+ return hr;
+} // RegMeta::FindExportedTypeByName
+
+//*******************************************************************************
+// Find the ManifestResource given the name.
+//*******************************************************************************
+STDMETHODIMP RegMeta::FindManifestResourceByName( // S_OK or error
+ LPCWSTR szName, // [IN] Name of the ManifestResource.
+ mdManifestResource *ptkManifestResource) // [OUT] Put the ManifestResource token here.
+{
+ HRESULT hr = S_OK;
+
+ BEGIN_ENTRYPOINT_NOTHROW;
+
+ LPCUTF8 szNameTmp = NULL;
+ CMiniMdRW *pMiniMd = NULL;
+
+ LOG((LOGMD, "MD RegMeta::FindManifestResourceByName(%S, %#08x)\n",
+ MDSTR(szName), ptkManifestResource));
+
+ START_MD_PERF();
+ LOCKREAD();
+
+
+ // Validate name for prefix.
+ if (!szName)
+ IfFailGo(E_INVALIDARG);
+
+ _ASSERTE(szName && ptkManifestResource);
+
+ ManifestResourceRec *pRecord;
+ ULONG cRecords; // Count of records.
+ LPUTF8 szUTF8Name; // UTF8 version of the name passed in.
+ ULONG i;
+
+ pMiniMd = &(m_pStgdb->m_MiniMd);
+ *ptkManifestResource = mdManifestResourceNil;
+ cRecords = pMiniMd->getCountManifestResources();
+ UTF8STR(szName, szUTF8Name);
+
+ // Search for the TypeRef.
+ for (i = 1; i <= cRecords; i++)
+ {
+ IfFailGo(pMiniMd->GetManifestResourceRecord(i, &pRecord));
+ IfFailGo(pMiniMd->getNameOfManifestResource(pRecord, &szNameTmp));
+ if (! strcmp(szUTF8Name, szNameTmp))
+ {
+ *ptkManifestResource = TokenFromRid(i, mdtManifestResource);
+ goto ErrExit;
+ }
+ }
+ IfFailGo( CLDB_E_RECORD_NOTFOUND );
+ErrExit:
+
+ STOP_MD_PERF(FindManifestResourceByName);
+ END_ENTRYPOINT_NOTHROW;
+
+ return hr;
+} // RegMeta::FindManifestResourceByName
+
+extern HRESULT STDMETHODCALLTYPE
+ GetAssembliesByName(LPCWSTR szAppBase,
+ LPCWSTR szPrivateBin,
+ LPCWSTR szAssemblyName,
+ IUnknown *ppIUnk[],
+ ULONG cMax,
+ ULONG *pcAssemblies);
+
+//*******************************************************************************
+// Used to find assemblies either in Fusion cache or on disk at build time.
+//*******************************************************************************
+STDMETHODIMP RegMeta::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.
+{
+#ifdef FEATURE_METADATA_IN_VM
+ HRESULT hr = S_OK;
+
+ BEGIN_ENTRYPOINT_NOTHROW;
+
+ LOG((LOGMD, "RegMeta::FindAssembliesByName(0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
+ szAppBase, szPrivateBin, szAssemblyName, ppIUnk, cMax, pcAssemblies));
+ START_MD_PERF();
+
+ // No need to lock this function. It is going through fusion to find the matching Assemblies by name
+
+ IfFailGo(GetAssembliesByName(szAppBase, szPrivateBin,
+ szAssemblyName, ppIUnk, cMax, pcAssemblies));
+
+ErrExit:
+ STOP_MD_PERF(FindAssembliesByName);
+ END_ENTRYPOINT_NOTHROW;
+
+ return hr;
+#else //!FEATURE_METADATA_IN_VM
+ // Calls to fusion are not suported outside VM
+ return E_NOTIMPL;
+#endif //!FEATURE_METADATA_IN_VM
+} // RegMeta::FindAssembliesByName