Confdump Agent  1.4.0
WbemServices.cpp
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends