in CppCustomVisualizer/dll/_EntryPoint.cpp [137:241]
HRESULT STDMETHODCALLTYPE CCppCustomVisualizerService::UseDefaultEvaluationBehavior(
_In_ Evaluation::DkmVisualizedExpression* pVisualizedExpression,
_Out_ bool* pUseDefaultEvaluationBehavior,
_Deref_out_opt_ Evaluation::DkmEvaluationResult** ppDefaultEvaluationResult
)
{
HRESULT hr;
// This method is called by the expression evaluator when a visualized expression's children are
// being expanded, or the value is being set. We just want to delegate this back to the C++ EE.
// So we need to set `*pUseDefaultEvaluationBehavior` to true and return the evaluation result which would
// be created if this custom visualizer didn't exist.
//
// NOTE: If this custom visualizer supported underlying strings (no DkmEvaluationResultFlags::RawString),
// this method would also be called when that is requested.
DkmRootVisualizedExpression* pRootVisualizedExpression = DkmRootVisualizedExpression::TryCast(pVisualizedExpression);
if (pRootVisualizedExpression == nullptr)
{
// This sample doesn't provide child evaluation results, so only root expressions are expected
return E_NOTIMPL;
}
DkmInspectionContext* pParentInspectionContext = pVisualizedExpression->InspectionContext();
CAutoDkmClosePtr<DkmLanguageExpression> pLanguageExpression;
hr = DkmLanguageExpression::Create(
pParentInspectionContext->Language(),
DkmEvaluationFlags::TreatAsExpression,
pRootVisualizedExpression->FullName(),
DkmDataItem::Null(),
&pLanguageExpression
);
if (FAILED(hr))
{
return hr;
}
// Create a new inspection context with 'DkmEvaluationFlags::ShowValueRaw' set. This is important because
// the result of the expression is a FILETIME, and we don't want our visualizer to be invoked again. This
// step would be unnecessary if we were evaluating a different expression that resulted in a type which
// we didn't visualize.
CComPtr<DkmInspectionContext> pInspectionContext;
if (DkmComponentManager::IsApiVersionSupported(DkmApiVersion::VS16RTMPreview))
{
// If we are running in VS 16 or newer, use this overload...
hr = DkmInspectionContext::Create(
pParentInspectionContext->InspectionSession(),
pParentInspectionContext->RuntimeInstance(),
pParentInspectionContext->Thread(),
pParentInspectionContext->Timeout(),
DkmEvaluationFlags::TreatAsExpression |
DkmEvaluationFlags::ShowValueRaw,
pParentInspectionContext->FuncEvalFlags(),
pParentInspectionContext->Radix(),
pParentInspectionContext->Language(),
pParentInspectionContext->ReturnValue(),
(Evaluation::DkmCompiledVisualizationData*)nullptr,
Evaluation::DkmCompiledVisualizationDataPriority::None,
pParentInspectionContext->ReturnValues(),
pParentInspectionContext->SymbolsConnection(),
&pInspectionContext
);
}
else
{
// Otherwise fall back to the Visual Studio 14 version
hr = DkmInspectionContext::Create(
pParentInspectionContext->InspectionSession(),
pParentInspectionContext->RuntimeInstance(),
pParentInspectionContext->Thread(),
pParentInspectionContext->Timeout(),
DkmEvaluationFlags::TreatAsExpression |
DkmEvaluationFlags::ShowValueRaw,
pParentInspectionContext->FuncEvalFlags(),
pParentInspectionContext->Radix(),
pParentInspectionContext->Language(),
pParentInspectionContext->ReturnValue(),
(Evaluation::DkmCompiledVisualizationData*)nullptr,
Evaluation::DkmCompiledVisualizationDataPriority::None,
pParentInspectionContext->ReturnValues(),
&pInspectionContext
);
}
if (FAILED(hr))
{
return hr;
}
CComPtr<DkmEvaluationResult> pEEEvaluationResult;
hr = pVisualizedExpression->EvaluateExpressionCallback(
pInspectionContext,
pLanguageExpression,
pVisualizedExpression->StackFrame(),
&pEEEvaluationResult
);
if (FAILED(hr))
{
return hr;
}
*ppDefaultEvaluationResult = pEEEvaluationResult.Detach();
*pUseDefaultEvaluationBehavior = true;
return S_OK;
}