/*
wmi.cpp
Copyright 2006 John Poole.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "wmi.h"
#define _WIN32_DCOM
#include <windows.h>
#include <comdef.h>
#include <wbemidl.h>
#include <sstream>
#include <iostream>
static IWbemServices * pSvc = NULL;
static IWbemLocator * pLoc = NULL;
static bool wmiInitialized = false;
static bool initializeWmi()
{
HRESULT result;
result = CoInitialize( NULL );
if( FAILED( result ) ) {
return false;
}
result = CoInitializeSecurity( NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL );
if( FAILED( result ) ) {
CoUninitialize();
return false;
}
result = CoCreateInstance( CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, ( LPVOID * )&pLoc );
if( FAILED( result ) ) {
CoUninitialize();
return false;
}
result = pLoc->ConnectServer( _bstr_t( L"ROOT\\CIMV2" ), NULL, NULL, 0, NULL, 0, 0, &pSvc );
if( FAILED( result ) ) {
CoUninitialize();
return false;
}
result = CoSetProxyBlanket( pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE );
if( FAILED( result ) ) {
CoUninitialize();
return false;
}
return true;
}
static std::string asciiEncode( const std::wstring & w )
{
std::ostringstream s;
char * c;
int r;
c = new char[ MB_CUR_MAX + 1 ];
for( size_t i = 0; i < w.length(); i++ ) {
r = wctomb( c, w[i] );
c[r] = '\0';
if( r <= 1 && c[0] > 0 ) {
s << c;
}
}
return s.str();
}
static std::wstring asciiDecode( const std::string & s )
{
std::wostringstream w;
wchar_t c;
for( size_t i = 0; i < s.length(); i++ ) {
mbtowc( &c, &s[i], 1 );
w << c;
}
return w.str();
}
static std::string trim( const std::string & s )
{
std::string::size_type p;
std::string::size_type q;
p = s.find_first_not_of( ' ' );
if( p == std::string::npos ) {
p = 0;
}
q = s.find_last_not_of( ' ' );
if( q == std::string::npos ) {
q = s.length() - 1;
}
return s.substr( p, q - p + 1 );
}
bool runWmiQuery( std::string query, std::map< std::string, uint64 > & wmiMap )
{
IEnumWbemClassObject * pEnumerator = NULL;
BSTR b;
IWbemClassObject * pclsObj = NULL;
HRESULT result;
VARIANT vtProp;
ULONG uReturn = 0;
if( !wmiInitialized ) {
wmiInitialized = initializeWmi();
if( !wmiInitialized ) {
return false;
}
}
b = _bstr_t( asciiDecode( query ).c_str() );
result = pSvc->ExecQuery( L"WQL", b, WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator );
if( FAILED( result ) ) {
return false;
}
while( pEnumerator ) {
result = pEnumerator->Next( WBEM_INFINITE, 1, &pclsObj, &uReturn );
if( !uReturn ) {
break;
}
VariantInit( &vtProp );
pclsObj->BeginEnumeration( WBEM_FLAG_NONSYSTEM_ONLY );
{
CIMTYPE pvtType;
VARIANT pVal;
BSTR pstrName;
while( pclsObj->Next( 0, &pstrName, &pVal, &pvtType, NULL ) == WBEM_S_NO_ERROR ) {
//std::wcout << pstrName << " " << pVal.vt << std::endl;
if( pVal.vt == VT_I4 ) {
wmiMap[ asciiEncode( pstrName ) ] = pVal.lVal;
//std::wcout << pstrName << ":" << pVal.bstrVal << std::endl;
}
SysFreeString( pstrName );
VariantClear( &pVal );
}
}
}
pEnumerator->Release();
if( pclsObj ) {
pclsObj->Release();
}
return true;
}
bool getWmiClass( const char * wmiClass, std::map< std::string, std::string > & wmiMap )
{
IEnumWbemClassObject * pEnumerator = NULL;
std::wostringstream query;
std::wstring q;
BSTR b;
IWbemClassObject * pclsObj = NULL;
HRESULT result;
VARIANT vtProp;
ULONG uReturn = 0;
if( !wmiInitialized ) {
wmiInitialized = initializeWmi();
if( !wmiInitialized ) {
return false;
}
}
query << "SELECT * FROM " << asciiDecode( wmiClass );
b = _bstr_t( query.str().c_str() );
result = pSvc->ExecQuery( L"WQL", b, WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator );
if( FAILED( result ) ) {
return false;
}
while( pEnumerator ) {
result = pEnumerator->Next( WBEM_INFINITE, 1, &pclsObj, &uReturn );
if( !uReturn ) {
break;
}
VariantInit( &vtProp );
pclsObj->BeginEnumeration( WBEM_FLAG_NONSYSTEM_ONLY );
{
CIMTYPE pvtType;
VARIANT pVal;
BSTR pstrName;
while( pclsObj->Next( 0, &pstrName, &pVal, &pvtType, NULL ) == WBEM_S_NO_ERROR ) {
//std::wcout << pstrName << " " << pVal.vt << std::endl;
if( pVal.vt == VT_BSTR ) {
wmiMap[ asciiEncode( pstrName ) ] = trim( asciiEncode( pVal.bstrVal ) );
//std::wcout << pstrName << ":" << pVal.bstrVal << std::endl;
}
SysFreeString( pstrName );
VariantClear( &pVal );
}
}
}
pEnumerator->Release();
if( pclsObj ) {
pclsObj->Release();
}
return true;
}
bool getWmiClass( const char * wmiClass, std::map< std::string, uint64 > & wmiMap )
{
IEnumWbemClassObject * pEnumerator = NULL;
std::wostringstream query;
std::wstring q;
BSTR b;
IWbemClassObject * pclsObj = NULL;
HRESULT result;
VARIANT vtProp;
ULONG uReturn = 0;
if( !wmiInitialized ) {
wmiInitialized = initializeWmi();
if( !wmiInitialized ) {
return false;
}
}
query << "SELECT * FROM " << asciiDecode( wmiClass );
b = _bstr_t( query.str().c_str() );
result = pSvc->ExecQuery( L"WQL", b, WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator );
if( FAILED( result ) ) {
return false;
}
while( pEnumerator ) {
result = pEnumerator->Next( WBEM_INFINITE, 1, &pclsObj, &uReturn );
if( !uReturn ) {
break;
}
VariantInit( &vtProp );
pclsObj->BeginEnumeration( WBEM_FLAG_NONSYSTEM_ONLY );
{
CIMTYPE pvtType;
VARIANT pVal;
BSTR pstrName;
while( pclsObj->Next( 0, &pstrName, &pVal, &pvtType, NULL ) == WBEM_S_NO_ERROR ) {
//std::wcout << pstrName << " " << pVal.vt << std::endl;
if( pVal.vt == VT_I4 ) {
wmiMap[ asciiEncode( pstrName ) ] = pVal.lVal;
//std::wcout << pstrName << ":" << pVal.bstrVal << std::endl;
}
SysFreeString( pstrName );
VariantClear( &pVal );
}
}
}
pEnumerator->Release();
if( pclsObj ) {
pclsObj->Release();
}
return true;
}