HRESULT FindTypeInMetaDataFile()

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;
    }