// Copyright (c) Microsoft. All rights reserved. // // This is unpublished source code of Microsoft. // The copyright notice above does not evidence any // actual or intended publication of such source code. // OneLiner : Implementation of MWmiObject // DevUnit : wlbstest // Author : Murtaza Hakim // include files #include "MWmiObject.h" #include "MWmiError.h" #include "mtrace.h" using namespace std; // constructor // MWmiObject::MWmiObject( const _bstr_t& ipAddr, const _bstr_t& nameSpace, const _bstr_t& loginName, const _bstr_t& passWord ) : _nameSpace( nameSpace ) { HRESULT hr; hr = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &pwl); if (FAILED(hr)) { TRACE( MTrace::SEVERE_ERROR, "CoCreateInstance failure\n"); throw _com_error( hr ); } // _bstr_t serverPath; serverPath = _bstr_t(L"\\\\") + ipAddr + _bstr_t(L"\\") + nameSpace; betterConnectServer( serverPath, loginName, passWord, 0, NULL, 0, 0, &pws ); // Set the proxy so that impersonation of the client occurs. // CoSetProxyBlanket(pws, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_DEFAULT, // RPC_C_AUTHZ_NAME, COLE_DEFAULT_PRINCIPAL, // NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, COLE_DEFAULT_AUTHINFO, // NULL, EOAC_DEFAULT // EOAC_NONE ); TRACE(MTrace::INFO, L"mwmiobject constructor\n" ); } // constructor // MWmiObject::MWmiObject( const _bstr_t& nameSpace ) : _nameSpace( nameSpace ) { HRESULT hr; // hr = CoCreateInstance(CLSID_WbemLocator, 0, hr = CoCreateInstance(CLSID_WbemUnauthenticatedLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &pwl); if (FAILED(hr)) { TRACE( MTrace::SEVERE_ERROR, "CoCreateInstance failure\n"); throw _com_error( hr ); } betterConnectServer( nameSpace, NULL, NULL, 0, NULL, 0, 0, &pws ); // Set the proxy so that impersonation of the client occurs. // CoSetProxyBlanket(pws, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NAME, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE ); TRACE(MTrace::INFO, L"mwmiobject constructor\n" ); } // copy constructor // MWmiObject::MWmiObject( const MWmiObject& obj ) : status( obj.status ), pwl( obj.pwl ), pws( obj.pws ), _nameSpace( obj._nameSpace ) { TRACE(MTrace::INFO, L"mwmiobject copy constructor\n" ); } // assignment operator // MWmiObject& MWmiObject::operator=(const MWmiObject& rhs ) { status = rhs.status; _nameSpace = rhs._nameSpace; pwl = rhs.pwl; pws = rhs.pws; TRACE(MTrace::INFO, L"mwmiobject assignment operator\n" ); return *this; } // destructor // MWmiObject::~MWmiObject() { TRACE(MTrace::INFO, L"mwmiobject destructor\n" ); } // getInstances // MWmiObject::MWmiObject_Error MWmiObject::getInstances( const _bstr_t& objectToGetInstancesOf, vector< MWmiInstance >* instanceStore ) { vector<_bstr_t> pathStore; // get paths to all instances. getPath( objectToGetInstancesOf, &pathStore ); // form instances for( int i = 0; i < pathStore.size(); ++i ) { instanceStore->push_back( MWmiInstance( objectToGetInstancesOf, pathStore[i], pwl, pws ) ); } return MWmiObject_SUCCESS; } // getSpecificInstance // MWmiObject::MWmiObject_Error MWmiObject::getSpecificInstance( const _bstr_t& objectToGetInstancesOf, const _bstr_t& relPath, vector< MWmiInstance >* instanceStore ) { vector<_bstr_t> pathStore; // get paths to all instances. getSpecificPath( objectToGetInstancesOf, relPath, &pathStore ); // form instances for( int i = 0; i < pathStore.size(); ++i ) { instanceStore->push_back( MWmiInstance( objectToGetInstancesOf, pathStore[i], pwl, pws ) ); } return MWmiObject_SUCCESS; } // getQueriedInstances // MWmiObject::MWmiObject_Error MWmiObject::getQueriedInstances( const _bstr_t& objectToGetInstancesOf, const _bstr_t& query, vector< MWmiInstance >* instanceStore ) { vector<_bstr_t> pathStore; // get paths to all instances. getQueriedPath( objectToGetInstancesOf, query, &pathStore ); // form instances for( int i = 0; i < pathStore.size(); ++i ) { instanceStore->push_back( MWmiInstance( objectToGetInstancesOf, pathStore[i], pwl, pws ) ); } return MWmiObject_SUCCESS; } // getPath // MWmiObject::MWmiObject_Error MWmiObject::getPath( const _bstr_t& objectToRunMethodOn, vector<_bstr_t> *pathStore ) { HRESULT hr; IEnumWbemClassObjectPtr pewco; IWbemClassObjectPtr pwco; _variant_t v_path; unsigned long count; // get instances of object // hr = pws->CreateInstanceEnum( objectToRunMethodOn, WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pewco ); if ( FAILED(hr)) { TRACE( MTrace::SEVERE_ERROR, "IWbemServices::CreateInstanceEnum failure\n" ); throw _com_error( hr ) ; } // there may be multiple instances. #if 1 // Set the proxy so that impersonation of the client occurs. // CoSetProxyBlanket(pewco, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NAME, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE ); count = 1; while ( (hr = pewco->Next( INFINITE, 1, &pwco, &count ) ) == S_OK ) { hr = pwco->Get( _bstr_t(L"__RELPATH"), 0, &v_path, NULL, NULL ); if( FAILED(hr) ) { TRACE( MTrace::SEVERE_ERROR, "IWbemClassObject::Get failure\n" ); throw _com_error( hr ); } pathStore->push_back( _bstr_t(v_path) ); count = 1; v_path.Clear(); } #endif #if 0 count = 1; hr = WBEM_S_NO_ERROR; while ( hr == WBEM_S_NO_ERROR ) { hr = pewco->Next( INFINITE, 1, &pwco, &count ); if( FAILED( hr ) ) { TRACE( MTrace::SEVERE_ERROR, "IWbemClassObject::Get failure\n" ); _bstr_t errText; GetErrorCodeText( hr, errText ); throw _com_error( hr ); } HRESULT hrGet; hrGet = pwco->Get( _bstr_t(L"__RELPATH"), 0, &v_path, NULL, NULL ); if( FAILED(hrGet ) ) { TRACE( MTrace::SEVERE_ERROR, "IWbemClassObject::Get failure\n" ); throw _com_error( hrGet ); } pathStore->push_back( _bstr_t(v_path) ); count = 1; v_path.Clear(); } #endif return MWmiObject_SUCCESS; } // getSpecificPath // MWmiObject::MWmiObject_Error MWmiObject::getSpecificPath( const _bstr_t& objectToRunMethodOn, const _bstr_t& relPath, vector<_bstr_t> *pathStore ) { HRESULT hr; IWbemClassObjectPtr pwcoInstance; IEnumWbemClassObjectPtr pewco; IWbemClassObjectPtr pwco; unsigned long count; _variant_t v_path; bool found; int i; _variant_t v_value; hr = pws->GetObject( relPath, 0, NULL, &pwcoInstance, NULL ); if( hr == 0x8004100c ) { // this is for setting class instances. // TRACE(MTrace::INFO, L"as this is not supported, trying different mechanism\n"); hr = pws->CreateInstanceEnum( objectToRunMethodOn, WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pewco ); if ( FAILED(hr)) { TRACE(MTrace::SEVERE_ERROR, L"IWbemServices::CreateInstanceEnum failure\n"); throw _com_error( hr ); } // there may be multiple instances. count = 1; while ( (hr = pewco->Next( INFINITE, 1, &pwco, &count ) ) == S_OK ) { hr = pwco->Get( _bstr_t(L"__RELPATH"), 0, &v_path, NULL, NULL ); if ( FAILED(hr)) { TRACE(MTrace::SEVERE_ERROR, L"IWbemClassObject::Get failure\n"); throw _com_error( hr ); } if( _bstr_t( v_path ) == relPath ) { // required instance found found = true; v_path.Clear(); break; } count = 1; v_path.Clear(); } if( found == false ) { TRACE( MTrace::SEVERE_ERROR, "unable to find instance with path specified\n"); throw _com_error( WBEM_E_INVALID_OBJECT_PATH ); } } else if( FAILED (hr) ) { TRACE( MTrace::SEVERE_ERROR, "IWbemServices::GetObject failure\n"); throw _com_error( hr ); } pathStore->push_back( relPath ); return MWmiObject_SUCCESS; } // getQueriedPath // MWmiObject::MWmiObject_Error MWmiObject::getQueriedPath( const _bstr_t& objectToRunMethodOn, const _bstr_t& query, vector<_bstr_t>* pathStore ) { HRESULT hr; IEnumWbemClassObjectPtr pewco; IWbemClassObjectPtr pwco; _variant_t v_path; unsigned long count; // get instances of object // hr = pws->ExecQuery( L"WQL", query, WBEM_FLAG_FORWARD_ONLY, NULL, &pewco ); if ( FAILED(hr)) { TRACE( MTrace::SEVERE_ERROR, "IWbemServices::CreateInstanceEnum failure\n" ); throw _com_error( hr ) ; } // there may be multiple instances. count = 1; while ( (hr = pewco->Next( INFINITE, 1, &pwco, &count ) ) == S_OK ) { hr = pwco->Get( _bstr_t(L"__RELPATH"), 0, &v_path, NULL, NULL ); if( FAILED(hr) ) { TRACE( MTrace::SEVERE_ERROR, "IWbemClassObject::Get failure\n" ); throw _com_error( hr ); } pathStore->push_back( _bstr_t(v_path) ); count = 1; v_path.Clear(); } return MWmiObject_SUCCESS; } // createInstance // MWmiObject::MWmiObject_Error MWmiObject::createInstance( const _bstr_t& objectToCreateInstancesOf, vector& instanceParameters ) // MWmiInstance* instanceCreated ) { HRESULT hr; IWbemStatusCodeText *pStatus = NULL; IWbemClassObjectPtr pwcoClass; IWbemClassObjectPtr pwcoInstance; // Get object required. hr = pws->GetObject( objectToCreateInstancesOf, 0, NULL, &pwcoClass, NULL ); if( FAILED (hr) ) { TRACE( MTrace::SEVERE_ERROR, "IWbemServices::GetObject failure\n"); throw _com_error( hr ); } hr = pwcoClass->SpawnInstance( 0, &pwcoInstance ); if( FAILED (hr) ) { TRACE( MTrace::SEVERE_ERROR, "IWbemClassObject::SpawnInstance failure\n"); throw _com_error( hr ); } for( int i = 0; i < instanceParameters.size(); ++i ) { hr = pwcoInstance->Put( instanceParameters[i]->getName(), 0, &(instanceParameters[i]->getValue() ), 0 ); if( FAILED( hr ) ) { TRACE( MTrace::SEVERE_ERROR, "IWbemClassObject::Put failure\n"); throw _com_error( hr ); } } hr = pws->PutInstance( pwcoInstance, WBEM_FLAG_CREATE_OR_UPDATE, NULL, NULL ); if( FAILED(hr) ) { TRACE( MTrace::SEVERE_ERROR, "IWbemServices::PutInstance failure\n"); throw _com_error( hr ); } return MWmiObject_SUCCESS; } MWmiObject::MWmiObject_Error MWmiObject::deleteInstance( MWmiInstance& instanceToDelete ) { HRESULT hr; IWbemCallResultPtr pwcr; hr = pws->DeleteInstance( instanceToDelete._path, WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pwcr ); if( FAILED(hr) ) { TRACE( MTrace::SEVERE_ERROR, "IWbemServices::DeleteInstance failure\n"); throw _com_error( hr ); } return MWmiObject_SUCCESS; } // getStatus // MWmiObject::MWmiObject_Error MWmiObject::getStatus() { return MWmiObject_SUCCESS; } // betterConnectServer // HRESULT MWmiObject::betterConnectServer( const BSTR strNetworkResource, const BSTR strUser, const BSTR strPassword, const BSTR strLocale, LONG lSecurityFlags, const BSTR strAuthority, IWbemContext *pCtx, IWbemServices **ppNamespace ) { HRESULT hr; hr = pwl->ConnectServer( strNetworkResource, NULL, // strUser, NULL, // strPassword, strLocale, lSecurityFlags, strAuthority, pCtx, ppNamespace ); // these have been found to be special cases where retrying may help. if( ( hr == 0x800706bf ) || ( hr == 0x80070767 ) || ( hr == 0x80070005 ) ) { int delay = 250; // milliseconds for( int i = 0; i < timesToRetry; ++i ) { Sleep(delay); TRACE( MTrace::SEVERE_ERROR, L"connectserver recoverable failure, retrying\n"); hr = pwl->ConnectServer( strNetworkResource, NULL, // strUser, NULL, // strPassword, strLocale, lSecurityFlags, strAuthority, pCtx, ppNamespace ); if( !FAILED( hr) ) { break; } } } else if ( hr == 0x80041064 ) { // trying to connect to local machine. Cannot use credentials. TRACE( MTrace::INFO, L"connecting to self. Retrying without using credentials\n"); hr = pwl->ConnectServer( strNetworkResource, NULL, NULL, 0, NULL, 0, 0, ppNamespace ); } else if( hr == 0x80004002 ) { // being connected to by a provider itself. TRACE( MTrace::INFO, L"connecting client may be a wmi provider itself. Retrying\n"); // we have to get a new wbemlocatar. // hr = CoCreateInstance(CLSID_WbemUnauthenticatedLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &pwl); if (FAILED(hr)) { TRACE(MTrace::SEVERE_ERROR, L"CoCreateInstance failure\n"); throw _com_error( hr ); } hr = pwl->ConnectServer( strNetworkResource, NULL, // strUser, NULL, // strPassword, strLocale, lSecurityFlags, strAuthority, pCtx, ppNamespace ); } if (FAILED(hr)) { // no hosts are in this cluster. Cannot proceed reliably. WCHAR hrValue[32]; _bstr_t errText; wstring errString; wsprintfW(hrValue, L"hr=0x%08lx", hr); GetErrorCodeText(hr, errText ); errString = L"betterConnectServer failure. " + wstring(hrValue); errString += " (" + errText + L").\n"; TRACE( MTrace::SEVERE_ERROR, errString ); throw _com_error( hr ); } return hr; }