Confdump Agent
1.4.0
|
00001 /* 00002 * Confdump-Agent - Dump static and runtime system configuration 00003 * Copyright (C) 2009-2012 Straton IT, SAS 00004 * 00005 * This program is free software: you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 3 as 00007 * published by the Free Software Foundation. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00016 */ 00017 00018 #include <comdef.h> 00019 #include <wbemidl.h> 00020 00021 #include "QStringList" 00022 00023 #include "Confdump/System/Wmi/WbemServices.hpp" 00024 #include "Confdump/System/Wmi/errors.hpp" 00025 #include "Confdump/System/Wmi/NoSuchNamespace.hpp" 00026 #include "Confdump/System/Wmi/NoSuchClass.hpp" 00027 00028 using boost::shared_ptr; 00029 00030 00031 namespace Confdump 00032 { 00033 namespace System 00034 { 00035 namespace Wmi 00036 { 00037 00038 WbemQueryIterator::WbemQueryIterator() 00039 { 00040 } 00041 00042 WbemQueryIterator::WbemQueryIterator( boost::shared_ptr<IEnumWbemClassObject> enumerator ) 00043 : enumerator_( enumerator ) 00044 { 00045 increment(); // get the first element 00046 } 00047 00048 WbemQueryIterator::~WbemQueryIterator() 00049 { 00050 } 00051 00052 bool WbemQueryIterator::equal(const WbemQueryIterator &other) const 00053 { 00054 return element_ == other.element_; 00055 } 00056 00057 void WbemQueryIterator::increment() 00058 { 00059 IWbemClassObject *object = 0; 00060 ULONG count = 0; 00061 HRESULT hr = enumerator_->Next( WBEM_INFINITE, 1, &object, &count ); 00062 throwOnWmiError( hr, "access the next WMI object" ); 00063 00064 if ( count ) 00065 { 00066 element_ = guardComObject( object ); 00067 } 00068 else // we're one-past-the-end 00069 { 00070 element_.reset(); 00071 enumerator_.reset(); 00072 } 00073 } 00074 00075 00076 00077 00078 00079 WbemServices::WbemServices( ComContext::Guard guard ) 00080 : comGuard_( guard ), wmiNamespace_( "root\\cimv2" ) 00081 { 00082 assert( guard ); 00083 } 00084 00085 WbemServices::~WbemServices() 00086 { 00087 } 00088 00089 namespace 00090 { 00091 00092 shared_ptr<IWbemLocator> createLocator() 00093 { 00094 IWbemLocator *locator = 0; 00095 HRESULT hr = CoCreateInstance( 00096 CLSID_WbemLocator, 00097 0, 00098 CLSCTX_INPROC_SERVER, 00099 IID_IWbemLocator, 00100 reinterpret_cast<void**>( &locator ) ); 00101 throwOnComError( hr, "obtain the Wbem locator" ); 00102 return guardComObject( locator ); 00103 } 00104 00105 shared_ptr<IWbemServices> servicesFromLocator( shared_ptr<IWbemLocator> locator, QString wmiNamespace ) 00106 { 00107 IWbemServices *services = 0; 00108 HRESULT hr = locator->ConnectServer( 00109 _bstr_t( wmiNamespace.toStdWString().c_str() ), 00110 0, /* User name */ 00111 0, /* User password */ 00112 0, /* Locale */ 00113 0, /* Security flags */ 00114 _bstr_t( L"" ), /* Authority */ 00115 0, /* Context object */ 00116 &services ); /* IWbemServices proxy */ 00117 00118 try { 00119 throwOnWmiError( hr, "connect to namespace "+wmiNamespace+" on the local computer" ); 00120 } 00121 catch ( Win32Error &e ) 00122 { 00123 if ( e.hresult() == NoSuchNamespace::hresult() ) 00124 throw NoSuchNamespace( wmiNamespace ); 00125 else 00126 throw; 00127 } 00128 00129 return guardComObject( services ); 00130 } 00131 00132 } 00133 00134 void WbemServices::connect() 00135 { 00136 shared_ptr<IWbemLocator> locator = createLocator(); 00137 services_ = servicesFromLocator( locator, wmiNamespace_ ); 00138 } 00139 00140 void WbemServices::setWmiNamespace( QString ns ) 00141 { 00142 if ( wmiLists_.isNamespaceAllowed( ns ) ) 00143 wmiNamespace_ = ns; 00144 else 00145 throw NoSuchThing( "Confdump will not query this namespace: " + ns ); 00146 } 00147 00148 boost::iterator_range<WbemQueryIterator> WbemServices::execQuery( const Query &query ) 00149 { 00150 assert( services_ ); 00151 00152 QString className = QString::fromLocal8Bit( query.getClass().c_str() ); 00153 if ( !wmiLists_.isTableAllowed( wmiNamespace_, className ) ) 00154 throw NoSuchThing( QString( "Confdump will not query this table: %1.%2" ) 00155 .arg( wmiNamespace_ ).arg( className ) ); 00156 00157 _bstr_t language( "WQL" ); 00158 _bstr_t query_string( query.getQuery().c_str() ); 00159 IEnumWbemClassObject *rawEnumerator = 0; 00160 00161 HRESULT hr = services_->ExecQuery( language, query_string, 00162 WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 00163 0, &rawEnumerator ); 00164 throwOnWmiError( hr, QString::fromStdString( "run the WMI query " + query.getQuery() ) ); 00165 00166 shared_ptr<IEnumWbemClassObject> enumerator = guardComObject( rawEnumerator ); 00167 00168 try { 00169 return boost::iterator_range<WbemQueryIterator>( WbemQueryIterator( enumerator ), WbemQueryIterator() ); 00170 } 00171 catch ( WmiError &e ) 00172 { 00173 if ( e.hresult() == NoSuchClass::hresult() ) 00174 throw NoSuchClass( QString::fromStdString( query.getClass() ) ); 00175 else 00176 throw; 00177 } 00178 } 00179 00180 boost::iterator_range<WbemQueryIterator> WbemServices::listAllClasses() 00181 { 00182 assert( services_ ); 00183 00184 IEnumWbemClassObject *rawEnumerator = 0; 00185 00186 HRESULT hr = services_->CreateClassEnum( 0, 00187 WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_DEEP, 00188 0, &rawEnumerator ); 00189 throwOnWmiError( hr, QString::fromStdString( "enumerate the WMI classes" ) ); 00190 shared_ptr<IEnumWbemClassObject> enumerator = guardComObject( rawEnumerator ); 00191 00192 return boost::iterator_range<WbemQueryIterator>( WbemQueryIterator( enumerator ), WbemQueryIterator() ); 00193 } 00194 00195 } 00196 } 00197 }