in src/UndockedRegFreeWinRT/UndockedRegFreeWinRT/typeresolution.cpp [54:201]
HRESULT FindTypeInMetaDataFile(
_In_ IMetaDataDispenserEx* pMetaDataDispenser,
_In_ PCWSTR pszFullName,
_In_ PCWSTR pszCandidateFilePath,
_In_ TYPE_RESOLUTION_OPTIONS resolutionOptions,
_COM_Outptr_opt_result_maybenull_ IMetaDataImport2** ppMetaDataImport,
_Out_opt_ mdTypeDef* pmdTypeDef)
{
HRESULT hr = S_OK;
Microsoft::WRL::ComPtr<IMetaDataImport2> spMetaDataImport;
MetaDataImportersLRUCache* pMetaDataImporterCache = MetaDataImportersLRUCache::GetMetaDataImportersLRUCacheInstance();
if (pMetaDataImporterCache != nullptr)
{
hr = pMetaDataImporterCache->GetMetaDataImporter(
pMetaDataDispenser,
pszCandidateFilePath,
&spMetaDataImport);
}
else
{
hr = E_OUTOFMEMORY;
}
if (SUCCEEDED(hr))
{
const size_t cFullName = wcslen(pszFullName);
wchar_t pszRetrievedName[g_uiMaxTypeName];
HCORENUM hEnum = nullptr;
mdTypeDef rgTypeDefs[32];
ULONG cTypeDefs;
DWORD dwTypeDefProps;
hr = RO_E_METADATA_NAME_NOT_FOUND;
if (TRO_RESOLVE_TYPE & resolutionOptions)
{
hr = spMetaDataImport->FindTypeDefByName(pszFullName, mdTokenNil, &rgTypeDefs[0]);
if (SUCCEEDED(hr))
{
// Check to confirm that the type we just found is a
// winrt type. If it is, we're good, otherwise we
// want to fail with RO_E_INVALID_METADATA_FILE.
hr = spMetaDataImport->GetTypeDefProps(rgTypeDefs[0], nullptr, 0, nullptr, &dwTypeDefProps, nullptr);
if (SUCCEEDED(hr))
{
// If we found the type but it's not a winrt type,
// it's an error.
//
// If the type is public, than the metadata file
// is corrupt (all public types in a winrt file
// must be tdWindowsRuntime). If the type is
// private, then we just want to report that the
// type wasn't found.
if (!IsTdWindowsRuntime(dwTypeDefProps))
{
if (IsTdPublic(dwTypeDefProps))
{
hr = RO_E_INVALID_METADATA_FILE;
}
else
{
hr = RO_E_METADATA_NAME_NOT_FOUND;
}
}
}
else
{
hr = RO_E_INVALID_METADATA_FILE;
}
if (SUCCEEDED(hr))
{
if (pmdTypeDef != nullptr)
{
*pmdTypeDef = rgTypeDefs[0];
}
if (ppMetaDataImport != nullptr)
{
*ppMetaDataImport = spMetaDataImport.Detach();
}
}
}
else if (hr == CLDB_E_RECORD_NOTFOUND)
{
hr = RO_E_METADATA_NAME_NOT_FOUND;
}
}
if ((hr == RO_E_METADATA_NAME_NOT_FOUND) &&
(TRO_RESOLVE_NAMESPACE & resolutionOptions))
{
// Check whether the name is a namespace rather than a type.
do
{
hr = spMetaDataImport->EnumTypeDefs(
&hEnum,
rgTypeDefs,
ARRAYSIZE(rgTypeDefs),
&cTypeDefs);
if (hr == S_OK)
{
for (UINT32 iTokenIndex = 0; iTokenIndex < cTypeDefs; ++iTokenIndex)
{
hr = spMetaDataImport->GetTypeDefProps(
rgTypeDefs[iTokenIndex],
pszRetrievedName,
ARRAYSIZE(pszRetrievedName),
nullptr,
&dwTypeDefProps,
nullptr);
if (FAILED(hr))
{
break;
}
hr = RO_E_METADATA_NAME_NOT_FOUND;
// Only consider windows runtime types when
// trying to determine if the name is a
// namespace.
if (IsTdWindowsRuntime(dwTypeDefProps) && (wcslen(pszRetrievedName) > cFullName))
{
if ((wcsncmp(pszRetrievedName, pszFullName, cFullName) == 0) &&
(pszRetrievedName[cFullName] == L'.'))
{
hr = RO_E_METADATA_NAME_IS_NAMESPACE;
break;
}
}
}
}
} while (hr == RO_E_METADATA_NAME_NOT_FOUND);
// There were no more tokens to enumerate, but the type was still not found.
if (hr == S_FALSE)
{
hr = RO_E_METADATA_NAME_NOT_FOUND;
}
if (hEnum != nullptr)
{
spMetaDataImport->CloseEnum(hEnum);
hEnum = nullptr;
}
}
}
return hr;
}