1 // Copyright 2020 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "tools/v8windbg/base/utilities.h"
6
7 #include <comutil.h>
8 #include <oleauto.h>
9
10 #include <vector>
11
12 namespace {
13
BoxObject(IDataModelManager * p_manager,IUnknown * p_object,ModelObjectKind kind,IModelObject ** pp_model_object)14 HRESULT BoxObject(IDataModelManager* p_manager, IUnknown* p_object,
15 ModelObjectKind kind, IModelObject** pp_model_object) {
16 *pp_model_object = nullptr;
17
18 VARIANT vt_val;
19 vt_val.vt = VT_UNKNOWN;
20 vt_val.punkVal = p_object;
21
22 HRESULT hr = p_manager->CreateIntrinsicObject(kind, &vt_val, pp_model_object);
23 return hr;
24 }
25
26 } // namespace
27
CreateProperty(IDataModelManager * p_manager,IModelPropertyAccessor * p_property,IModelObject ** pp_property_object)28 HRESULT CreateProperty(IDataModelManager* p_manager,
29 IModelPropertyAccessor* p_property,
30 IModelObject** pp_property_object) {
31 return BoxObject(p_manager, p_property, ObjectPropertyAccessor,
32 pp_property_object);
33 }
34
CreateMethod(IDataModelManager * p_manager,IModelMethod * p_method,IModelObject ** pp_method_object)35 HRESULT CreateMethod(IDataModelManager* p_manager, IModelMethod* p_method,
36 IModelObject** pp_method_object) {
37 return BoxObject(p_manager, p_method, ObjectMethod, pp_method_object);
38 }
39
UnboxProperty(IModelObject * object,IModelPropertyAccessor ** result)40 HRESULT UnboxProperty(IModelObject* object, IModelPropertyAccessor** result) {
41 ModelObjectKind kind = (ModelObjectKind)-1;
42 RETURN_IF_FAIL(object->GetKind(&kind));
43 if (kind != ObjectPropertyAccessor) return E_FAIL;
44 _variant_t variant;
45 RETURN_IF_FAIL(object->GetIntrinsicValue(&variant));
46 if (variant.vt != VT_UNKNOWN) return E_FAIL;
47 WRL::ComPtr<IModelPropertyAccessor> accessor;
48 RETURN_IF_FAIL(WRL::ComPtr<IUnknown>(variant.punkVal).As(&accessor));
49 *result = accessor.Detach();
50 return S_OK;
51 }
52
CreateTypedIntrinsic(uint64_t value,IDebugHostType * type,IModelObject ** result)53 HRESULT CreateTypedIntrinsic(uint64_t value, IDebugHostType* type,
54 IModelObject** result) {
55 // Figure out what kind of VARIANT we need to make.
56 IntrinsicKind kind;
57 VARTYPE carrier;
58 RETURN_IF_FAIL(type->GetIntrinsicType(&kind, &carrier));
59
60 VARIANT vt_val;
61 switch (carrier) {
62 case VT_BOOL:
63 vt_val.boolVal = value ? VARIANT_TRUE : VARIANT_FALSE;
64 break;
65 case VT_I1:
66 vt_val.cVal = static_cast<int8_t>(value);
67 break;
68 case VT_UI1:
69 vt_val.bVal = static_cast<uint8_t>(value);
70 break;
71 case VT_I2:
72 vt_val.iVal = static_cast<int16_t>(value);
73 break;
74 case VT_UI2:
75 vt_val.uiVal = static_cast<uint16_t>(value);
76 break;
77 case VT_INT:
78 vt_val.intVal = static_cast<int>(value);
79 break;
80 case VT_UINT:
81 vt_val.uintVal = static_cast<unsigned int>(value);
82 break;
83 case VT_I4:
84 vt_val.lVal = static_cast<int32_t>(value);
85 break;
86 case VT_UI4:
87 vt_val.ulVal = static_cast<uint32_t>(value);
88 break;
89 case VT_INT_PTR:
90 vt_val.llVal = static_cast<intptr_t>(value);
91 break;
92 case VT_UINT_PTR:
93 vt_val.ullVal = static_cast<uintptr_t>(value);
94 break;
95 case VT_I8:
96 vt_val.llVal = static_cast<int64_t>(value);
97 break;
98 case VT_UI8:
99 vt_val.ullVal = static_cast<uint64_t>(value);
100 break;
101 default:
102 return E_FAIL;
103 }
104 vt_val.vt = carrier;
105 return sp_data_model_manager->CreateTypedIntrinsicObject(&vt_val, type,
106 result);
107 }
108
CreateULong64(ULONG64 value,IModelObject ** pp_int)109 HRESULT CreateULong64(ULONG64 value, IModelObject** pp_int) {
110 HRESULT hr = S_OK;
111 *pp_int = nullptr;
112
113 VARIANT vt_val;
114 vt_val.vt = VT_UI8;
115 vt_val.ullVal = value;
116
117 hr = sp_data_model_manager->CreateIntrinsicObject(ObjectIntrinsic, &vt_val,
118 pp_int);
119 return hr;
120 }
121
UnboxULong64(IModelObject * object,ULONG64 * value,bool convert)122 HRESULT UnboxULong64(IModelObject* object, ULONG64* value, bool convert) {
123 ModelObjectKind kind = (ModelObjectKind)-1;
124 RETURN_IF_FAIL(object->GetKind(&kind));
125 if (kind != ObjectIntrinsic) return E_FAIL;
126 _variant_t variant;
127 RETURN_IF_FAIL(object->GetIntrinsicValue(&variant));
128 if (convert) {
129 RETURN_IF_FAIL(VariantChangeType(&variant, &variant, 0, VT_UI8));
130 }
131 if (variant.vt != VT_UI8) return E_FAIL;
132 *value = variant.ullVal;
133 return S_OK;
134 }
135
GetInt32(IDebugHostConstant * object,int * value)136 HRESULT GetInt32(IDebugHostConstant* object, int* value) {
137 variant_t variant;
138 RETURN_IF_FAIL(object->GetValue(&variant));
139
140 if (variant.vt != VT_I4) return E_FAIL;
141 *value = variant.lVal;
142 return S_OK;
143 }
144
CreateInt32(int value,IModelObject ** pp_int)145 HRESULT CreateInt32(int value, IModelObject** pp_int) {
146 HRESULT hr = S_OK;
147 *pp_int = nullptr;
148
149 VARIANT vt_val;
150 vt_val.vt = VT_I4;
151 vt_val.intVal = value;
152
153 hr = sp_data_model_manager->CreateIntrinsicObject(ObjectIntrinsic, &vt_val,
154 pp_int);
155 return hr;
156 }
157
CreateUInt32(uint32_t value,IModelObject ** pp_int)158 HRESULT CreateUInt32(uint32_t value, IModelObject** pp_int) {
159 HRESULT hr = S_OK;
160 *pp_int = nullptr;
161
162 VARIANT vt_val;
163 vt_val.vt = VT_UI4;
164 vt_val.uintVal = value;
165
166 hr = sp_data_model_manager->CreateIntrinsicObject(ObjectIntrinsic, &vt_val,
167 pp_int);
168 return hr;
169 }
170
CreateBool(bool value,IModelObject ** pp_val)171 HRESULT CreateBool(bool value, IModelObject** pp_val) {
172 HRESULT hr = S_OK;
173 *pp_val = nullptr;
174
175 VARIANT vt_val;
176 vt_val.vt = VT_BOOL;
177 vt_val.boolVal = value;
178
179 hr = sp_data_model_manager->CreateIntrinsicObject(ObjectIntrinsic, &vt_val,
180 pp_val);
181 return hr;
182 }
183
CreateNumber(double value,IModelObject ** pp_val)184 HRESULT CreateNumber(double value, IModelObject** pp_val) {
185 HRESULT hr = S_OK;
186 *pp_val = nullptr;
187
188 VARIANT vt_val;
189 vt_val.vt = VT_R8;
190 vt_val.dblVal = value;
191
192 hr = sp_data_model_manager->CreateIntrinsicObject(ObjectIntrinsic, &vt_val,
193 pp_val);
194 return hr;
195 }
196
CreateString(std::u16string value,IModelObject ** pp_val)197 HRESULT CreateString(std::u16string value, IModelObject** pp_val) {
198 HRESULT hr = S_OK;
199 *pp_val = nullptr;
200
201 VARIANT vt_val;
202 vt_val.vt = VT_BSTR;
203 vt_val.bstrVal =
204 ::SysAllocString(reinterpret_cast<const OLECHAR*>(value.c_str()));
205
206 hr = sp_data_model_manager->CreateIntrinsicObject(ObjectIntrinsic, &vt_val,
207 pp_val);
208 return hr;
209 }
210
UnboxString(IModelObject * object,BSTR * value)211 HRESULT UnboxString(IModelObject* object, BSTR* value) {
212 ModelObjectKind kind = (ModelObjectKind)-1;
213 RETURN_IF_FAIL(object->GetKind(&kind));
214 if (kind != ObjectIntrinsic) return E_FAIL;
215 _variant_t variant;
216 RETURN_IF_FAIL(object->GetIntrinsicValue(&variant));
217 if (variant.vt != VT_BSTR) return E_FAIL;
218 *value = variant.Detach().bstrVal;
219 return S_OK;
220 }
221
GetModelAtIndex(WRL::ComPtr<IModelObject> & sp_parent,WRL::ComPtr<IModelObject> & sp_index,IModelObject ** p_result)222 HRESULT GetModelAtIndex(WRL::ComPtr<IModelObject>& sp_parent,
223 WRL::ComPtr<IModelObject>& sp_index,
224 IModelObject** p_result) {
225 WRL::ComPtr<IIndexableConcept> sp_indexable_concept;
226 RETURN_IF_FAIL(sp_parent->GetConcept(__uuidof(IIndexableConcept),
227 &sp_indexable_concept, nullptr));
228
229 std::vector<IModelObject*> p_indexers{sp_index.Get()};
230 return sp_indexable_concept->GetAt(sp_parent.Get(), 1, p_indexers.data(),
231 p_result, nullptr);
232 }
233
GetCurrentThread(WRL::ComPtr<IDebugHostContext> & sp_host_context,IModelObject ** p_current_thread)234 HRESULT GetCurrentThread(WRL::ComPtr<IDebugHostContext>& sp_host_context,
235 IModelObject** p_current_thread) {
236 WRL::ComPtr<IModelObject> sp_boxed_context, sp_root_namespace;
237 WRL::ComPtr<IModelObject> sp_debugger, sp_sessions, sp_processes, sp_threads;
238 WRL::ComPtr<IModelObject> sp_curr_session, sp_curr_process;
239
240 RETURN_IF_FAIL(BoxObject(sp_data_model_manager.Get(), sp_host_context.Get(),
241 ObjectContext, &sp_boxed_context));
242 RETURN_IF_FAIL(sp_data_model_manager->GetRootNamespace(&sp_root_namespace));
243 RETURN_IF_FAIL(
244 sp_root_namespace->GetKeyValue(L"Debugger", &sp_debugger, nullptr));
245 RETURN_IF_FAIL(sp_debugger->GetKeyValue(L"Sessions", &sp_sessions, nullptr));
246 RETURN_IF_FAIL(
247 GetModelAtIndex(sp_sessions, sp_boxed_context, &sp_curr_session));
248 RETURN_IF_FAIL(
249 sp_curr_session->GetKeyValue(L"Processes", &sp_processes, nullptr));
250 RETURN_IF_FAIL(
251 GetModelAtIndex(sp_processes, sp_boxed_context, &sp_curr_process));
252 RETURN_IF_FAIL(
253 sp_curr_process->GetKeyValue(L"Threads", &sp_threads, nullptr));
254 return GetModelAtIndex(sp_threads, sp_boxed_context, p_current_thread);
255 }
256