HRESULT MicrosoftInstrumentationEngine::AssemblyInjector::ImportTypeDef()

in src/InstrumentationEngine/AssemblyInjector.cpp [78:263]


HRESULT MicrosoftInstrumentationEngine::AssemblyInjector::ImportTypeDef(_In_ mdTypeDef sourceTypeDef, _Out_ mdTypeDef *pTargetTypeDef)
{
    HRESULT hr = S_OK;

    IfFalseRet(sourceTypeDef != mdTokenNil && sourceTypeDef != mdTypeDefNil, E_FAIL);

    TokenMap::const_iterator itr = m_typeDefMap.find(sourceTypeDef);
    if (itr != m_typeDefMap.end())
    {
        *pTargetTypeDef = itr->second;
        return S_OK;
    }

    CLogging::XmlDumpHelper dumpLogHelper(L"ImportTypeDef", 1);
    dumpLogHelper.WriteUlongNode(L"token", sourceTypeDef);

    WCHAR szTypeDef[MAX_NAME] = { 0 };
    ULONG cchTypeDef = 0;
    DWORD dwTypeDefFlags = 0;
    mdToken tkExtends = mdTokenNil;
    IfFailRet(m_pSourceImport->GetTypeDefProps(sourceTypeDef, szTypeDef, _countof(szTypeDef), &cchTypeDef, &dwTypeDefFlags, &tkExtends));

    dumpLogHelper.WriteStringNode(L"Name", szTypeDef);

    mdToken targetExtends = mdTokenNil;
    IfFailRet(ConvertToken(tkExtends, &targetExtends));

    ATL::CAutoVectorPtr<mdInterfaceImpl> pInterfaceImpls;
    ATL::CAutoVectorPtr<mdToken> pImplements;
    //On x86 machines this EnumInterfaceImpls returns nullptr enum and CountEnum will return 0xcccccccc as ulCount.
    //Thus we need to validate the Enum returned S_OK, not S_FALSE
    CMetadataEnumCloser<IMetaDataImport2> spHCorEnum(m_pSourceImport, nullptr);
    IfFailRet(hr = m_pSourceImport->EnumInterfaceImpls(spHCorEnum.Get(), sourceTypeDef, nullptr, 0, nullptr));
    if (hr == S_OK)
    {
        ULONG ulCount = 0;
        IfFailRet(hr = m_pSourceImport->CountEnum(spHCorEnum.Get(), &ulCount));
        if (hr == S_OK)
        {
            if (ulCount != 0)
            {
                pInterfaceImpls.Attach(new mdInterfaceImpl[ulCount]);
                spHCorEnum.Reset(nullptr);
                IfFailRet(m_pSourceImport->EnumInterfaceImpls(spHCorEnum.Get(), sourceTypeDef, pInterfaceImpls, ulCount, nullptr));
                pImplements.Attach(new mdToken[ulCount + 1]);
                for (ULONG i = 0; i < ulCount; i++)
                {
                    IfFailRet(m_pSourceImport->GetInterfaceImplProps(pInterfaceImpls[i], nullptr, &(pImplements[i])));
                    IfFailRet(ConvertToken(pImplements[i], &(pImplements[i])));
                }
                pImplements[ulCount] = mdTokenNil;
            }
        }
    }

    if (!IsTdNested(dwTypeDefFlags))
    {
        //find matching class by name
        HRESULT hrFound = CLDB_E_RECORD_NOTFOUND;
        if (szTypeDef[0] == MERGE_TYPE_PREFIX)
        {
            hrFound = m_pTargetImport->FindTypeDefByName(szTypeDef + 1, mdTokenNil, pTargetTypeDef);
            dumpLogHelper.WriteStringNode(L"MergedToType", szTypeDef + 1);
        }

        if (hrFound == CLDB_E_RECORD_NOTFOUND)
        {
            IfFailRet(m_pTargetEmit->DefineTypeDef(szTypeDef,
                dwTypeDefFlags,
                targetExtends,
                pImplements,
                pTargetTypeDef));
        }
        else
        {
            IfFailRet(hrFound);
        }
    }
    else
    {
        mdTypeDef sourceEnclosingTypeDef = mdTypeDefNil;
        mdTypeDef targetEnclosingTypeDef = mdTypeDefNil;
        IfFailRet(m_pSourceImport->GetNestedClassProps(sourceTypeDef, &sourceEnclosingTypeDef));
        IfFailRet(ConvertToken(sourceEnclosingTypeDef, &targetEnclosingTypeDef));

        //find matching class by name
        HRESULT hrFound = CLDB_E_RECORD_NOTFOUND;
        if (szTypeDef[0] == MERGE_TYPE_PREFIX)
        {
            hrFound = m_pTargetImport->FindTypeDefByName(szTypeDef + 1, targetEnclosingTypeDef, pTargetTypeDef);
            dumpLogHelper.WriteStringNode(L"MergedToType", szTypeDef + 1);
        }

        if (hrFound == CLDB_E_RECORD_NOTFOUND)
        {
            IfFailRet(m_pTargetEmit->DefineNestedType(szTypeDef,
                dwTypeDefFlags,
                targetExtends,
                pImplements,
                targetEnclosingTypeDef,
                pTargetTypeDef));
        }
        else
        {
            IfFailRet(hrFound);
        }
    }

    m_typeDefMap[sourceTypeDef] = *pTargetTypeDef;
    dumpLogHelper.WriteUlongNode(L"targetToken", *pTargetTypeDef);

    CMetadataEnumCloser<IMetaDataImport2> spHEnSourceFields(m_pSourceImport, nullptr);
    mdFieldDef curSourceField = mdFieldDefNil;
    ULONG cTokens = 0;
    while (S_OK == (hr = m_pSourceImport->EnumFields(spHEnSourceFields.Get(), sourceTypeDef, &curSourceField, 1, &cTokens)))
    {
        mdFieldDef targetFieldDef = mdFieldDefNil;
        IfFailRet(ImportFieldDef(curSourceField, &targetFieldDef));
    }
    IfFailRet(hr);

    spHCorEnum.Reset(nullptr);
    mdMethodDef curSourceMethod = mdMethodDefNil;
    while (S_OK == (hr = m_pSourceImport->EnumMethods(spHCorEnum.Get(), sourceTypeDef, &curSourceMethod, 1, &cTokens)))
    {
        mdMethodDef targetMethodDef = mdMethodDefNil;
        IfFailRet(ImportMethodDef(curSourceMethod, &targetMethodDef));
    }
    IfFailRet(hr);

    spHCorEnum.Reset(nullptr);
    mdProperty curSourceProperty = mdPropertyNil;
    while (S_OK == (hr = m_pSourceImport->EnumProperties(spHCorEnum.Get(), sourceTypeDef, &curSourceProperty, 1, &cTokens)))
    {
        mdProperty targetProperty = mdPropertyNil;
        IfFailRet(ImportProperty(curSourceProperty, &targetProperty));
    }
    IfFailRet(hr);

    spHCorEnum.Reset(nullptr);
    mdEvent curSourceEvent = mdEventNil;
    while (S_OK == (hr = m_pSourceImport->EnumEvents(spHCorEnum.Get(), sourceTypeDef, &curSourceEvent, 1, &cTokens)))
    {
        mdEvent targetEvent = mdEventNil;
        IfFailRet(ImportEvent(curSourceEvent, &targetEvent));
    }
    IfFailRet(hr);

    spHCorEnum.Reset(nullptr);
    mdToken sourceImplementationMethod = mdTokenNil;
    mdToken sourceDeclarationMethod = mdTokenNil;
    while (S_OK == (hr = m_pSourceImport->EnumMethodImpls(spHCorEnum.Get(), sourceTypeDef, &sourceImplementationMethod, &sourceDeclarationMethod, 1, &cTokens)))
    {
        IfFailRet(ImportMethodImpl(sourceTypeDef, sourceImplementationMethod, sourceDeclarationMethod));
    }
    IfFailRet(hr);

    if ((dwTypeDefFlags & tdExplicitLayout) != 0)
    {
        ULONG cFieldOffset = 0;
        IfFailRet(m_pSourceImport->GetClassLayout(sourceTypeDef, nullptr, nullptr, 0, &cFieldOffset, nullptr));
        ATL::CAutoVectorPtr<COR_FIELD_OFFSET> fieldOffsets(new COR_FIELD_OFFSET[cFieldOffset + 1]);

        DWORD dwPackSize = 0;
        ULONG ulClassSize = 0;
        IfFailRet(m_pSourceImport->GetClassLayout(sourceTypeDef, &dwPackSize, fieldOffsets, cFieldOffset, nullptr, &ulClassSize));
        for (ULONG i = 0; i < cFieldOffset; i++)
        {
            IfFailRet(ImportFieldDef(fieldOffsets[i].ridOfField, &(fieldOffsets[i].ridOfField)));
        }
        fieldOffsets[cFieldOffset].ridOfField = mdFieldDefNil;
        fieldOffsets[cFieldOffset].ulOffset = 0;
        IfFailRet(m_pTargetEmit->SetClassLayout(*pTargetTypeDef, dwPackSize, fieldOffsets, ulClassSize));
    }

    spHCorEnum.Reset(nullptr);
    mdGenericParam curSourceGenericParam = mdGenericParamNil;
    while (S_OK == (hr = m_pSourceImport->EnumGenericParams(spHCorEnum.Get(), sourceTypeDef, &curSourceGenericParam, 1, nullptr)))
    {
        mdGenericParam targetGenericParam = mdGenericParamNil;
        IfFailRet(ImportGenericParam(curSourceGenericParam, &targetGenericParam));
    }
    IfFailRet(hr);

    return S_OK;
}