in src/InstrumentationEngine/ProfilerManager.cpp [182:318]
HRESULT CProfilerManager::AddRawProfilerHook(
_In_ IUnknown *pUnkProfilerCallback
)
{
HRESULT hr = S_OK;
IfNullRetPointer(pUnkProfilerCallback);
CProfilerCallbackHolder* profilerCallbackHolder = static_cast<CProfilerCallbackHolder*>(InterlockedCompareExchangePointer(
(volatile PVOID*)&m_profilerCallbackHolder,
nullptr,
nullptr));
if (profilerCallbackHolder != nullptr)
{
CLogging::LogError(_T("CAppDomainInfo::AddRawProfilerHook - Raw profiler hook is already initialized"));
return E_FAIL;
}
if (!GetIsInInitialize())
{
CLogging::LogError(_T("Begin CAppDomainInfo::AddRawProfilerHook - Cannot add a raw profiler hook after initialize"));
return E_FAIL;
}
CCriticalSectionHolder lock(&m_cs);
profilerCallbackHolder = new CProfilerCallbackHolder;
// Rather than following COM-rules and QI-ing for each specific ICorProfilerCallback version, we instead follow the implementation set by the CLR
// where to interface inheritance, higher versioned ICorProfilerCallback## can be statically-casted to lower versioned ICorProfilerCallback##,
// and raw profilers QI can just return the highest supported version (they must still provide implementation for all lower versioned callbacks).
//
// See https://github.com/dotnet/runtime/blob/cf6b06b1d36d545e37b00bf1a6311b7fff33ff4e/src/coreclr/src/vm/eetoprofinterfaceimpl.cpp#L613
// ICorProfilerCallback7
CComPtr<ICorProfilerCallback7> pCorProfilerCallback7;
hr = pUnkProfilerCallback->QueryInterface(__uuidof(ICorProfilerCallback7), (LPVOID*)&pCorProfilerCallback7);
if (SUCCEEDED(hr))
{
profilerCallbackHolder->m_CorProfilerCallback7 = pCorProfilerCallback7;
}
// ICorProfilerCallback6
if (profilerCallbackHolder->m_CorProfilerCallback7)
{
profilerCallbackHolder->m_CorProfilerCallback6 = static_cast<ICorProfilerCallback6*>(profilerCallbackHolder->m_CorProfilerCallback7);
}
else
{
CComPtr<ICorProfilerCallback6> pCorProfilerCallback6;
hr = pUnkProfilerCallback->QueryInterface(__uuidof(ICorProfilerCallback6), (LPVOID*)&pCorProfilerCallback6);
if (SUCCEEDED(hr))
{
profilerCallbackHolder->m_CorProfilerCallback6 = pCorProfilerCallback6;
}
}
// ICorProfilerCallback5
if (profilerCallbackHolder->m_CorProfilerCallback6)
{
profilerCallbackHolder->m_CorProfilerCallback5 = static_cast<ICorProfilerCallback5*>(profilerCallbackHolder->m_CorProfilerCallback6);
}
else
{
CComPtr<ICorProfilerCallback5> pCorProfilerCallback5;
hr = pUnkProfilerCallback->QueryInterface(__uuidof(ICorProfilerCallback5), (LPVOID*)&pCorProfilerCallback5);
if (SUCCEEDED(hr))
{
profilerCallbackHolder->m_CorProfilerCallback5 = pCorProfilerCallback5;
}
}
// ICorProfilerCallback4
if (profilerCallbackHolder->m_CorProfilerCallback5)
{
profilerCallbackHolder->m_CorProfilerCallback4 = static_cast<ICorProfilerCallback4*>(profilerCallbackHolder->m_CorProfilerCallback5);
}
else
{
CComPtr<ICorProfilerCallback4> pCorProfilerCallback4;
hr = pUnkProfilerCallback->QueryInterface(__uuidof(ICorProfilerCallback4), (LPVOID*)&pCorProfilerCallback4);
if (SUCCEEDED(hr))
{
profilerCallbackHolder->m_CorProfilerCallback4 = pCorProfilerCallback4;
}
}
// ICorProfilerCallback3
if (profilerCallbackHolder->m_CorProfilerCallback4)
{
profilerCallbackHolder->m_CorProfilerCallback3 = static_cast<ICorProfilerCallback3*>(profilerCallbackHolder->m_CorProfilerCallback4);
}
else
{
CComPtr<ICorProfilerCallback3> pCorProfilerCallback3;
hr = pUnkProfilerCallback->QueryInterface(__uuidof(ICorProfilerCallback3), (LPVOID*)&pCorProfilerCallback3);
if (SUCCEEDED(hr))
{
profilerCallbackHolder->m_CorProfilerCallback3 = pCorProfilerCallback3;
}
}
// ICorProfilerCallback2
if (profilerCallbackHolder->m_CorProfilerCallback3)
{
profilerCallbackHolder->m_CorProfilerCallback2 = static_cast<ICorProfilerCallback2*>(profilerCallbackHolder->m_CorProfilerCallback3);
}
else
{
CComPtr<ICorProfilerCallback2> pCorProfilerCallback2;
hr = pUnkProfilerCallback->QueryInterface(__uuidof(ICorProfilerCallback2), (LPVOID*)&pCorProfilerCallback2);
if (SUCCEEDED(hr))
{
profilerCallbackHolder->m_CorProfilerCallback2 = pCorProfilerCallback2;
}
}
// ICorProfilerCallback
if (profilerCallbackHolder->m_CorProfilerCallback2)
{
profilerCallbackHolder->m_CorProfilerCallback = static_cast<ICorProfilerCallback*>(profilerCallbackHolder->m_CorProfilerCallback2);
}
else
{
CComPtr<ICorProfilerCallback> pCorProfilerCallback;
hr = pUnkProfilerCallback->QueryInterface(__uuidof(ICorProfilerCallback), (LPVOID*)&pCorProfilerCallback);
if (SUCCEEDED(hr))
{
profilerCallbackHolder->m_CorProfilerCallback = pCorProfilerCallback;
}
}
// ICorProfiler::Initialize happens before any other callbacks so this shouldn't have any race conditions
InterlockedExchangePointer((void**)&m_profilerCallbackHolder, profilerCallbackHolder);
return S_OK;
}