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 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
|
/*
* os_win32/wmiquery.cpp
*
* Home page of code is: http://www.smartmontools.org
*
* Copyright (C) 2011-13 Christian Franke <smartmontools-support@lists.sourceforge.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "config.h"
#define WINVER 0x0400
#define _WIN32_WINNT WINVER
#include "wmiquery.h"
#include <stdio.h>
const char * wmiquery_cpp_cvsid = "$Id: wmiquery.cpp 4120 2015-08-27 16:12:21Z samm2 $"
WMIQUERY_H_CVSID;
/////////////////////////////////////////////////////////////////////////////
// com_bstr
com_bstr::com_bstr(const char * str)
: m_bstr(0)
{
int sz = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, str, -1, (LPWSTR)0, 0);
if (sz <= 0)
return;
m_bstr = SysAllocStringLen((OLECHAR*)0, sz-1);
if (!m_bstr)
return; // throw std::bad_alloc
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, str, -1, m_bstr, sz);
}
bool com_bstr::to_str(const BSTR & bstr, std::string & str)
{
if (!bstr)
return false;
int sz = WideCharToMultiByte(CP_ACP, 0, bstr, -1, (LPSTR)0, 0, (LPCSTR)0, (LPBOOL)0);
if (sz <= 0)
return false;
char * buf = new char[sz];
WideCharToMultiByte(CP_ACP, 0, bstr, -1, buf, sz, (LPCSTR)0, (LPBOOL)0);
str = buf;
delete [] buf;
return true;
}
/////////////////////////////////////////////////////////////////////////////
// wbem_object
std::string wbem_object::get_str(const char * name) /*const*/
{
std::string s;
if (!m_intf)
return s;
VARIANT var; VariantInit(&var);
if (m_intf->Get(com_bstr(name), 0L, &var, (CIMTYPE*)0, (LPLONG)0) /* != WBEM_S_NO_ERROR */)
return s;
if (var.vt == VT_BSTR)
com_bstr::to_str(var.bstrVal, s);
VariantClear(&var);
return s;
}
/////////////////////////////////////////////////////////////////////////////
// wbem_enumerator
bool wbem_enumerator::next(wbem_object & obj)
{
if (!m_intf)
return false;
ULONG n = 0;
HRESULT rc = m_intf->Next(5000 /*5s*/, 1 /*count*/, obj.m_intf.replace(), &n);
if (FAILED(rc) || n != 1)
return false;
return true;
}
/////////////////////////////////////////////////////////////////////////////
// wbem_services
const CLSID xCLSID_WbemLocator = {0x4590f811, 0x1d3a, 0x11d0, {0x89, 0x1f, 0x00, 0xaa, 0x00, 0x4b, 0x2e, 0x24}};
const IID xIID_IWbemLocator = {0xdc12a687, 0x737f, 0x11cf, {0x88, 0x4d, 0x00, 0xaa, 0x00, 0x4b, 0x2e, 0x24}};
bool wbem_services::connect()
{
// Init COM during first call.
static HRESULT init_rc = -1;
static bool init_tried = false;
if (!init_tried) {
init_tried = true;
init_rc = CoInitialize((LPVOID)0);
}
if (!(init_rc == S_OK || init_rc == S_FALSE))
return false;
/// Create locator.
com_intf_ptr<IWbemLocator> locator;
HRESULT rc = CoCreateInstance(xCLSID_WbemLocator, (LPUNKNOWN)0,
CLSCTX_INPROC_SERVER, xIID_IWbemLocator, (LPVOID*)locator.replace());
if (FAILED(rc))
return false;
// Set timeout flag if supported.
long flags = 0;
OSVERSIONINFOA ver; ver.dwOSVersionInfoSize = sizeof(ver);
if (GetVersionExA(&ver) && ver.dwPlatformId == VER_PLATFORM_WIN32_NT
&& ( ver.dwMajorVersion >= 6 // Vista
|| (ver.dwMajorVersion == 5 && ver.dwMinorVersion >= 1))) // XP
flags = WBEM_FLAG_CONNECT_USE_MAX_WAIT; // return in 2min or less
// Connect to local server.
rc = locator->ConnectServer(com_bstr("\\\\.\\root\\cimv2"),
(BSTR)0, (BSTR)0, (BSTR)0, // User, Password, Locale
flags, (BSTR)0, (IWbemContext*)0, m_intf.replace());
if (FAILED(rc))
return false;
// Set authentication information,
rc = CoSetProxyBlanket(m_intf.get(), RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE,
(OLECHAR*)0, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE,
(RPC_AUTH_IDENTITY_HANDLE*)0, EOAC_NONE);
if (FAILED(rc)) {
m_intf.reset();
return false;
}
return true;
}
bool wbem_services::vquery(wbem_enumerator & result, const char * qstr, va_list args) /*const*/
{
if (!m_intf)
return false;
char qline[1024];
vsnprintf(qline, sizeof(qline), qstr, args);
qline[sizeof(qline)-1] = 0;
HRESULT rc = m_intf->ExecQuery(
com_bstr("WQL"), com_bstr(qline),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
(IWbemContext*)0, result.m_intf.replace());
if (FAILED(rc))
return false;
return true;
}
bool wbem_services::vquery1(wbem_object & obj, const char * qstr, va_list args) /*const*/
{
wbem_enumerator result;
if (!vquery(result, qstr, args))
return false;
if (!result.next(obj))
return false;
wbem_object peek;
if (result.next(peek))
return false;
return true;
}
bool wbem_services::query(wbem_enumerator & result, const char * qstr, ...) /*const*/
{
va_list args; va_start(args, qstr);
bool ok = vquery(result, qstr, args);
va_end(args);
return ok;
}
bool wbem_services::query1(wbem_object & obj, const char * qstr, ...) /*const*/
{
va_list args; va_start(args, qstr);
bool ok = vquery1(obj, qstr, args);
va_end(args);
return ok;
}
|