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