blob: 1f0e2bc6708e22013c7d6422f573981da257c8a5 [file] [log] [blame]
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "tools/v8windbg/base/utilities.h"
#include <comutil.h>
#include <oleauto.h>
#include <vector>
namespace {
HRESULT BoxObject(IDataModelManager* p_manager, IUnknown* p_object,
ModelObjectKind kind, IModelObject** pp_model_object) {
*pp_model_object = nullptr;
VARIANT vt_val;
vt_val.vt = VT_UNKNOWN;
vt_val.punkVal = p_object;
HRESULT hr = p_manager->CreateIntrinsicObject(kind, &vt_val, pp_model_object);
return hr;
}
} // namespace
HRESULT CreateProperty(IDataModelManager* p_manager,
IModelPropertyAccessor* p_property,
IModelObject** pp_property_object) {
return BoxObject(p_manager, p_property, ObjectPropertyAccessor,
pp_property_object);
}
HRESULT CreateMethod(IDataModelManager* p_manager, IModelMethod* p_method,
IModelObject** pp_method_object) {
return BoxObject(p_manager, p_method, ObjectMethod, pp_method_object);
}
HRESULT UnboxProperty(IModelObject* object, IModelPropertyAccessor** result) {
ModelObjectKind kind = (ModelObjectKind)-1;
RETURN_IF_FAIL(object->GetKind(&kind));
if (kind != ObjectPropertyAccessor) return E_FAIL;
_variant_t variant;
RETURN_IF_FAIL(object->GetIntrinsicValue(&variant));
if (variant.vt != VT_UNKNOWN) return E_FAIL;
WRL::ComPtr<IModelPropertyAccessor> accessor;
RETURN_IF_FAIL(WRL::ComPtr<IUnknown>(variant.punkVal).As(&accessor));
*result = accessor.Detach();
return S_OK;
}
HRESULT CreateTypedIntrinsic(uint64_t value, IDebugHostType* type,
IModelObject** result) {
// Figure out what kind of VARIANT we need to make.
IntrinsicKind kind;
VARTYPE carrier;
RETURN_IF_FAIL(type->GetIntrinsicType(&kind, &carrier));
VARIANT vt_val;
switch (carrier) {
case VT_BOOL:
vt_val.boolVal = value ? VARIANT_TRUE : VARIANT_FALSE;
break;
case VT_I1:
vt_val.cVal = static_cast<int8_t>(value);
break;
case VT_UI1:
vt_val.bVal = static_cast<uint8_t>(value);
break;
case VT_I2:
vt_val.iVal = static_cast<int16_t>(value);
break;
case VT_UI2:
vt_val.uiVal = static_cast<uint16_t>(value);
break;
case VT_INT:
vt_val.intVal = static_cast<int>(value);
break;
case VT_UINT:
vt_val.uintVal = static_cast<unsigned int>(value);
break;
case VT_I4:
vt_val.lVal = static_cast<int32_t>(value);
break;
case VT_UI4:
vt_val.ulVal = static_cast<uint32_t>(value);
break;
case VT_INT_PTR:
vt_val.llVal = static_cast<intptr_t>(value);
break;
case VT_UINT_PTR:
vt_val.ullVal = static_cast<uintptr_t>(value);
break;
case VT_I8:
vt_val.llVal = static_cast<int64_t>(value);
break;
case VT_UI8:
vt_val.ullVal = static_cast<uint64_t>(value);
break;
default:
return E_FAIL;
}
vt_val.vt = carrier;
return sp_data_model_manager->CreateTypedIntrinsicObject(&vt_val, type,
result);
}
HRESULT CreateULong64(ULONG64 value, IModelObject** pp_int) {
HRESULT hr = S_OK;
*pp_int = nullptr;
VARIANT vt_val;
vt_val.vt = VT_UI8;
vt_val.ullVal = value;
hr = sp_data_model_manager->CreateIntrinsicObject(ObjectIntrinsic, &vt_val,
pp_int);
return hr;
}
HRESULT UnboxULong64(IModelObject* object, ULONG64* value, bool convert) {
ModelObjectKind kind = (ModelObjectKind)-1;
RETURN_IF_FAIL(object->GetKind(&kind));
if (kind != ObjectIntrinsic) return E_FAIL;
_variant_t variant;
RETURN_IF_FAIL(object->GetIntrinsicValue(&variant));
if (convert) {
RETURN_IF_FAIL(VariantChangeType(&variant, &variant, 0, VT_UI8));
}
if (variant.vt != VT_UI8) return E_FAIL;
*value = variant.ullVal;
return S_OK;
}
HRESULT GetInt32(IDebugHostConstant* object, int* value) {
variant_t variant;
RETURN_IF_FAIL(object->GetValue(&variant));
if (variant.vt != VT_I4) return E_FAIL;
*value = variant.ullVal;
return S_OK;
}
HRESULT CreateInt32(int value, IModelObject** pp_int) {
HRESULT hr = S_OK;
*pp_int = nullptr;
VARIANT vt_val;
vt_val.vt = VT_I4;
vt_val.intVal = value;
hr = sp_data_model_manager->CreateIntrinsicObject(ObjectIntrinsic, &vt_val,
pp_int);
return hr;
}
HRESULT CreateUInt32(uint32_t value, IModelObject** pp_int) {
HRESULT hr = S_OK;
*pp_int = nullptr;
VARIANT vt_val;
vt_val.vt = VT_UI4;
vt_val.uintVal = value;
hr = sp_data_model_manager->CreateIntrinsicObject(ObjectIntrinsic, &vt_val,
pp_int);
return hr;
}
HRESULT CreateBool(bool value, IModelObject** pp_val) {
HRESULT hr = S_OK;
*pp_val = nullptr;
VARIANT vt_val;
vt_val.vt = VT_BOOL;
vt_val.boolVal = value;
hr = sp_data_model_manager->CreateIntrinsicObject(ObjectIntrinsic, &vt_val,
pp_val);
return hr;
}
HRESULT CreateNumber(double value, IModelObject** pp_val) {
HRESULT hr = S_OK;
*pp_val = nullptr;
VARIANT vt_val;
vt_val.vt = VT_R8;
vt_val.dblVal = value;
hr = sp_data_model_manager->CreateIntrinsicObject(ObjectIntrinsic, &vt_val,
pp_val);
return hr;
}
HRESULT CreateString(std::u16string value, IModelObject** pp_val) {
HRESULT hr = S_OK;
*pp_val = nullptr;
VARIANT vt_val;
vt_val.vt = VT_BSTR;
vt_val.bstrVal =
::SysAllocString(reinterpret_cast<const OLECHAR*>(value.c_str()));
hr = sp_data_model_manager->CreateIntrinsicObject(ObjectIntrinsic, &vt_val,
pp_val);
return hr;
}
HRESULT UnboxString(IModelObject* object, BSTR* value) {
ModelObjectKind kind = (ModelObjectKind)-1;
RETURN_IF_FAIL(object->GetKind(&kind));
if (kind != ObjectIntrinsic) return E_FAIL;
_variant_t variant;
RETURN_IF_FAIL(object->GetIntrinsicValue(&variant));
if (variant.vt != VT_BSTR) return E_FAIL;
*value = variant.Detach().bstrVal;
return S_OK;
}
HRESULT GetModelAtIndex(WRL::ComPtr<IModelObject>& sp_parent,
WRL::ComPtr<IModelObject>& sp_index,
IModelObject** p_result) {
WRL::ComPtr<IIndexableConcept> sp_indexable_concept;
RETURN_IF_FAIL(sp_parent->GetConcept(__uuidof(IIndexableConcept),
&sp_indexable_concept, nullptr));
std::vector<IModelObject*> p_indexers{sp_index.Get()};
return sp_indexable_concept->GetAt(sp_parent.Get(), 1, p_indexers.data(),
p_result, nullptr);
}
HRESULT GetCurrentThread(WRL::ComPtr<IDebugHostContext>& sp_host_context,
IModelObject** p_current_thread) {
WRL::ComPtr<IModelObject> sp_boxed_context, sp_root_namespace;
WRL::ComPtr<IModelObject> sp_debugger, sp_sessions, sp_processes, sp_threads;
WRL::ComPtr<IModelObject> sp_curr_session, sp_curr_process;
RETURN_IF_FAIL(BoxObject(sp_data_model_manager.Get(), sp_host_context.Get(),
ObjectContext, &sp_boxed_context));
RETURN_IF_FAIL(sp_data_model_manager->GetRootNamespace(&sp_root_namespace));
RETURN_IF_FAIL(
sp_root_namespace->GetKeyValue(L"Debugger", &sp_debugger, nullptr));
RETURN_IF_FAIL(sp_debugger->GetKeyValue(L"Sessions", &sp_sessions, nullptr));
RETURN_IF_FAIL(
GetModelAtIndex(sp_sessions, sp_boxed_context, &sp_curr_session));
RETURN_IF_FAIL(
sp_curr_session->GetKeyValue(L"Processes", &sp_processes, nullptr));
RETURN_IF_FAIL(
GetModelAtIndex(sp_processes, sp_boxed_context, &sp_curr_process));
RETURN_IF_FAIL(
sp_curr_process->GetKeyValue(L"Threads", &sp_threads, nullptr));
return GetModelAtIndex(sp_threads, sp_boxed_context, p_current_thread);
}