HRESULT MicrosoftInstrumentationEngine::AssemblyInjector::ImportAssemblyRef()

in src/InstrumentationEngine/AssemblyInjector.cpp [330:459]


HRESULT MicrosoftInstrumentationEngine::AssemblyInjector::ImportAssemblyRef(_In_ mdAssemblyRef sourceAssemblyRef, _Out_ mdToken *pTargetAssemblyScope)
{
    HRESULT hr = S_OK;

    IfFalseRet(sourceAssemblyRef != mdTokenNil && sourceAssemblyRef != mdAssemblyRefNil, E_FAIL);

    TokenMap::const_iterator itr = m_assemblyRefMap.find(sourceAssemblyRef);
    if (itr != m_assemblyRefMap.end())
    {
        *pTargetAssemblyScope = itr->second;
        return hr;
    }

    CLogging::XmlDumpHelper dumpLogHelper(L"ImportAssemblyRef", 1);
    dumpLogHelper.WriteUlongNode(L"token", sourceAssemblyRef);


    ATL::CComPtr<IMetaDataAssemblyImport> pAssemblyImport;
    IfFailRet(m_pSourceImport->QueryInterface(IID_IMetaDataAssemblyImport, reinterpret_cast<void**>(&pAssemblyImport)));

    ATL::CComPtr<IMetaDataAssemblyImport> pTargetAssemblyImport;
    IfFailRet(m_pTargetImport->QueryInterface(IID_IMetaDataAssemblyImport, reinterpret_cast<void**>(&pTargetAssemblyImport)));

    const void* pbPublicKeyOrToken = nullptr;
    ULONG cbPublicKeyOrToken = 0;
    WCHAR szName[MAX_NAME] = { 0 };
    ULONG cchName = 0;
    const void* pbHashValue = nullptr;
    ULONG cbHashValue = 0;
    DWORD dwAssemblyRefFlags = 0;
    IfFailRet(pAssemblyImport->GetAssemblyRefProps(sourceAssemblyRef,
        &pbPublicKeyOrToken,
        &cbPublicKeyOrToken,
        szName,
        _countof(szName),
        &cchName,
        nullptr,
        &pbHashValue,
        &cbHashValue,
        &dwAssemblyRefFlags));

    CMetadataEnumCloser<IMetaDataAssemblyImport> spHCorEnumTarget(pTargetAssemblyImport, nullptr);

    mdAssemblyRef cur = mdAssemblyRefNil;
    ULONG cTokens = 0;
    while (S_OK == (hr = pTargetAssemblyImport->EnumAssemblyRefs(spHCorEnumTarget.Get(), &cur, 1, &cTokens)))
    {
        const void* pbPublicKeyOrTokenTarget = nullptr;
        ULONG cbPublicKeyOrTokenTarget = 0;
        WCHAR szNameTarget[MAX_NAME] = { 0 };
        ULONG cchNameTarget = 0;
        const void* pbHashValueTarget = nullptr;
        ULONG cbHashValueTarget = 0;
        DWORD dwAssemblyRefFlagsTarget = 0;
        IfFailRet(pAssemblyImport->GetAssemblyRefProps(cur,
            &pbPublicKeyOrTokenTarget,
            &cbPublicKeyOrTokenTarget,
            szNameTarget,
            _countof(szName),
            &cchNameTarget,
            nullptr,
            &pbHashValueTarget,
            &cbHashValueTarget,
            &dwAssemblyRefFlagsTarget));

        if (wcscmp(szName, szNameTarget) == 0)
        {
            break;
        }
    }

    IfFailRet(hr);
    if (hr == S_OK)
    {
        *pTargetAssemblyScope = cur;
        m_assemblyRefMap[sourceAssemblyRef] = *pTargetAssemblyScope;
        dumpLogHelper.WriteStringNode(L"UseExistingRef", L"true");
        dumpLogHelper.WriteUlongNode(L"targetToken", *pTargetAssemblyScope);
        return hr;
    }

    // didn't find a matching ref - perhaps the reference is to the assembly we are Importing within?
    mdAssembly targetAssembly = mdAssemblyNil;
    IfFailRet(pTargetAssemblyImport->GetAssemblyFromScope(&targetAssembly));

    const void* pbPublicKeyOrTokenTarget = nullptr;
    ULONG cbPublicKeyOrTokenTarget = 0;
    ULONG ulHashAlgIdTarget = 0;
    WCHAR szNameTarget[MAX_NAME] = { 0 };
    DWORD dwAssemblyFlagsTarget = 0;
    IfFailRet(pTargetAssemblyImport->GetAssemblyProps(targetAssembly,
        &pbPublicKeyOrTokenTarget,
        &cbPublicKeyOrTokenTarget,
        &ulHashAlgIdTarget,
        szNameTarget,
        _countof(szNameTarget),
        &cchName,
        nullptr,
        &dwAssemblyFlagsTarget));

    if (wcscmp(szName, szNameTarget) == 0)
    {
        *pTargetAssemblyScope = targetAssembly;
        m_assemblyRefMap[sourceAssemblyRef] = *pTargetAssemblyScope;
        dumpLogHelper.WriteStringNode(L"UseTarget", L"true");
        dumpLogHelper.WriteUlongNode(L"targetToken", *pTargetAssemblyScope);
        return S_OK;
    }

    // maybe the reference is to a contract assembly which is ultimately implemented by the assembly we are Importing into
    // this is an ad-hoc list and isn't comprehensive
    if (wcscmp(L"mscorlib", szNameTarget) == 0)
    {
        if (wcscmp(szName, L"System.Runtime") == 0 ||
            wcscmp(szName, L"System.Collections") == 0 ||
            wcscmp(szName, L"System.Console") == 0 ||
            wcscmp(szName, L"System.Reflection") == 0
            )
        {
            *pTargetAssemblyScope = targetAssembly;
            m_assemblyRefMap[sourceAssemblyRef] = *pTargetAssemblyScope;
            dumpLogHelper.WriteStringNode(L"ContractAssembly", L"true");
            dumpLogHelper.WriteUlongNode(L"targetToken", *pTargetAssemblyScope);
            return S_OK;
        }
    }

    CLogging::LogError(_T("Adding new assembly refs not supported: %s"), szName);
    return E_NOTIMPL;
}