GCC Code Coverage Report


Directory: src/gate/
File: src/gate/system/management.c
Date: 2026-03-20 22:56:14
Exec Total Coverage
Lines: 0 48 0.0%
Functions: 0 13 0.0%
Branches: 0 14 0.0%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright(c) 2018-2026, Stefan Meislinger |
4 | All rights reserved. |
5 | |
6 | Redistribution and use in source and binary forms, with or without |
7 | modification, are permitted provided that the following conditions are met:|
8 | |
9 | 1. Redistributions of source code must retain the above copyright notice, |
10 | this list of conditions and the following disclaimer. |
11 | 2. Redistributions in binary form must reproduce the above copyright |
12 | notice, this list of conditions and the following disclaimer in the |
13 | documentation and/or other materials provided with the distribution. |
14 | |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"|
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
25 | THE POSSIBILITY OF SUCH DAMAGE. |
26 +----------------------------------------------------------------------------+
27 */
28
29 #include "gate/system/management.h"
30 #include "gate/results.h"
31 #include "gate/comparers.h"
32 #include "gate/debugging.h"
33 #include "gate/utilities.h"
34
35 #if defined(GATE_SYS_WIN) && !defined(GATE_SYS_WIN16)
36 # define GATE_SYSTEM_MANAGEMENT_WINAPI_IMPL
37 #else
38 # define GATE_SYSTEM_MANAGEMENT_NO_IMPL
39 #endif
40
41
42
43 gate_management_object_t* gate_management_object_copy(gate_management_object_t* dest, gate_management_object_t const* source)
44 {
45 gate_management_object_t* ret = NULL;
46 do
47 {
48 gate_mem_clear(dest, sizeof(gate_management_object_t));
49
50 if (NULL == gate_map_copy(&dest->properties, &source->properties))
51 {
52 break;
53 }
54 if (NULL == gate_string_clone(&dest->path, &source->path))
55 {
56 break;
57 }
58 if (NULL == gate_string_clone(&dest->name, &source->name))
59 {
60 break;
61 }
62 if (NULL == gate_string_clone(&dest->type, &source->type))
63 {
64 break;
65 }
66 /* success */
67 ret = dest;
68 } while (0);
69
70 if ((ret == NULL) && (dest != NULL))
71 {
72 gate_string_release(&dest->type);
73 gate_string_release(&dest->name);
74 gate_string_release(&dest->path);
75 gate_map_destroy(&dest->properties);
76 }
77 return ret;
78 }
79
80 void gate_management_object_release(gate_management_object_t* mgmt_obj)
81 {
82 if (mgmt_obj)
83 {
84 gate_string_release(&mgmt_obj->type);
85 gate_string_release(&mgmt_obj->name);
86 gate_string_release(&mgmt_obj->path);
87 gate_map_destroy(&mgmt_obj->properties);
88 gate_mem_clear(mgmt_obj, sizeof(gate_management_object_t));
89 }
90 }
91
92
93 #if defined(GATE_SYSTEM_MANAGEMENT_WINAPI_IMPL)
94
95 #include "gate/system/platform/management_wmi.h"
96
97
98 static gate_string_t const subsys_wmi = GATE_STRING_INIT_STATIC("wmi");
99
100 static gate_string_t const token_path_prefix = GATE_STRING_INIT_STATIC("\\\\");
101 static gate_string_t const token_host_separator = GATE_STRING_INIT_STATIC("\\");
102 static gate_string_t const token_default_host = GATE_STRING_INIT_STATIC(".");
103 static gate_string_t const token_ns_root = GATE_STRING_INIT_STATIC("ROOT");
104 static gate_string_t const token_default_ns = GATE_STRING_INIT_STATIC("ROOT\\CIMV2");
105 static gate_string_t const token_ns_separator = GATE_STRING_INIT_STATIC("\\");
106 static gate_string_t const token_ns_class_separator = GATE_STRING_INIT_STATIC(":");
107 static gate_string_t const token_class_instance_separator = GATE_STRING_INIT_STATIC(".");
108 static gate_string_t const token_singleton = GATE_STRING_INIT_STATIC("=@");
109
110 static gate_string_t const uid_prefix = GATE_STRING_INIT_STATIC("\\\\.\\");
111 static gate_string_t const ns_root_cimv2 = GATE_STRING_INIT_STATIC("ROOT\\CIMV2");
112
113 typedef struct gate_management_impl_class
114 {
115 gate_string_t host;
116 gate_string_t sub_system;
117 gate_string_t name_space;
118 } gate_management_impl_t;
119
120
121 #define GATE_BREAK_IF_ZERO(len_var, result_var) if(0 == (len_var)) { result_var = GATE_RESULT_OUTOFMEMORY; break; }
122
123 static gate_result_t gate_mgmt_build_path(gate_strbuilder_t* builder, gate_string_t const* host, gate_string_t const* name_space,
124 gate_string_t const* class_name, gate_string_t const* instance_name)
125 {
126 gate_result_t ret = GATE_RESULT_OK;
127 gate_size_t len = 0;
128
129 do
130 {
131 len = gate_strbuilder_append_string(builder, &token_path_prefix);
132 GATE_BREAK_IF_ZERO(len, ret);
133
134 if (gate_string_is_empty(host))
135 {
136 len = gate_strbuilder_append_string(builder, &token_default_host);
137 }
138 else
139 {
140 len = gate_strbuilder_append_string(builder, host);
141 }
142 GATE_BREAK_IF_ZERO(len, ret);
143
144 len = gate_strbuilder_append_string(builder, &token_host_separator);
145 GATE_BREAK_IF_ZERO(len, ret);
146
147 if (gate_string_is_empty(name_space))
148 {
149 len = gate_strbuilder_append_string(builder, &token_default_ns);
150 }
151 else
152 {
153 len = gate_strbuilder_append_string(builder, name_space);
154 }
155 GATE_BREAK_IF_ZERO(len, ret);
156
157 if (!gate_string_is_empty(class_name))
158 {
159 len = gate_strbuilder_append_string(builder, &token_ns_class_separator);
160 GATE_BREAK_IF_ZERO(len, ret);
161
162 len = gate_strbuilder_append_string(builder, class_name);
163 GATE_BREAK_IF_ZERO(len, ret);
164
165 if (gate_string_is_empty(instance_name))
166 {
167 len = gate_strbuilder_append_string(builder, &token_class_instance_separator);
168 GATE_BREAK_IF_ZERO(len, ret);
169 len = gate_strbuilder_append_string(builder, instance_name);
170 GATE_BREAK_IF_ZERO(len, ret);
171 }
172 }
173 } while (0);
174
175 GATE_DEBUG_TRACE_FAILED_RESULT(ret);
176 return ret;
177 }
178 #undef GATE_BREAK_IF_ZERO
179
180
181 static IWbemServices* gate_mgmt_load_wmi_service_impl(gate_string_t const* host, gate_string_t const* name_space,
182 gate_string_t const* user, gate_string_t const* password)
183 {
184 gate_result_t result;
185 IWbemServices* ret = NULL;
186 IWbemLocator* locator = NULL;
187 char path_buffer[4096];
188 gate_strbuilder_t path_builder = GATE_INIT_EMPTY;
189 gate_string_t path = GATE_STRING_INIT_EMPTY;
190 BSTR str_resource = NULL;
191 BSTR str_user = NULL;
192 BSTR str_pass = NULL;
193 HRESULT hr;
194
195 do
196 {
197 gate_strbuilder_create_static(&path_builder, path_buffer, sizeof(path_buffer), 0);
198
199 result = gate_mgmt_build_path(&path_builder, host, name_space, NULL, NULL);
200 GATE_BREAK_IF_FAILED(result);
201
202
203 if (!gate_string_is_empty(user))
204 {
205 str_user = gate_win32_bstr_create(user);
206 }
207 if (!gate_string_is_empty(password))
208 {
209 str_pass = gate_win32_bstr_create(password);
210 }
211
212
213 if (NULL == gate_strbuilder_to_string(&path_builder, &path))
214 {
215 break;
216 }
217 GATE_DEBUG_TRACE(path.str);
218
219
220 str_resource = gate_win32_bstr_create(&path);
221 gate_string_release(&path);
222
223 hr = gate_win32_com_create_instance(&CLSID_WbemLocator, &IID_IWbemLocator, (LPVOID*)&locator);
224 if (FAILED(hr))
225 {
226 GATE_DEBUG_TRACE("CoCreateInstance() failed");
227 GATE_DEBUG_TRACE_VALUE(hr);
228 break;
229 }
230
231 hr = locator->lpVtbl->ConnectServer(locator, str_resource, str_user, str_pass, NULL, 0, NULL, NULL, &ret);
232 if (FAILED(hr))
233 {
234 GATE_DEBUG_TRACE("locator->ConnectServer() failed");
235 GATE_DEBUG_TRACE(path.str);
236 GATE_DEBUG_TRACE_VALUE(hr);
237 break;
238 }
239 } while (0);
240
241 if (locator != NULL)
242 {
243 locator->lpVtbl->Release(locator);
244 }
245 if (str_resource != NULL) gate_win32_bstr_release(str_resource);
246 if (str_user != NULL) gate_win32_bstr_release(str_user);
247 if (str_pass != NULL) gate_win32_bstr_release(str_pass);
248 gate_strbuilder_release(&path_builder);
249
250 return ret;
251 }
252
253 static gate_result_t gate_mgmt_load_wmi_service(gate_string_t const* host, gate_string_t const* name_space,
254 gate_string_t const* user, gate_string_t const* password,
255 IWbemServices** services, gate_bool_t* uninit)
256 {
257 gate_result_t ret = gate_win32_com_init();
258 HRESULT hr = gate_win32_com_init();
259 if (hr == S_OK)
260 {
261 *uninit = true;
262 }
263 else if (hr == S_FALSE)
264 {
265 *uninit = false;
266 }
267 else
268 {
269 *uninit = false;
270 ret = GATE_RESULT_INVALIDSTATE;
271 GATE_DEBUG_TRACE("locator->ConnectServer() failed");
272 GATE_DEBUG_TRACE_VALUE(hr);
273 }
274
275 *services = gate_mgmt_load_wmi_service_impl(host, name_space, user, password);
276 if (*services != NULL)
277 {
278 ret = GATE_RESULT_OK;
279 }
280 else
281 {
282 ret = GATE_RESULT_NOTAVAILABLE;
283 if (*uninit)
284 {
285 gate_win32_com_uninit();
286 *uninit = false;
287 }
288 }
289 GATE_DEBUG_TRACE_FAILED_RESULT(ret);
290 return ret;
291 }
292
293 static gate_result_t gate_mgmt_unload_wmi_service(IWbemServices** services, gate_bool_t* uninit)
294 {
295 if (*services)
296 {
297 (*services)->lpVtbl->Release(*services);
298 *services = NULL;
299 }
300 if (*uninit)
301 {
302 gate_win32_com_uninit();
303 *uninit = false;
304 }
305 return GATE_RESULT_OK;
306 }
307
308 gate_result_t gate_management_open(gate_string_t const* host, gate_string_t const* subsystem, gate_string_t const* name_space,
309 gate_enumint_t flags, gate_management_t* handle)
310 {
311 gate_result_t ret = GATE_RESULT_FAILED;
312 gate_management_impl_t* impl = NULL;
313
314 GATE_UNUSED_ARG(flags);
315 do
316 {
317 if (gate_string_is_empty(subsystem))
318 {
319 subsystem = &subsys_wmi;
320 }
321
322 if (gate_string_is_empty(host))
323 {
324 host = &token_default_host;
325 }
326
327 if (!gate_string_equals_ic(subsystem, &subsys_wmi))
328 {
329 ret = GATE_RESULT_NOTSUPPORTED;
330 break;
331 }
332
333 impl = (gate_management_impl_t*)gate_mem_alloc(sizeof(gate_management_impl_t));
334 if (impl == NULL)
335 {
336 ret = GATE_RESULT_OUTOFMEMORY;
337 break;
338 }
339 gate_mem_clear(impl, sizeof(gate_management_impl_t));
340 gate_string_clone(&impl->host, host);
341 gate_string_clone(&impl->name_space, name_space);
342 gate_string_clone(&impl->sub_system, subsystem);
343
344 *handle = impl;
345 ret = GATE_RESULT_OK;
346 } while (0);
347
348 if (GATE_FAILED(ret))
349 {
350 if (impl)
351 {
352 gate_string_release(&impl->host);
353 gate_string_release(&impl->name_space);
354 gate_string_release(&impl->sub_system);
355 gate_mem_dealloc(impl);
356 }
357 }
358 GATE_DEBUG_TRACE_FAILED_RESULT(ret);
359 return ret;
360 }
361 gate_result_t gate_management_close(gate_management_t handle)
362 {
363 gate_management_impl_t* impl = (gate_management_impl_t*)handle;
364 gate_result_t ret = GATE_RESULT_OK;
365
366 if (impl)
367 {
368 gate_string_release(&impl->host);
369 gate_string_release(&impl->name_space);
370 gate_string_release(&impl->sub_system);
371 gate_mem_dealloc(impl);
372 }
373
374 GATE_DEBUG_TRACE_FAILED_RESULT(ret);
375 return ret;
376 }
377
378 static gate_result_t gate_mgmt_read_properties(IWbemClassObject* wmi_obj, gate_map_t* props, gate_bool_t system_only, gate_bool_t keys_only)
379 {
380 gate_result_t ret = GATE_RESULT_FAILED;
381 LONG enum_flags = system_only ? WBEM_FLAG_SYSTEM_ONLY : WBEM_FLAG_NONSYSTEM_ONLY;
382 HRESULT hr;
383 BSTR bstr_name;
384 gate_string_t str_name;
385 VARIANT var_value = GATE_INIT_EMPTY;
386 gate_value_t value;
387
388 do
389 {
390 if (gate_map_is_empty(props))
391 {
392 gate_map_create(props, &gate_compare_string,
393 sizeof(gate_string_t), &gate_string_copy_constructor, &gate_string_destructor,
394 sizeof(gate_value_t), &gate_value_copy_constructor, &gate_value_destructor);
395 }
396
397 if (keys_only)
398 {
399 enum_flags |= WBEM_FLAG_KEYS_ONLY;
400 }
401 hr = wmi_obj->lpVtbl->BeginEnumeration(wmi_obj, enum_flags);
402 if (FAILED(hr))
403 {
404 GATE_DEBUG_TRACE("wmi->BeginEnumeration() failed");
405 GATE_DEBUG_TRACE_VALUE(hr);
406 ret = GATE_RESULT_FAILED;
407 break;
408 }
409
410 for (;;)
411 {
412 bstr_name = NULL;
413 gate_win32_variant_init(&var_value);
414 hr = wmi_obj->lpVtbl->Next(wmi_obj, 0, &bstr_name, &var_value, NULL, NULL);
415 if (WBEM_S_NO_ERROR != hr)
416 {
417 break;
418 }
419
420 if (NULL == gate_win32_bstr_to_string(bstr_name, &str_name))
421 {
422
423 }
424 else
425 {
426 if (NULL == gate_win32_variant_to_value(&var_value, &value))
427 {
428 /* failed or not supported */
429 }
430 else
431 {
432 gate_map_add(props, &str_name, &value);
433 gate_value_release(&value);
434 }
435 gate_string_release(&str_name);
436 }
437 gate_win32_bstr_release(bstr_name);
438 gate_win32_variant_clear(&var_value);
439 }
440 ret = GATE_RESULT_OK;
441 } while (0);
442
443 GATE_DEBUG_TRACE_FAILED_RESULT(ret);
444 return ret;
445 }
446
447
448
449 static gate_string_t const wmi_property_path = GATE_STRING_INIT_STATIC("__PATH");
450 static gate_string_t const wmi_property_class = GATE_STRING_INIT_STATIC("__CLASS");
451
452 static gate_result_t gate_mgmt_create_object(IWbemClassObject* wmi_obj, gate_management_object_t* target)
453 {
454 gate_result_t ret = GATE_RESULT_FAILED;
455 gate_map_t sys_props = GATE_INIT_EMPTY;
456 gate_map_t key_props = GATE_INIT_EMPTY;
457 gate_value_t const* val_path = NULL;
458 gate_value_t const* val_class = NULL;
459
460 do
461 {
462 ret = gate_mgmt_read_properties(wmi_obj, &sys_props, true, false);
463 GATE_BREAK_IF_FAILED(ret);
464
465 ret = gate_mgmt_read_properties(wmi_obj, &key_props, false, true);
466 GATE_BREAK_IF_FAILED(ret);
467
468 val_path = (gate_value_t const*)gate_map_get_value(&sys_props, &wmi_property_path);
469 val_class = (gate_value_t const*)gate_map_get_value(&sys_props, &wmi_property_class);
470 if (val_path)
471 {
472 gate_value_load_string(val_path->value_type, &val_path->content.ptr_value, &target->path);
473 }
474 if (val_class)
475 {
476 gate_value_load_string(val_class->value_type, &val_class->content.ptr_value, &target->type);
477 }
478
479
480 ret = gate_mgmt_read_properties(wmi_obj, &target->properties, false, false);
481
482 } while (0);
483
484 gate_map_destroy(&sys_props);
485 gate_map_destroy(&key_props);
486
487 GATE_DEBUG_TRACE_FAILED_RESULT(ret);
488 return ret;
489 }
490
491 static gate_result_t gate_mgmt_parse_path(gate_string_t const* wmi_path, gate_string_t* host, gate_string_t* name_space,
492 gate_string_t* class_name, gate_string_t* instance)
493 {
494 gate_size_t posHostEnd;
495 gate_size_t posNsEnd;
496 gate_size_t posClassEnd;
497 //\\W900D049\root\cimv2:Win32_OperatingSystem=@
498 //\\W900D049\root\cimv2:Win32_Process.Handle="0"
499 if (!gate_string_starts_with(wmi_path, &token_path_prefix))
500 {
501 return GATE_RESULT_INVALIDINPUT;
502 }
503 posHostEnd = gate_string_pos(wmi_path, &token_host_separator, 2);
504 if (posHostEnd == GATE_STR_NPOS)
505 {
506 return GATE_RESULT_INVALIDINPUT;
507 }
508 if (host)
509 {
510 gate_string_substr(host, wmi_path, 2, posHostEnd - 2);
511 }
512
513 posNsEnd = gate_string_pos(wmi_path, &token_ns_class_separator, posHostEnd + 1);
514 if (posNsEnd == GATE_STR_NPOS)
515 {
516 gate_string_substr(name_space, wmi_path, posHostEnd + 1, GATE_STR_NPOS);
517 if (class_name)
518 {
519 gate_string_create_empty(class_name);
520 }
521 if (instance)
522 {
523 gate_string_create_empty(instance);
524 }
525 return GATE_RESULT_OK;
526 }
527 if (name_space)
528 {
529 gate_string_substr(name_space, wmi_path, posHostEnd + 1, posNsEnd - posHostEnd - 1);
530 }
531
532 posClassEnd = gate_string_pos(wmi_path, &token_class_instance_separator, posNsEnd + 1);
533 if (posClassEnd == GATE_STR_NPOS)
534 {
535 if (class_name)
536 {
537 gate_string_substr(class_name, wmi_path, posNsEnd + 1, GATE_STR_NPOS);
538 if (gate_string_ends_with(class_name, &token_singleton))
539 {
540 class_name->length -= token_singleton.length;
541 }
542 }
543 if (instance)
544 {
545 gate_string_create_empty(instance);
546 }
547 return GATE_RESULT_OK;
548 }
549 if (class_name)
550 {
551 gate_string_substr(class_name, wmi_path, posNsEnd + 1, posClassEnd - posNsEnd - 1);
552 }
553 if (instance)
554 {
555 gate_string_substr(instance, wmi_path, posClassEnd + 1, GATE_STR_NPOS);
556 }
557 return GATE_RESULT_OK;
558 }
559
560 static gate_result_t gate_mgmt_run_query(IWbemServices* services, gate_string_t const* query,
561 gate_management_callback_t callback, void* user_param)
562 {
563 gate_result_t ret = GATE_RESULT_FAILED;
564 BSTR bstr_lang = gate_win32_bstr_create_wstr(L"WQL");
565 BSTR bstr_query = gate_win32_bstr_create(query);
566 HRESULT hr;
567 IEnumWbemClassObject* ienum = NULL;
568 IWbemClassObject* wmi_obj = NULL;
569 ULONG returned;
570 gate_management_object_t mgmt_obj;
571 gate_bool_t continue_loop = true;
572
573 do
574 {
575 hr = gate_win32_com_set_proxy_blanket((IUnknown*)services, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL,
576 RPC_C_AUTHN_LEVEL_CONNECT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
577 if (FAILED(hr))
578 {
579 GATE_DEBUG_TRACE("CoSetProxyBlanket() failed");
580 GATE_DEBUG_TRACE_VALUE(hr);
581 ret = GATE_RESULT_INVALIDSTATE;
582 break;
583 }
584
585 hr = services->lpVtbl->ExecQuery(services, bstr_lang, bstr_query,
586 WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &ienum);
587 if (FAILED(hr))
588 {
589 GATE_DEBUG_TRACE("services->ExecQuery() failed");
590 GATE_DEBUG_TRACE(query->str);
591 GATE_DEBUG_TRACE_VALUE(hr);
592 ret = GATE_RESULT_FAILED;
593 break;
594 }
595
596 while (continue_loop && (WBEM_S_NO_ERROR == (hr = ienum->lpVtbl->Next(ienum, WBEM_INFINITE, 1, &wmi_obj, &returned))))
597 {
598 gate_mem_clear(&mgmt_obj, sizeof(mgmt_obj));
599
600 ret = gate_mgmt_create_object(wmi_obj, &mgmt_obj);
601 if (GATE_SUCCEEDED(ret))
602 {
603 continue_loop = callback(&mgmt_obj, user_param);
604 gate_management_object_release(&mgmt_obj);
605 }
606 wmi_obj->lpVtbl->Release(wmi_obj);
607 }
608 } while (0);
609
610 if (ienum) ienum->lpVtbl->Release(ienum);
611 if (bstr_query) gate_win32_bstr_release(bstr_query);
612 if (bstr_lang) gate_win32_bstr_release(bstr_lang);
613 GATE_DEBUG_TRACE_FAILED_RESULT(ret);
614 return ret;
615 }
616
617 static gate_bool_t gate_mgmt_cb_use_first(gate_management_object_t const* obj, void* user_param)
618 {
619 gate_management_object_t* dst_obj = (gate_management_object_t*)user_param;
620 gate_mem_clear(dst_obj, sizeof(gate_management_object_t));
621 if (gate_management_object_copy(dst_obj, obj))
622 {
623 return false; /* one found, cancel further iteration */
624 }
625 else
626 {
627 return true; /* continue, try next */
628 }
629 }
630
631 static gate_result_t gate_mgmt_get_object_impl(IWbemServices* services, gate_string_t const* path, gate_management_object_t* obj)
632 {
633 gate_result_t ret;
634 gate_string_t host = GATE_STRING_INIT_EMPTY;
635 gate_string_t ns = GATE_STRING_INIT_EMPTY;
636 gate_string_t class_name = GATE_STRING_INIT_EMPTY;
637 gate_string_t instance = GATE_STRING_INIT_EMPTY;
638 BSTR bstr = NULL;
639 IWbemClassObject* wmi_obj = NULL;
640 gate_strbuilder_t query_builder;
641 char query_buffer[2048];
642 gate_string_t query_string;
643 HRESULT hr;
644
645 do
646 {
647 ret = gate_mgmt_parse_path(path, &host, &ns, &class_name, &instance);
648 GATE_BREAK_IF_FAILED(ret);
649
650 if (gate_string_is_empty(&instance))
651 {
652 /* class query */
653 bstr = gate_win32_bstr_create(path);
654 hr = services->lpVtbl->GetObject(services, bstr, WBEM_FLAG_RETURN_WBEM_COMPLETE, NULL, &wmi_obj, NULL);
655 if (FAILED(hr))
656 {
657 GATE_DEBUG_TRACE("services->GetObjectW failed");
658 GATE_DEBUG_TRACE_VALUE(hr);
659 ret = GATE_RESULT_FAILED;
660 }
661 else
662 {
663 ret = gate_mgmt_create_object(wmi_obj, obj);
664 }
665 }
666 else
667 {
668 static gate_string_t const q_select = GATE_STRING_INIT_STATIC("SELECT * FROM ");
669 static gate_string_t const q_where = GATE_STRING_INIT_STATIC(" WHERE ");
670 char where_buffer[1024];
671 gate_strbuilder_t where_builder;
672 gate_string_t where_clause = GATE_STRING_INIT_EMPTY;
673
674 gate_strbuilder_create_static(&where_builder, where_buffer, sizeof(where_buffer), 0);
675 gate_strbuilder_append_string(&where_builder, &instance);
676 gate_strbuilder_replace_str(&where_builder, ",", 1, " AND ", 5, 0, GATE_STR_NPOS);
677 gate_string_create_static_len(&where_clause,
678 gate_strbuilder_ptr(&where_builder, 0),
679 gate_strbuilder_length(&where_builder)
680 );
681
682 gate_strbuilder_create_static(&query_builder, query_buffer, sizeof(query_buffer), 0);
683 gate_strbuilder_append_string(&query_builder, &q_select);
684 gate_strbuilder_append_string(&query_builder, &class_name);
685 gate_strbuilder_append_string(&query_builder, &q_where);
686 /*gate_strbuilder_append_string(&query_builder, &instance);*/
687 gate_strbuilder_append_string(&query_builder, &where_clause);
688 gate_strbuilder_to_string(&query_builder, &query_string);
689 gate_strbuilder_release(&query_builder);
690
691 ret = gate_mgmt_run_query(services, &query_string, &gate_mgmt_cb_use_first, obj);
692 gate_string_release(&query_string);
693 }
694
695 } while (0);
696
697 if (wmi_obj) wmi_obj->lpVtbl->Release(wmi_obj);
698 if (bstr) gate_win32_bstr_release(bstr);
699 gate_string_release(&instance);
700 gate_string_release(&class_name);
701 gate_string_release(&ns);
702 gate_string_release(&host);
703
704 GATE_DEBUG_TRACE_FAILED_RESULT(ret);
705 return ret;
706 }
707
708 gate_result_t gate_management_get_object(gate_management_t handle, gate_string_t const* path, gate_management_object_t* obj)
709 {
710 gate_result_t ret = GATE_RESULT_FAILED;
711 gate_management_impl_t* impl = (gate_management_impl_t*)handle;
712 IWbemServices* services = NULL;
713 gate_bool_t must_uninit = false;
714
715 ret = gate_mgmt_load_wmi_service(&impl->host, &impl->name_space, NULL, NULL, &services, &must_uninit);
716 if (GATE_SUCCEEDED(ret))
717 {
718 ret = gate_mgmt_get_object_impl(services, path, obj);
719 gate_mgmt_unload_wmi_service(&services, &must_uninit);
720 }
721 GATE_DEBUG_TRACE_FAILED_RESULT(ret);
722 return ret;
723 }
724
725 gate_result_t gate_management_query(gate_management_t handle, gate_string_t const* path, gate_string_t const* query,
726 gate_management_callback_t callback, void* userparam)
727 {
728 gate_result_t ret = GATE_RESULT_FAILED;
729 gate_management_impl_t* impl = (gate_management_impl_t*)handle;
730 IWbemServices* services = NULL;
731 gate_bool_t must_uninit = false;
732
733 ret = gate_mgmt_load_wmi_service(&impl->host, &impl->name_space, NULL, NULL, &services, &must_uninit);
734 if (GATE_SUCCEEDED(ret))
735 {
736 ret = gate_mgmt_run_query(services, query, callback, userparam);
737
738 gate_mgmt_unload_wmi_service(&services, &must_uninit);
739 }
740 GATE_DEBUG_TRACE_FAILED_RESULT(ret);
741 return ret;
742 }
743
744 static gate_string_t const wmi_query_classes = GATE_STRING_INIT_STATIC("Select * From Meta_Class");
745
746 gate_result_t gate_management_list_children(gate_management_t handle, gate_string_t const* path,
747 gate_management_callback_t callback, void* userparam)
748 {
749 gate_result_t ret = GATE_RESULT_FAILED;
750 gate_management_impl_t* impl = (gate_management_impl_t*)handle;
751 IWbemServices* services = NULL;
752 gate_bool_t must_uninit = false;
753 gate_strbuilder_t query_builder = GATE_INIT_EMPTY;
754 char query_buffer[1024];
755 gate_string_t query_string = GATE_STRING_INIT_EMPTY;
756 gate_string_t host = GATE_STRING_INIT_EMPTY;
757 gate_string_t name_space = GATE_STRING_INIT_EMPTY;
758 gate_string_t class_name = GATE_STRING_INIT_EMPTY;
759 gate_string_t instance_name = GATE_STRING_INIT_EMPTY;
760
761 ret = gate_mgmt_load_wmi_service(&impl->host, &impl->name_space, NULL, NULL, &services, &must_uninit);
762 if (GATE_SUCCEEDED(ret))
763 {
764 if (gate_string_is_empty(path))
765 {
766 ret = gate_mgmt_run_query(services, &wmi_query_classes, callback, userparam);
767 }
768 else
769 {
770 ret = gate_mgmt_parse_path(path, &host, &name_space, &class_name, &instance_name);
771 if (GATE_SUCCEEDED(ret))
772 {
773 if (gate_string_is_empty(&class_name))
774 {
775 ret = gate_mgmt_run_query(services, &wmi_query_classes, callback, userparam);
776 }
777 else
778 {
779 gate_strbuilder_create_static(&query_builder, query_buffer, sizeof(query_buffer), 0);
780
781 gate_strbuilder_to_string(&query_builder, &query_string);
782 ret = gate_mgmt_run_query(services, &query_string, callback, userparam);
783 gate_string_release(&query_string);
784 gate_strbuilder_release(&query_builder);
785 }
786 }
787
788 gate_string_release(&host);
789 gate_string_release(&name_space);
790 gate_string_release(&class_name);
791 gate_string_release(&instance_name);
792 }
793 gate_mgmt_unload_wmi_service(&services, &must_uninit);
794 }
795 GATE_DEBUG_TRACE_FAILED_RESULT(ret);
796 return ret;
797 }
798 gate_result_t gate_management_list_properties(gate_management_t handle, gate_string_t const* path, gate_map_t* properties)
799 {
800 gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED;
801 gate_management_impl_t* impl = (gate_management_impl_t*)handle;
802
803 GATE_DEBUG_TRACE_FAILED_RESULT(ret);
804 return ret;
805 }
806 gate_result_t gate_management_list_methodnames(gate_management_t handle, gate_string_t const* path, gate_array_t* methodnames)
807 {
808 gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED;
809 gate_management_impl_t* impl = (gate_management_impl_t*)handle;
810
811 GATE_DEBUG_TRACE_FAILED_RESULT(ret);
812 return ret;
813 }
814 gate_result_t gate_management_get_property(gate_management_t handle, gate_string_t const* path, gate_string_t const* propname, gate_value_t* value)
815 {
816 gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED;
817 gate_management_impl_t* impl = (gate_management_impl_t*)handle;
818
819 GATE_DEBUG_TRACE_FAILED_RESULT(ret);
820 return ret;
821 }
822 gate_result_t gate_management_set_property(gate_management_t handle, gate_string_t const* path, gate_string_t const* propname, gate_value_t const* value)
823 {
824 gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED;
825 gate_management_impl_t* impl = (gate_management_impl_t*)handle;
826
827 GATE_DEBUG_TRACE_FAILED_RESULT(ret);
828 return ret;
829 }
830
831 #define BREAK_IF_HRESULT_FAILED(hresultvar, retvar) if (FAILED(hresultvar)) { \
832 retvar = GATE_RESULT_FAILED; \
833 break; \
834 }
835
836 static gate_result_t setup_argument_values(IWbemClassObject* arg_defs, gate_map_t const* src_value_map, IWbemClassObject* dst_wmi_args)
837 {
838 gate_result_t ret = GATE_RESULT_OK;
839 HRESULT hr;
840
841 do
842 {
843 BSTR bstr_arg_name = NULL;
844 VARIANT variant_value = GATE_INIT_EMPTY;
845 CIMTYPE cim_type = 0;
846
847 hr = arg_defs->lpVtbl->BeginEnumeration(arg_defs, WBEM_FLAG_LOCAL_ONLY);
848 BREAK_IF_HRESULT_FAILED(hr, ret);
849
850 while (WBEM_S_NO_ERROR == (hr = arg_defs->lpVtbl->Next(arg_defs, 0, &bstr_arg_name, &variant_value, &cim_type, NULL)))
851 {
852 gate_string_t str_arg_name = GATE_STRING_INIT_EMPTY;
853 if (NULL != gate_win32_bstr_to_string(bstr_arg_name, &str_arg_name))
854 {
855 /* lookup parameter in input map (string->value) */
856 gate_value_t const* ptr_value = (gate_value_t const*)gate_map_get_value(src_value_map, &str_arg_name);
857 if (ptr_value)
858 {
859 do
860 {
861 /* we have a value, convert it to VARIANT */
862 VARIANT var_value = GATE_INIT_EMPTY;
863 ret = gate_win32_value_to_variant(ptr_value, &var_value);
864 GATE_BREAK_IF_FAILED(ret);
865
866 /* apply the variant on in-args object */
867 hr = dst_wmi_args->lpVtbl->Put(dst_wmi_args, bstr_arg_name, 0, &var_value, 0);
868 gate_win32_variant_clear(&var_value);
869 BREAK_IF_HRESULT_FAILED(hr, ret);
870 } while (0);
871 }
872 }
873 gate_string_release(&str_arg_name);
874 gate_win32_bstr_release(bstr_arg_name);
875 gate_win32_variant_clear(&variant_value);
876 GATE_BREAK_IF_FAILED(ret);
877 }
878 arg_defs->lpVtbl->EndEnumeration(arg_defs);
879 } while (0);
880 return ret;
881 }
882
883 static gate_result_t extract_argument_values(IWbemClassObject* wmi_args, gate_map_t* dst_value_map)
884 {
885 gate_result_t ret = GATE_RESULT_FAILED;
886 BSTR bstr_name = NULL;
887 VARIANT variant_value = GATE_INIT_EMPTY;
888 CIMTYPE cim_type = 0;
889 HRESULT hr;
890
891 do
892 {
893 hr = wmi_args->lpVtbl->BeginEnumeration(wmi_args, WBEM_FLAG_LOCAL_ONLY);
894 BREAK_IF_HRESULT_FAILED(hr, ret);
895
896 gate_map_destroy(dst_value_map);
897 if (NULL == gate_util_stringvaluemap_create(dst_value_map))
898 {
899 ret = GATE_RESULT_OUTOFMEMORY;
900 break;
901 }
902
903 while (WBEM_S_NO_ERROR == (hr = wmi_args->lpVtbl->Next(wmi_args, 0, &bstr_name, &variant_value, &cim_type, NULL)))
904 {
905 gate_value_t val = GATE_INIT_EMPTY;
906 if (NULL != gate_win32_variant_to_value(&variant_value, &val))
907 {
908 gate_string_t str_name;
909 if (NULL != gate_win32_bstr_to_string(bstr_name, &str_name))
910 {
911 gate_map_add(dst_value_map, &str_name, &val);
912 gate_string_release(&str_name);
913 }
914 gate_value_release(&val);
915 }
916 gate_win32_bstr_release(bstr_name);
917 gate_win32_variant_clear(&variant_value);
918 }
919 wmi_args->lpVtbl->EndEnumeration(wmi_args);
920 } while (0);
921
922 return ret;
923 }
924
925 gate_result_t gate_management_invoke(gate_management_t handle,
926 gate_string_t const* path, gate_string_t const* methodname,
927 gate_map_t const* input_values, gate_map_t* output_values)
928 {
929 gate_result_t ret = GATE_RESULT_FAILED;
930 gate_management_impl_t* impl = (gate_management_impl_t*)handle;
931 gate_string_t wmi_host = GATE_STRING_INIT_EMPTY;
932 gate_string_t wmi_namespace = GATE_STRING_INIT_EMPTY;
933 gate_string_t wmi_class_name = GATE_STRING_INIT_EMPTY;
934 gate_string_t wmi_instance = GATE_STRING_INIT_EMPTY;
935 IWbemServices* wmi_services = NULL;
936 IWbemClassObject* wmi_class = NULL;
937 IWbemClassObject* wmi_inparamdefs = NULL;
938 IWbemClassObject* wmi_outparamdefs = NULL;
939 IWbemClassObject* wmi_inargs = NULL;
940 IWbemClassObject* wmi_outargs = NULL;
941 gate_bool_t must_uninit = false;
942
943 BSTR bstr_class = NULL;
944 BSTR bstr_method = NULL;
945 BSTR bstr_path = NULL;
946 HRESULT hr;
947
948 do
949 {
950 ret = gate_mgmt_parse_path(path, &wmi_host, &wmi_namespace, &wmi_class_name, &wmi_instance);
951 GATE_BREAK_IF_FAILED(ret);
952
953 ret = gate_mgmt_load_wmi_service(&wmi_host, &wmi_namespace, NULL, NULL, &wmi_services, &must_uninit);
954 GATE_BREAK_IF_FAILED(ret);
955
956 bstr_class = gate_win32_bstr_create(&wmi_class_name);
957 bstr_method = gate_win32_bstr_create(methodname);
958 bstr_path = gate_win32_bstr_create(path);
959
960 /* get wmi object class */
961 hr = wmi_services->lpVtbl->GetObject(wmi_services, bstr_class, WBEM_FLAG_RETURN_WBEM_COMPLETE, NULL, &wmi_class, NULL);
962 BREAK_IF_HRESULT_FAILED(hr, ret);
963
964 /* get wmi object method parameters */
965 hr = wmi_class->lpVtbl->GetMethod(wmi_class, bstr_method, WBEM_FLAG_RETURN_WBEM_COMPLETE, &wmi_inparamdefs, &wmi_outparamdefs);
966 BREAK_IF_HRESULT_FAILED(hr, ret);
967
968 if ((wmi_inparamdefs != NULL) && (input_values != NULL))
969 {
970 /* set input parameters (from gate [name->value] map to wmi object) */
971 hr = wmi_inparamdefs->lpVtbl->SpawnInstance(wmi_inparamdefs, 0, &wmi_inargs);
972 BREAK_IF_HRESULT_FAILED(hr, ret);
973
974 ret = setup_argument_values(wmi_inparamdefs, input_values, wmi_inargs);
975 GATE_BREAK_IF_FAILED(ret);
976 }
977
978 /* execute WMI method */
979 hr = wmi_services->lpVtbl->ExecMethod(wmi_services, bstr_path, bstr_method, 0, NULL, wmi_inargs, &wmi_outargs, NULL);
980 BREAK_IF_HRESULT_FAILED(hr, ret);
981
982 if ((wmi_outargs != NULL) && (output_values != NULL))
983 {
984 extract_argument_values(wmi_outargs, output_values);
985 }
986 } while (0);
987
988 GATE_COM_RELEASE(wmi_outargs);
989 GATE_COM_RELEASE(wmi_inargs);
990 GATE_COM_RELEASE(wmi_outparamdefs);
991 GATE_COM_RELEASE(wmi_inparamdefs);
992 GATE_COM_RELEASE(wmi_class);
993
994 gate_win32_bstr_release(bstr_class);
995 gate_win32_bstr_release(bstr_method);
996 gate_win32_bstr_release(bstr_path);
997
998 gate_string_release(&wmi_host);
999 gate_string_release(&wmi_namespace);
1000 gate_string_release(&wmi_class_name);
1001 gate_string_release(&wmi_instance);
1002
1003 gate_mgmt_unload_wmi_service(&wmi_services, &must_uninit);
1004
1005 GATE_DEBUG_TRACE_FAILED_RESULT(ret);
1006 return ret;
1007 }
1008
1009 #endif /* GATE_SYSTEM_MANAGEMENT_WINAPI_IMPL */
1010
1011
1012
1013
1014 #if defined(GATE_SYSTEM_MANAGEMENT_NO_IMPL)
1015
1016 gate_result_t gate_management_list_subsystems(gate_string_t const* host, gate_array_t* subsystems)
1017 {
1018 GATE_UNUSED_ARG(host);
1019 GATE_UNUSED_ARG(subsystems);
1020 return GATE_RESULT_NOTIMPLEMENTED;
1021 }
1022
1023 gate_result_t gate_management_open(gate_string_t const* host, gate_string_t const* subsystem,
1024 gate_string_t const* name_space, gate_enumint_t flags, gate_management_t* handle)
1025 {
1026 GATE_UNUSED_ARG(host);
1027 GATE_UNUSED_ARG(subsystem);
1028 GATE_UNUSED_ARG(name_space);
1029 GATE_UNUSED_ARG(flags);
1030 GATE_UNUSED_ARG(handle);
1031 return GATE_RESULT_NOTIMPLEMENTED;
1032 }
1033
1034 gate_result_t gate_management_close(gate_management_t handle)
1035 {
1036 GATE_UNUSED_ARG(handle);
1037 return GATE_RESULT_NOTIMPLEMENTED;
1038 }
1039
1040 gate_result_t gate_management_get_object(gate_management_t handle, gate_string_t const* path,
1041 gate_management_object_t* obj)
1042 {
1043 GATE_UNUSED_ARG(handle);
1044 GATE_UNUSED_ARG(path);
1045 GATE_UNUSED_ARG(obj);
1046 return GATE_RESULT_NOTIMPLEMENTED;
1047 }
1048
1049 gate_result_t gate_management_query(gate_management_t handle, gate_string_t const* path,
1050 gate_string_t const* query, gate_management_callback_t callback, void* userparam)
1051 {
1052 GATE_UNUSED_ARG(handle);
1053 GATE_UNUSED_ARG(path);
1054 GATE_UNUSED_ARG(query);
1055 GATE_UNUSED_ARG(callback);
1056 GATE_UNUSED_ARG(userparam);
1057 return GATE_RESULT_NOTIMPLEMENTED;
1058 }
1059
1060 gate_result_t gate_management_list_children(gate_management_t handle, gate_string_t const* path,
1061 gate_management_callback_t callback, void* userparam)
1062 {
1063 GATE_UNUSED_ARG(handle);
1064 GATE_UNUSED_ARG(path);
1065 GATE_UNUSED_ARG(callback);
1066 GATE_UNUSED_ARG(userparam);
1067 return GATE_RESULT_NOTIMPLEMENTED;
1068 }
1069
1070 gate_result_t gate_management_list_properties(gate_management_t handle, gate_string_t const* path, gate_map_t* properties)
1071 {
1072 GATE_UNUSED_ARG(handle);
1073 GATE_UNUSED_ARG(path);
1074 GATE_UNUSED_ARG(properties);
1075 return GATE_RESULT_NOTIMPLEMENTED;
1076 }
1077
1078 gate_result_t gate_management_list_methodnames(gate_management_t handle, gate_string_t const* path, gate_array_t* methodnames)
1079 {
1080 GATE_UNUSED_ARG(handle);
1081 GATE_UNUSED_ARG(path);
1082 GATE_UNUSED_ARG(methodnames);
1083 return GATE_RESULT_NOTIMPLEMENTED;
1084 }
1085
1086 gate_result_t gate_management_get_property(gate_management_t handle, gate_string_t const* path,
1087 gate_string_t const* propname, gate_value_t* value)
1088 {
1089 GATE_UNUSED_ARG(handle);
1090 GATE_UNUSED_ARG(path);
1091 GATE_UNUSED_ARG(propname);
1092 GATE_UNUSED_ARG(value);
1093 return GATE_RESULT_NOTIMPLEMENTED;
1094 }
1095
1096 gate_result_t gate_management_set_property(gate_management_t handle, gate_string_t const* path,
1097 gate_string_t const* propname, gate_value_t const* value)
1098 {
1099 GATE_UNUSED_ARG(handle);
1100 GATE_UNUSED_ARG(path);
1101 GATE_UNUSED_ARG(propname);
1102 GATE_UNUSED_ARG(value);
1103 return GATE_RESULT_NOTIMPLEMENTED;
1104 }
1105
1106 gate_result_t gate_management_invoke(gate_management_t handle,
1107 gate_string_t const* path, gate_string_t const* methodname,
1108 gate_map_t const* input_values, gate_map_t* output_values)
1109 {
1110 GATE_UNUSED_ARG(handle);
1111 GATE_UNUSED_ARG(path);
1112 GATE_UNUSED_ARG(methodname);
1113 GATE_UNUSED_ARG(input_values);
1114 GATE_UNUSED_ARG(output_values);
1115 return GATE_RESULT_NOTIMPLEMENTED;
1116 }
1117
1118 #endif /* GATE_SYSTEM_MANAGEMENT_NO_IMPL */
1119