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