-
Notifications
You must be signed in to change notification settings - Fork 0
/
wmi.cpp
142 lines (119 loc) · 3.14 KB
/
wmi.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#include "wmi.h"
#include "log.h"
#include <windows.h>
#pragma comment(lib, "wbemuuid.lib")
bool WMIWrapper::is_init = false;
void WMIWrapper::initialize() {
HRESULT hr = S_OK;
if (is_init)
return;
hr = ::CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hr) && hr != S_FALSE && hr != RPC_E_CHANGED_MODE) {
Log::print_error_hr(L"Cannot initialize COM", hr);
return;
}
hr = ::CoInitializeSecurity(
NULL, // Security descriptor
-1, // COM negotiates authentication service
NULL, // Authentication services
NULL, // Reserved
RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication level for proxies
RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation level for proxies
NULL, // Authentication info
EOAC_NONE, // Additional capabilities of the client or server
NULL); // Reserved
if (FAILED(hr) && hr != RPC_E_TOO_LATE) {
Log::print_error_hr(L"Cannot set COM security process-wide", hr);
return;
}
is_init = true;
}
void WMIWrapper::finalize() {
if (is_init) {
CoUninitialize();
is_init = false;
}
}
WMIWrapper::WMIWrapper() {
if (!is_init)
initialize();
}
bool WMIWrapper::ExecQuery(const std::wstring& query) {
HRESULT hr = S_OK;
hr = ::CoCreateInstance(
CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator,
(LPVOID*) &locator);
if (FAILED(hr)) {
Log::print_error_hr(L"Cannot create WbemLocator COM object (WMI)", hr);
return false;
}
hr = locator->ConnectServer(
L"ROOT\\CIMV2",
NULL, NULL, 0,
NULL, 0, 0,
&server);
if (FAILED(hr)) {
Log::print_error_hr(L"Cannot connect to WbemLocator server (WMI)", hr);
return false;
}
hr = ::CoSetProxyBlanket(
server,
RPC_C_AUTHN_WINNT,
RPC_C_AUTHZ_NONE,
NULL,
RPC_C_AUTHN_LEVEL_CALL,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
EOAC_NONE);
if (FAILED(hr)) {
Log::print_error_hr(L"Cannot set WbemLocator proxy blanket (WMI)", hr);
return false;
}
hr = server->ExecQuery(
bstr_t(L"WQL"),
bstr_t(query.c_str()),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&enumerator);
if (FAILED(hr)) {
Log::print_error_hr(L"Cannot execute WMI query", hr);
return false;
}
query_done = true;
ULONG ul_ret = 0;
hr = enumerator->Next(WBEM_INFINITE, 1, &obj, &ul_ret);
if (FAILED(hr)) {
Log::print(L"Query is empty");
query_empty = true;
return true;
}
query_empty = false;
return true;
}
bool WMIWrapper::GetTextProperty(const std::wstring& property, std::string& result) {
HRESULT hr = S_OK;
variant_t variant;
if (!query_done) {
#ifdef _DEBUG
throw std::runtime_error("WIMWrapper::GetTextProperty() called with no query ready");
#else
result = "1111111";
return false;
#endif
}
if (query_empty) {
result = "1000001";
return true;
}
hr = obj->Get(property.c_str(), 0, &variant, 0, 0);
if (FAILED(hr)) {
result = "1111111";
return false;
}
_bstr_t bstr(variant.bstrVal);
result = (LPCSTR) bstr;
return true;
}