2 * os_win32/wmiquery.cpp
4 * Home page of code is: http://www.smartmontools.org
6 * Copyright (C) 2011-13 Christian Franke
8 * SPDX-License-Identifier: GPL-2.0-or-later
13 #define _WIN32_WINNT WINVER
19 const char * wmiquery_cpp_cvsid
= "$Id: wmiquery.cpp 4760 2018-08-19 18:45:53Z chrfranke $"
23 /////////////////////////////////////////////////////////////////////////////
26 com_bstr::com_bstr(const char * str
)
29 int sz
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, str
, -1, (LPWSTR
)0, 0);
32 m_bstr
= SysAllocStringLen((OLECHAR
*)0, sz
-1);
34 return; // throw std::bad_alloc
35 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, str
, -1, m_bstr
, sz
);
38 bool com_bstr::to_str(const BSTR
& bstr
, std::string
& str
)
42 int sz
= WideCharToMultiByte(CP_ACP
, 0, bstr
, -1, (LPSTR
)0, 0, (LPCSTR
)0, (LPBOOL
)0);
45 char * buf
= new char[sz
];
46 WideCharToMultiByte(CP_ACP
, 0, bstr
, -1, buf
, sz
, (LPCSTR
)0, (LPBOOL
)0);
53 /////////////////////////////////////////////////////////////////////////////
56 std::string
wbem_object::get_str(const char * name
) /*const*/
62 VARIANT var
; VariantInit(&var
);
63 if (m_intf
->Get(com_bstr(name
), 0L, &var
, (CIMTYPE
*)0, (LPLONG
)0) /* != WBEM_S_NO_ERROR */)
66 if (var
.vt
== VT_BSTR
)
67 com_bstr::to_str(var
.bstrVal
, s
);
73 /////////////////////////////////////////////////////////////////////////////
76 bool wbem_enumerator::next(wbem_object
& obj
)
82 HRESULT rc
= m_intf
->Next(5000 /*5s*/, 1 /*count*/, obj
.m_intf
.replace(), &n
);
83 if (FAILED(rc
) || n
!= 1)
89 /////////////////////////////////////////////////////////////////////////////
92 const CLSID xCLSID_WbemLocator
= {0x4590f811, 0x1d3a, 0x11d0, {0x89, 0x1f, 0x00, 0xaa, 0x00, 0x4b, 0x2e, 0x24}};
93 const IID xIID_IWbemLocator
= {0xdc12a687, 0x737f, 0x11cf, {0x88, 0x4d, 0x00, 0xaa, 0x00, 0x4b, 0x2e, 0x24}};
95 bool wbem_services::connect()
97 // Init COM during first call.
98 static HRESULT init_rc
= -1;
99 static bool init_tried
= false;
102 init_rc
= CoInitialize((LPVOID
)0);
104 if (!(init_rc
== S_OK
|| init_rc
== S_FALSE
))
108 com_intf_ptr
<IWbemLocator
> locator
;
109 HRESULT rc
= CoCreateInstance(xCLSID_WbemLocator
, (LPUNKNOWN
)0,
110 CLSCTX_INPROC_SERVER
, xIID_IWbemLocator
, (LPVOID
*)locator
.replace());
114 // Set timeout flag if supported.
116 OSVERSIONINFOA ver
; ver
.dwOSVersionInfoSize
= sizeof(ver
);
117 if (GetVersionExA(&ver
) && ver
.dwPlatformId
== VER_PLATFORM_WIN32_NT
118 && ( ver
.dwMajorVersion
>= 6 // Vista
119 || (ver
.dwMajorVersion
== 5 && ver
.dwMinorVersion
>= 1))) // XP
120 flags
= WBEM_FLAG_CONNECT_USE_MAX_WAIT
; // return in 2min or less
122 // Connect to local server.
123 rc
= locator
->ConnectServer(com_bstr("\\\\.\\root\\cimv2"),
124 (BSTR
)0, (BSTR
)0, (BSTR
)0, // User, Password, Locale
125 flags
, (BSTR
)0, (IWbemContext
*)0, m_intf
.replace());
129 // Set authentication information,
130 rc
= CoSetProxyBlanket(m_intf
.get(), RPC_C_AUTHN_WINNT
, RPC_C_AUTHZ_NONE
,
131 (OLECHAR
*)0, RPC_C_AUTHN_LEVEL_CALL
, RPC_C_IMP_LEVEL_IMPERSONATE
,
132 (RPC_AUTH_IDENTITY_HANDLE
*)0, EOAC_NONE
);
141 bool wbem_services::vquery(wbem_enumerator
& result
, const char * qstr
, va_list args
) /*const*/
147 vsnprintf(qline
, sizeof(qline
), qstr
, args
);
148 qline
[sizeof(qline
)-1] = 0;
150 HRESULT rc
= m_intf
->ExecQuery(
151 com_bstr("WQL"), com_bstr(qline
),
152 WBEM_FLAG_FORWARD_ONLY
| WBEM_FLAG_RETURN_IMMEDIATELY
,
153 (IWbemContext
*)0, result
.m_intf
.replace());
160 bool wbem_services::vquery1(wbem_object
& obj
, const char * qstr
, va_list args
) /*const*/
162 wbem_enumerator result
;
163 if (!vquery(result
, qstr
, args
))
166 if (!result
.next(obj
))
170 if (result
.next(peek
))
176 bool wbem_services::query(wbem_enumerator
& result
, const char * qstr
, ...) /*const*/
178 va_list args
; va_start(args
, qstr
);
179 bool ok
= vquery(result
, qstr
, args
);
184 bool wbem_services::query1(wbem_object
& obj
, const char * qstr
, ...) /*const*/
186 va_list args
; va_start(args
, qstr
);
187 bool ok
= vquery1(obj
, qstr
, args
);