|
|
/*++
Copyright (C) 1996-2001 Microsoft Corporation
Module Name:
WBEMNAME.CPP
Abstract:
Implements the COM layer of WINMGMT --- the class representing a namespace. It is defined in wbemname.h
History:
raymcc 05-Apr-96 Created. raymcc 23-Apr-00 Whistler extensions
--*/
#include "precomp.h"
#pragma warning (disable : 4786)
#include <wbemcore.h>
#include <map>
#include <vector>
#include <genutils.h>
#include <oahelp.inl>
#include <wqllex.h>
#include <autoptr.h>
#include <comutl.h>
#include <helper.h>
#include "wmiarbitrator.h"
#include "wmifinalizer.h"
#include "wmimerger.h"
#ifdef DBG
TimeTraces gTimeTraceHistory; CStaticCritSec OperationStat::lock_; #endif
extern BOOL g_bDontAllowNewConnections;
//***************************************************************************
//
//***************************************************************************
#define WBEM_MASK_DEPTH (WBEM_FLAG_DEEP | WBEM_FLAG_SHALLOW)
#define WBEM_MASK_CREATE_UPDATE (WBEM_FLAG_CREATE_ONLY | WBEM_FLAG_UPDATE_ONLY | WBEM_FLAG_CREATE_OR_UPDATE)
bool illFormatedClass2 (const wchar_t * pszSuperclass) { for (const wchar_t * p = pszSuperclass; *p != L'\0'; ++p) { if (!(isunialphanum (*p) || *p == L'_')) { return true; //Ill formated
} } return false; };
HRESULT IsDerivedFromSystem(CWbemObject& obj, bool * result) { *result = true; CVar vClass; HRESULT hr = obj.GetClassName(&vClass); if (FAILED(hr)) return hr;
wchar_t * className = vClass.GetLPWSTR(); if (className[0] == L'_') return S_OK;
CVar vDeriv; hr = obj.GetDerivation(&vDeriv); if (FAILED(hr)) return hr;
CVarVector *pvTemp = vDeriv.GetVarVector();
for (int j = 0; j < pvTemp->Size(); j++) { CVar& vParentName = pvTemp->GetAt(j); wchar_t * parentName = vParentName.GetLPWSTR(); if (parentName[0] == L'_') { return S_OK; } } *result = false; return S_OK; };
//***************************************************************************
//
// StripServer
// if the string is \\SOMETHING\namespace1\namespace2
// returns namespace1\namespace2
// but it pre-allocates \\.\ in front of it, so that you can move back the pointer
//
//***************************************************************************
LPWSTR StripServer(LPWSTR pszNamespace) { LPWSTR lpRet = NULL; WCHAR * lpPtr = pszNamespace; if (*lpPtr == L'\\' || *lpPtr == L'/') { lpPtr++; if (*lpPtr == L'\\' || *lpPtr == L'/') { BOOL bSlash = FALSE; while (*lpPtr) { lpPtr++; if (*lpPtr == L'\\' || *lpPtr == L'/') { bSlash = TRUE; break; } } if (bSlash) { lpPtr++; size_t tmpSize = 4 + wcslen(lpPtr) + 1; WCHAR * pFull = new WCHAR[tmpSize]; if (NULL == pFull) return pFull; StringCchCopyW(pFull,tmpSize,L"\\\\.\\"); StringCchCopyW(pFull+4,tmpSize-4,lpPtr); lpRet = pFull; } } }
if (!lpRet) { size_t tmpSize = 4 + wcslen(lpPtr) + 1; WCHAR * pFull = new WCHAR[tmpSize]; if (NULL == pFull) return pFull; StringCchCopyW(pFull,tmpSize,L"\\\\.\\"); StringCchCopyW(pFull+4,tmpSize-4,lpPtr); lpRet = pFull; }
return lpRet; }
//
//
//
///////////////////////////////////////////////////////////////
class CSecureEssNamespaceSink : public CUnkBase<IWbemObjectSink, &IID_IWbemObjectSink> { CWbemPtr<CWbemNamespace> m_pNamespace; CWbemPtr<IWbemObjectSink> m_pSink;
public:
CSecureEssNamespaceSink( CWbemNamespace* pNamespace, IWbemObjectSink* pSink ) : m_pNamespace(pNamespace), m_pSink(pSink) {}
STDMETHOD(Indicate)(long lObjectCount, IWbemClassObject** pObjArray) { HRESULT hRes = m_pNamespace->CheckNs(); if (FAILED(hRes)) return hRes;
if ( !m_pNamespace->Allowed( WBEM_FULL_WRITE_REP ) ) return WBEM_E_ACCESS_DENIED; return m_pSink->Indicate( lObjectCount, pObjArray ); }
STDMETHOD(SetStatus)(long a, long b, BSTR c, IWbemClassObject* d) { HRESULT hRes = m_pNamespace->CheckNs(); if (FAILED(hRes)) return hRes;
if ( !m_pNamespace->Allowed( WBEM_FULL_WRITE_REP ) ) return WBEM_E_ACCESS_DENIED; return m_pSink->SetStatus( a, b, c, d ); } };
//***************************************************************************
//
//***************************************************************************
//
CWbemNamespace::CWbemNamespace() { m_uSecondaryRefCount = 0; m_bShutDown = FALSE;
m_pSession = 0; m_pDriver = 0; m_pNsHandle = 0; m_pScopeHandle = 0;
m_pThisNamespace = 0; m_pThisNamespaceFull = 0; m_dwPermission = 0; m_dwSecurityFlags = 0; m_wszUserName = 0;
m_bProvider = FALSE; m_bForClient = FALSE; m_bESS = FALSE;
m_bSecurityInitialized = FALSE;
m_pProvFact = 0; m_pCoreSvc = 0; m_bRepositOnly = FALSE; m_pRefreshingSvc = NULL;
m_pszClientMachineName = NULL; m_dwClientProcessID = -1;
m_pArb = CWmiArbitrator::GetRefedArbitrator(); m_pArb->RegisterNamespace((_IWmiCoreHandle *)this);
gClientCounter.AddClientPtr(&m_Entry);
}
//***************************************************************************
//
//***************************************************************************
//
CWbemNamespace *CWbemNamespace::CreateInstance() { try { if (NULL == CWmiArbitrator::GetUnrefedArbitrator()) return NULL; CWbemNamespace *pNs = new CWbemNamespace; if (pNs) pNs->AddRef(); return pNs; } catch(CX_Exception &) { return 0; } }
//***************************************************************************
//
// CWbemNamespace::Initialize
//
// Real constructor. In addition to finding the namespace in the database, this
// function also enumerates all the class providers in the namespace and
// loads them. It also notifies the ESS of the opening.
//
// PARAMETERS:
//
// LPWSTR Namespace The full of the namespace to create.
//
// RETURN VALUES:
//
// Even though this function has no return values, it indicates success
// or failure by setting the Status member variable to the error code.
// WBEM_S_NO_ERROR On Success
// WBEM_E_INVALID_NAMESPACE No such namespace
// WBEM_E_CRITICAL_ERROR Other database error.
//
//***************************************************************************
HRESULT CWbemNamespace::Initialize( LPWSTR pszNamespace, LPWSTR wszUserName, DWORD dwSecFlags, DWORD dwPermission, BOOL bForClient, BOOL bRepositOnly, LPCWSTR pszClientMachineName, DWORD dwClientProcessID, BOOL bSkipSDInitialize, IWmiDbSession *pParentSession) { try { m_dwSecurityFlags = dwSecFlags; m_dwPermission = dwPermission; if(g_bDontAllowNewConnections) return WBEM_E_SHUTTING_DOWN;
PSID pRawSid; SID_IDENTIFIER_AUTHORITY id = SECURITY_NT_AUTHORITY;
if (!AllocateAndInitializeSid( &id, 2, // SEC:REVIEWED 2002-03-22 : OK
SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0,0,0,0,0,0,&pRawSid)) return WBEM_E_OUT_OF_MEMORY;
CNtSid Sid(pRawSid); FreeSid( pRawSid ); if (CNtSid::NoError != Sid.GetStatus()) return WBEM_E_OUT_OF_MEMORY; CNtAce ace(1,ACCESS_ALLOWED_ACE_TYPE,0,Sid); if(ace.GetStatus() != 0) return WBEM_E_OUT_OF_MEMORY;
CNtAcl acl; acl.AddAce(&ace); m_sdCheckAdmin.SetDacl(&acl); CNtSid owner(CNtSid::CURRENT_USER); if (CNtSid::NoError != owner.GetStatus()) return WBEM_E_OUT_OF_MEMORY; m_sdCheckAdmin.SetGroup(&owner); m_sdCheckAdmin.SetOwner(&owner);
m_bForClient = bForClient;
m_pThisNamespaceFull = StripServer(pszNamespace); if(m_pThisNamespaceFull == NULL) return WBEM_E_OUT_OF_MEMORY; m_pThisNamespace = m_pThisNamespaceFull + 4; // move past "\\.\"
m_pCoreSvc = CCoreServices::CreateInstance(); if(m_pCoreSvc == NULL) return WBEM_E_OUT_OF_MEMORY;
m_pProvFact = 0;
m_bRepositOnly = bRepositOnly;
// Flip the slashes
// ================
WCHAR* pwc = m_pThisNamespace; while(*pwc) { if(*pwc == '/') *pwc = '\\'; pwc++; }
m_wszUserName = (wszUserName?Macro_CloneLPWSTR(wszUserName):NULL);
// Repository binding.
// ===================
m_pNsHandle = 0; HRESULT hRes; IWmiDbSession *pTempSession= pParentSession; if (pTempSession == NULL) { hRes = CRepository::GetDefaultSession(&pTempSession); if (FAILED(hRes)) return hRes; } else pTempSession->AddRef(); CReleaseMe rmSession(pTempSession);
hRes = CRepository::OpenScope(pTempSession, m_pThisNamespace, 0, &m_pDriver, &m_pSession, &m_pScopeHandle, &m_pNsHandle); if (FAILED(hRes)) { Status = WBEM_E_INVALID_NAMESPACE; return hRes; }
if (m_pScopeHandle == 0) { m_bSubscope = FALSE; m_pScopeHandle = m_pNsHandle; if(m_pScopeHandle == NULL) { ERRORTRACE((LOG_WBEMCORE, "OpenScope returned success, yet m_pNsHandle is null!\n")); return WBEM_E_CRITICAL_ERROR; } m_pScopeHandle->AddRef(); } else { #ifdef DBG
DebugBreak(); #endif
m_bSubscope = TRUE; return WBEM_E_INVALID_NAMESPACE; }
m_pProvFact = 0; if (!bRepositOnly) { _IWmiProvSS *pProvSS = 0; m_pCoreSvc->GetProviderSubsystem(0, &pProvSS); CReleaseMe _(pProvSS);
if(pProvSS) { HRESULT hr = pProvSS->Create( this, // Stupid because v-table access can occur before constructor completion
0, // lFlags
0, // pCtx
m_pThisNamespace, // Path
IID__IWmiProviderFactory, (LPVOID *) &m_pProvFact );
if (FAILED(hr)) return hr ; } }
if(pszClientMachineName) { delete m_pszClientMachineName; DUP_STRING_NEW(m_pszClientMachineName, pszClientMachineName); if(m_pszClientMachineName == NULL) return WBEM_E_OUT_OF_MEMORY; } m_dwClientProcessID = dwClientProcessID;
Status = WBEM_S_NO_ERROR;
//Initialize Security descriptor
if (!bSkipSDInitialize) { hRes = InitializeSD(pTempSession); if (FAILED(hRes)) return hRes; }
m_pCoreSvc->IncrementCounter(WMICORE_SELFINST_CONNECTIONS, 1);
return Status;
} catch(...) { ExceptionCounter c; return WBEM_E_FAILED; } }
//***************************************************************************
//
// CWbemNamespace::~CWbemNamespace
//
// Notifies the ESS of namespace closure and frees up all the class providers.
//
//***************************************************************************
CWbemNamespace::~CWbemNamespace() { // do this before releasing the arbitrator
m_pArb->UnregisterNamespace((_IWmiCoreHandle *)this);
if (m_pCoreSvc) m_pCoreSvc->DecrementCounter(WMICORE_SELFINST_CONNECTIONS, 1);
ReleaseIfNotNULL(m_pProvFact); ReleaseIfNotNULL(m_pCoreSvc); ReleaseIfNotNULL(m_pSession); ReleaseIfNotNULL(m_pDriver); ReleaseIfNotNULL(m_pNsHandle); ReleaseIfNotNULL(m_pScopeHandle); ReleaseIfNotNULL(m_pRefreshingSvc); ReleaseIfNotNULL(m_pArb);
DeleteAndNull(m_pThisNamespaceFull); DeleteAndNull(m_wszUserName); DeleteAndNull(m_pszClientMachineName);
gClientCounter.RemoveClientPtr(&m_Entry); }
//***************************************************************************
//
// CWbemNamespace::QueryInterface
//
// Exports IWbemServices interface.
//
//***************************************************************************
STDMETHODIMP CWbemNamespace::QueryInterface( IN REFIID riid, OUT LPVOID *ppvObj ) {
*ppvObj = 0;
if (IID_IUnknown==riid || IID_IWbemServices==riid ) { *ppvObj = (IWbemServices*)this; AddRef(); return S_OK; } else if (IID_IWbemRefreshingServices == riid) { CInCritSec ics(&m_cs);
// Check if we already have this one
if ( NULL == m_pRefreshingSvc ) { IUnknown * pUnk = NULL; // Aggregate this interface - We MUST use IUnknown, so the aggregee does not AddRef us.
HRESULT hr = CoCreateInstance( CLSID__WbemConfigureRefreshingSvcs, // SEC:REVIEWED 2002-03-22 : OK
(IWbemServices*) this, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**) &pUnk ); if (FAILED(hr)) return hr; OnDeleteIf<IUnknown *,void(*)(IUnknown *),RM> rmUnk(pUnk);
_IWbemConfigureRefreshingSvcs* pCfgRefrSvc = NULL; hr = pUnk->QueryInterface( IID__IWbemConfigureRefreshingSvcs, (void**) &pCfgRefrSvc ); if (FAILED(hr)) return hr; CReleaseMe rm(pCfgRefrSvc);
// Use BSTR's in case any marshaling takes place
BSTR pstrMachineName = SysAllocString( ConfigMgr::GetMachineName() ); if (NULL == pstrMachineName) return E_OUTOFMEMORY; CSysFreeMe sfm1( pstrMachineName );
BSTR pstrNamespace = SysAllocString( m_pThisNamespace ); if (NULL == pstrNamespace) return E_OUTOFMEMORY; CSysFreeMe sfm2( pstrNamespace );
hr = pCfgRefrSvc->SetServiceData( pstrMachineName, pstrNamespace );
if (FAILED(hr)) return hr;
// compensate the Automatic Objects above
m_pRefreshingSvc = pUnk; rmUnk.dismiss(); }
return m_pRefreshingSvc->QueryInterface( IID_IWbemRefreshingServices, ppvObj ); } else if(IID_IWbemInternalServices == riid) { *ppvObj = (IWbemInternalServices*)this; AddRef(); return S_OK; }
return E_NOINTERFACE; }
//***************************************************************************
//
//***************************************************************************
//
ULONG CWbemNamespace::AddRef() { ULONG uNewCount = InterlockedIncrement((LONG *) &m_uSecondaryRefCount); return uNewCount; }
//***************************************************************************
//
//***************************************************************************
//
ULONG CWbemNamespace::Release() { ULONG uNewCount = InterlockedDecrement((LONG *) &m_uSecondaryRefCount); if (0 == uNewCount) delete this; return uNewCount; }
//***************************************************************************
//
//***************************************************************************
//
HRESULT CWbemNamespace::Dump(FILE *f) { // SEC:REVIEWED 2002-03-22 : OK; debugging use only
fprintf(f, "---Namespace = 0x%p----------------------------\n", this); // SEC:REVIEWED 2002-03-22 : OK
fprintf(f, " Secondary Refcount = %d\n", m_uSecondaryRefCount); // SEC:REVIEWED 2002-03-22 : OK
if(m_pThisNamespace) fprintf(f, " Name = %ls\n", m_pThisNamespace); // SEC:REVIEWED 2002-03-22 : OK
if(m_wszUserName) fprintf(f, " User Name = %ls\n", m_wszUserName); // SEC:REVIEWED 2002-03-22 : OK
if(m_pszClientMachineName) fprintf(f, " Client Machine Name = %ls\n", m_pszClientMachineName); // SEC:REVIEWED 2002-03-22 : OK
else fprintf(f, " Client Machine Name = <unknown>\n"); // SEC:REVIEWED 2002-03-22 : OK
if(m_dwClientProcessID) fprintf(f, " Client Process = 0X%X\n", m_dwClientProcessID); // SEC:REVIEWED 2002-03-22 : OK
else fprintf(f, " Client Process = <unknown>\n"); // SEC:REVIEWED 2002-03-22 : OK
return S_OK; }
//***************************************************************************
//
//***************************************************************************
//
/*
HRESULT CWbemNamespace::SetErrorObj(IWbemClassObject* pErrorObj) { if (pErrorObj == NULL) { return S_OK; }
IErrorInfo* pInfo; HRESULT hRes = pErrorObj->QueryInterface(IID_IErrorInfo, (void**)&pInfo); if (FAILED(hRes)) return hRes;
hRes = SetErrorInfo(0, pInfo); pInfo->Release(); return hRes; } */
//***************************************************************************
//
// CWbemNamespace::SplitLocalized
//
//***************************************************************************
HRESULT CWbemNamespace::SplitLocalized ( CWbemObject *pOriginal, CWbemObject *pStoredObj ) { HRESULT hres = 0;
CVar vProv;
IWbemQualifierSet *pOrigQs = NULL, *pStoredQs = NULL; VARIANT vVal; VariantInit(&vVal);
hres = pOriginal->GetQualifierSet(&pOrigQs); if (FAILED(hres)) return hres;
if (pStoredObj) { hres = pStoredObj->GetQualifierSet(&pStoredQs); if (FAILED(hres)) { pOrigQs->Release(); return hres; } }
hres = FixAmendedQualifiers(pOrigQs, pStoredQs); pOrigQs->Release(); pOrigQs = NULL; if (pStoredQs) { pStoredQs->Release(); pStoredQs = NULL; }
if (SUCCEEDED(hres)) { pOriginal->BeginEnumeration(0); LONG lLong; CIMTYPE ct; VARIANT vNewVal; VariantInit(&vNewVal); BSTR strPropName = NULL;
while((hres = pOriginal->Next(0, &strPropName, &vNewVal, &ct, &lLong)) == S_OK) { CSysFreeMe sfm(strPropName); CClearMe ccm(&vNewVal); CWStringArray arrDel; pOrigQs = NULL; pStoredQs = NULL;
// Ignore system qualifiers.
if (strPropName[0] == L'_') { continue; }
hres = pOriginal->GetPropertyQualifierSet(strPropName, &pOrigQs); if (FAILED(hres)) { return hres; }
pStoredQs = NULL; if (pStoredObj) { pStoredObj->GetPropertyQualifierSet(strPropName, &pStoredQs); }
hres = FixAmendedQualifiers(pOrigQs, pStoredQs); pOrigQs->Release(); if (pStoredQs) pStoredQs->Release();
}
pOriginal->EndEnumeration();
// Unfortunately, we have to enumerate the methods,
// and *then* update them...
BSTR bstrMethodName;
pOriginal->BeginMethodEnumeration(0); IWbemClassObject *pLIn = NULL, *pLOut = NULL, *pOIn = NULL, *pOOut = NULL;
// first count the number of methods
while ( pOriginal->NextMethod( 0, &bstrMethodName, 0, 0 ) == S_OK ) { pLIn = pLOut = pOIn = pOOut = NULL; pOrigQs = NULL ; pStoredQs = NULL ;
hres = pOriginal->GetMethod(bstrMethodName, 0, &pLIn, &pLOut); if ( FAILED ( hres ) ) { continue ; }
CSysFreeMe fm(bstrMethodName); CReleaseMe rm0(pLIn); CReleaseMe rm2(pLOut);
hres = pOriginal->GetMethodQualifierSet(bstrMethodName, &pOrigQs); if (FAILED(hres)) { continue; }
CReleaseMe rm4 ( pOrigQs ) ;
if (pStoredObj) { hres = pStoredObj->GetMethodQualifierSet(bstrMethodName, &pStoredQs); if ( FAILED ( hres ) ) { continue ; } }
CReleaseMe rm5 ( pStoredQs ) ;
// Method qualifiers...
hres = FixAmendedQualifiers(pOrigQs, pStoredQs);
if (SUCCEEDED(hres)) { if (pStoredObj) hres = pStoredObj->GetMethod(bstrMethodName, 0, &pOIn, &pOOut);
CReleaseMe rm1(pOIn); CReleaseMe rm3(pOOut);
if (pLIn) hres = SplitLocalized((CWbemObject *)pLIn, (CWbemObject *)pOIn);
if (pLOut) hres = SplitLocalized((CWbemObject *)pLOut, (CWbemObject *)pOOut);
hres = pOriginal->PutMethod(bstrMethodName, 0, pLIn, pLOut); } else break; } pOriginal->EndMethodEnumeration();
}
hres = 0;
return hres;
}
//***************************************************************************
//
// CWbemNamespace::FixAmendedQualifiers
//
//***************************************************************************
HRESULT CWbemNamespace::FixAmendedQualifiers( IWbemQualifierSet *pOriginal, IWbemQualifierSet *pNew ) { HRESULT hres = 0; CWStringArray arrDelete; CWStringArray arrProps; BSTR strName = 0; long lFlavor;
int i;
pOriginal->BeginEnumeration(0); // BUGBUG EndEnum
while(pOriginal->Next(0, &strName, NULL, NULL) == S_OK) { CSysFreeMe sfm(strName); if (CFlexArray::no_error != arrProps.Add(strName)) return WBEM_E_OUT_OF_MEMORY; }
for (i = 0; i < arrProps.Size(); i++) { _variant_t vVal; pOriginal->Get(arrProps.GetAt(i), 0, &vVal, &lFlavor); if (lFlavor & WBEM_FLAVOR_AMENDED) { // Delete the "amended" qualifier.
if (CFlexArray::no_error != arrDelete.Add(arrProps.GetAt(i))) return WBEM_E_OUT_OF_MEMORY;
// Restore any original qualifier value.
if (pNew) { _variant_t vOldVal; long lOldFlavor; if (pNew->Get(arrProps.GetAt(i), 0, &vOldVal, &lOldFlavor) != WBEM_E_NOT_FOUND) { pOriginal->Put(arrProps.GetAt(i), &vOldVal, lOldFlavor); arrDelete.RemoveAt(arrDelete.Size()-1); } } } } pOriginal->EndEnumeration();
for (i = 0; i < arrDelete.Size(); i++) { pOriginal->Delete(arrDelete.GetAt(i)); }
arrDelete.Empty();
return hres;
}
//***************************************************************************
//
// CWbemNamespace::Exec_DeleteClass
//
// Actually deletes the class from the database. No class provider support.
// Raises class deletion event.
//
// Parameters and return values are exacly the same as those for DeleteClass
// as described in help
//
//***************************************************************************
HRESULT CWbemNamespace::Exec_DeleteClass( LPWSTR pszClassName, long lFlags, IWbemContext* pCtx, CBasicObjectSink* pSink ) { TIMETRACE(TimeTraces::DeleteClass); HRESULT hRes; IWbemServices *pClassProv = 0; CSynchronousSink* pSyncSink = 0; BSTR bstrClass = 0; IWbemClassObject* pStaticClassDef = 0; BOOL bInRepository = FALSE;
if (pszClassName == 0 || pSink == 0) return pSink->Return(WBEM_E_INVALID_PARAMETER);
if (pszClassName[0] == L'_') return pSink->Return(WBEM_E_INVALID_OPERATION);
// Bring up the dynamic class provider symposium for consultation.
// ===============================================================
if (!m_bRepositOnly && m_pProvFact) { hRes = m_pProvFact->GetClassProvider( 0, // lFlags
pCtx, m_wszUserName, m_wsLocale, m_pThisNamespace, // IWbemPath pointer
0, IID_IWbemServices, (LPVOID *) &pClassProv );
if (FAILED(hRes)) return pSink->Return(hRes); }
CReleaseMe _2(pClassProv);
_IWmiCoreWriteHook *pHook = 0; hRes = m_pCoreSvc->NewPerTaskHook(&pHook); if (FAILED(hRes)) return pSink->Return(hRes); CReleaseMe _(pHook); HRESULT hHookResult = 0;
// First, try repository.
// ======================
if (m_bRepositOnly || m_pProvFact == NULL) {
if (!Allowed(WBEM_FULL_WRITE_REP)) return pSink->Return(WBEM_E_ACCESS_DENIED);
if (pHook) pHook->PreDelete(WBEM_FLAG_CLASS_DELETE, lFlags, pCtx, NULL, m_pThisNamespace, pszClassName );
hRes = CRepository::DeleteByPath(m_pSession, m_pNsHandle, pszClassName, lFlags);
if (pHook) pHook->PostDelete(WBEM_FLAG_CLASS_DELETE, hRes, pCtx, NULL, m_pThisNamespace, pszClassName, NULL);
return pSink->Return(hRes); }
// If here, we have to get it first because dynamic class providers
// could be seriously affected by the removal of the class.
// ================================================================
hRes = CRepository::GetObject( m_pSession, m_pNsHandle, pszClassName, 0, &pStaticClassDef );
CReleaseMe _1(pStaticClassDef);
if (SUCCEEDED(hRes)) { bInRepository = TRUE; if (!Allowed(WBEM_FULL_WRITE_REP)) return pSink->Return(WBEM_E_ACCESS_DENIED); if (pStaticClassDef == 0) return pSink->Return(WBEM_E_CRITICAL_ERROR); }
// Build up a synchronous sink to receive the class.
// =================================================
pSyncSink = CSynchronousSink::Create(); if (pSyncSink == NULL) return pSink->Return(WBEM_E_OUT_OF_MEMORY); pSyncSink->AddRef(); CReleaseMe _3(pSyncSink);
// Try to get it.
// ==============
bstrClass = SysAllocString(pszClassName); if (bstrClass == 0) return pSink->Return(WBEM_E_OUT_OF_MEMORY); CSysFreeMe sfm(bstrClass);
// If the class was in the repository, we are merely advising dynamic
// class providers that the class is going away.
// ==================================================================
if (bInRepository) lFlags |= WBEM_FLAG_ADVISORY; else { if (!Allowed(WBEM_WRITE_PROVIDER)) return pSink->Return(WBEM_E_ACCESS_DENIED); }
hRes = pClassProv->DeleteClassAsync(bstrClass, lFlags & ~WBEM_FLAG_USE_AMENDED_QUALIFIERS, pCtx, pSyncSink);
if (FAILED(hRes) && hRes != WBEM_E_NOT_FOUND) return pSink->Return(hRes);
pSyncSink->Block(); IWbemClassObject* pErrorObj = 0; pSyncSink->GetStatus(&hRes, NULL, &pErrorObj); CReleaseMe rmErrObj(pErrorObj);
if (FAILED(hRes)) { pSink->Return(hRes, pErrorObj); return hRes; }
// If here, we can go ahead with it.
// =================================
if (pHook) pHook->PreDelete(WBEM_FLAG_CLASS_DELETE, lFlags, pCtx, NULL, m_pThisNamespace, pszClassName );
if (bInRepository) hRes = CRepository::DeleteByPath(m_pSession, m_pNsHandle, pszClassName, lFlags);
if (pHook) pHook->PostDelete(WBEM_FLAG_CLASS_DELETE, hRes, pCtx, NULL, m_pThisNamespace, pszClassName, NULL);
return pSink->Return(hRes); }
//***************************************************************************
//
// CWbemNamespace::Exec_CreateClassEnum
//
//***************************************************************************
HRESULT CWbemNamespace::Exec_CreateClassEnum( LPWSTR pszSuperclass, long lFlags, IWbemContext* pCtx, CBasicObjectSink* pSink ) { TIMETRACE(TimeTraces::CreateClassEnum); HRESULT hRes; IWbemClassObject* pErrorObj = 0; IWbemServices *pClassProv = 0; CSynchronousSink* pSyncSink = 0; BSTR bstrClass = 0; IWbemClassObject* pResultObj = 0; CCombiningSink* pCombiningSink = NULL; CLocaleMergingSink * pLocaleSink = NULL; CBasicObjectSink *pTmp = 0; BSTR bstrSuperclass = 0; bool bProvSSNotFound = false; bool bRepNotFound = false;
// Quick check of parms.
// =====================
if (pSink == 0) return WBEM_E_INVALID_PARAMETER;
if (pszSuperclass == 0) // Ensure we point to a blank instead of NULL with no superclass
pszSuperclass = L""; else { if (illFormatedClass2 (pszSuperclass)) return pSink->Return(WBEM_E_INVALID_CLASS); }
// Prepare some sinks to hold everything.
// ======================================
if ((lFlags & WBEM_FLAG_USE_AMENDED_QUALIFIERS)) { pLocaleSink = new CLocaleMergingSink(pSink, m_wsLocale, m_pThisNamespace); if (pLocaleSink == NULL) return pSink->Return(WBEM_E_OUT_OF_MEMORY); pLocaleSink->AddRef(); pTmp = pLocaleSink; } else pTmp = pSink; CReleaseMe _1(pLocaleSink);
pCombiningSink = new CCombiningSink(pTmp); if (NULL == pCombiningSink) return pSink->Return(WBEM_E_OUT_OF_MEMORY); pCombiningSink->AddRef(); CReleaseMe _2(pCombiningSink);
// Bring up the dynamic class provider symposium for consultation.
// ===============================================================
if ( !m_bRepositOnly && m_pProvFact) {
hRes = m_pProvFact->GetClassProvider( 0, // lFlags
pCtx, m_wszUserName, m_wsLocale, m_pThisNamespace, // IWbemPath pointer
0, IID_IWbemServices, (LPVOID *) &pClassProv );
if (FAILED(hRes)) return pCombiningSink->Return(hRes); }
CReleaseMe _3(pClassProv);
// Get the repository classes.
// ===========================
BOOL bUseStatic = !(lFlags & WBEM_FLAG_NO_STATIC); if (bUseStatic) { if ((lFlags & WBEM_MASK_DEPTH) == WBEM_FLAG_DEEP) { // DEEP ENUM
// ==========
IWbemObjectSink *pObjSink = (IWbemObjectSink *) pCombiningSink; hRes = CRepository::QueryClasses( m_pSession, m_pNsHandle, WBEM_FLAG_DEEP | WBEM_FLAG_VALIDATE_CLASS_EXISTENCE, pszSuperclass, pObjSink); } else { // SHALLOW ENUM
// =============
IWbemObjectSink *pObjSink = (IWbemObjectSink *) pCombiningSink; hRes = CRepository::QueryClasses( m_pSession, m_pNsHandle, WBEM_FLAG_SHALLOW | WBEM_FLAG_VALIDATE_CLASS_EXISTENCE, pszSuperclass, pObjSink); }
//If a SetStatus of INVALID_CLASS was indicated it means there is no static
//class, however we need to continue on with dynamic classes, so we need
//to clear the error.
if ((pCombiningSink->GetHResult() == WBEM_E_NOT_FOUND) || (hRes == WBEM_E_NOT_FOUND)) { bRepNotFound = true; pCombiningSink->ClearHResult(); hRes = WBEM_S_NO_ERROR; }
if (FAILED(hRes)) { // A real failure. Give up.
// =========================
return pCombiningSink->Return(hRes); } }
if (m_bRepositOnly || m_pProvFact == NULL) return pCombiningSink->Return(WBEM_S_NO_ERROR);
// If here, we have to merge in the dynamic classes.
// =================================================
// Build up a synchronous sink to receive the classes.
// ===================================================
pSyncSink = CSynchronousSink::Create(); if (pSyncSink == NULL) return pSink->Return(WBEM_E_OUT_OF_MEMORY); pSyncSink->AddRef(); CReleaseMe _4(pSyncSink);
// Try to get it.
// ==============
bstrSuperclass = SysAllocString(pszSuperclass); if (bstrSuperclass == 0) return pSink->Return(WBEM_E_OUT_OF_MEMORY); CSysFreeMe sfm99(bstrSuperclass);
CDecoratingSink * pDecore = new CDecoratingSink(pSyncSink, this); if(pDecore == NULL) return pSink->Return(WBEM_E_OUT_OF_MEMORY); pDecore->AddRef(); CReleaseMe cdecor(pDecore); hRes = pClassProv->CreateClassEnumAsync(bstrSuperclass, (lFlags & (~WBEM_FLAG_USE_AMENDED_QUALIFIERS)) & ~WBEM_FLAG_NO_STATIC, pCtx, pDecore); if ((pSyncSink->GetHResult() == WBEM_E_NOT_FOUND) || (hRes == WBEM_E_NOT_FOUND)) { bProvSSNotFound = true; pSyncSink->ClearHResult(); hRes = WBEM_S_NO_ERROR; }
if (bProvSSNotFound && bRepNotFound) { //Neither the provider subsystem nor the repository found this object,
//therefore we need to actually return an error!
return pCombiningSink->Return(WBEM_E_INVALID_CLASS); }
if (FAILED(hRes) && hRes != WBEM_E_NOT_FOUND) return pCombiningSink->Return(hRes);
pSyncSink->Block(); pSyncSink->GetStatus(&hRes, NULL, &pErrorObj);
if (FAILED(hRes)) { pCombiningSink->Return(hRes, pErrorObj); if (pErrorObj) pErrorObj->Release(); return hRes; }
// Otherwise, somebody claimed to have supplied some classes. Add them into to the
// combining sink.
// =================================================================================
CRefedPointerArray<IWbemClassObject>& raObjects = pSyncSink->GetObjects();
for (int i = 0; i < raObjects.GetSize(); i++) { IWbemClassObject *pClsDef = (IWbemClassObject *) raObjects[i]; pCombiningSink->Indicate(1, &pClsDef); }
return pCombiningSink->Return(WBEM_S_NO_ERROR); }
//***************************************************************************
//
// CWbemNamespace::Exec_PutClass
//
//***************************************************************************
HRESULT CWbemNamespace::Exec_PutClass( READONLY IWbemClassObject* pObj, long lFlags, IWbemContext* pCtx, CBasicObjectSink* pSink, BOOL fIsInternal ) { TIMETRACE(TimeTraces::PutClass); HRESULT hRes; IWbemClassObject* pErrorObj = 0; IWbemServices *pClassProv = 0; CSynchronousSink* pSyncSink = 0; BSTR bstrClass = 0; IWbemClassObject* pStaticClassDef = 0; BOOL bInRepository = FALSE;
// Maintains old functionality
long lRealFlags = lFlags;
if (pSink == 0) return WBEM_E_INVALID_PARAMETER;
if (pObj == 0) return pSink->Return(WBEM_E_INVALID_PARAMETER);
// Extract the class name.
// =======================
CVARIANT v; hRes = pObj->Get(L"__CLASS", 0, &v, 0, 0); if (FAILED(hRes)) return pSink->Return(hRes);
WCHAR * pClassName = L""; if (VT_BSTR == V_VT(&v) && NULL != V_BSTR(&v)) { pClassName = V_BSTR(&v); }
if (wcslen_max(pClassName,g_IdentifierLimit) > g_IdentifierLimit) return pSink->Return(WBEM_E_QUOTA_VIOLATION); COperationError OpInfo(pSink, L"PutClass",pClassName); if (!OpInfo.IsOk()) return pSink->Return(WBEM_E_OUT_OF_MEMORY); _IWmiObject * pIntObj = NULL; hRes = pObj->QueryInterface(IID__IWmiObject,(void **)&pIntObj); CReleaseMe rm1(pIntObj); if (FAILED(hRes)) return OpInfo.ErrorOccurred(WBEM_E_INVALID_PARAMETER);
if (WBEM_S_NO_ERROR == pIntObj->IsObjectInstance()) return OpInfo.ErrorOccurred(WBEM_E_INVALID_OPERATION);
CVARIANT v2; hRes = pObj->Get(L"__SuperClass", 0, &v2, 0, 0); if (FAILED(hRes)) return OpInfo.ErrorOccurred(hRes);
if (v2.GetStr() && wcslen(v2.GetStr())) // SEC:REVIEWED 2002-03-22 : OK; NULL terminator provably exists
{ if (CSystemProperties::IsIllegalDerivedClass(v2.GetStr())) return OpInfo.ErrorOccurred(WBEM_E_INVALID_SUPERCLASS); }
if (!fIsInternal ) { if ((v.GetStr() == NULL) || (v.GetStr()[0] == '_')) // SEC:REVIEWED 2002-03-22 : OK; null terminator provably exists
return OpInfo.ErrorOccurred(WBEM_E_INVALID_OPERATION); if (v.GetStr()[wcslen(v.GetStr())-1] == '_') // SEC:REVIEWED 2002-03-22 : OK; null terminator provably exists
return OpInfo.ErrorOccurred(WBEM_E_INVALID_OBJECT); }
if ( !m_bRepositOnly && !fIsInternal && m_pProvFact ) { // Bring up the dynamic class provider symposium for consultation.
// ===============================================================
hRes = m_pProvFact->GetClassProvider( 0, // lFlags
pCtx, m_wszUserName, m_wsLocale, m_pThisNamespace, // IWbemPath pointer
0, IID_IWbemServices, (LPVOID *) &pClassProv );
if (FAILED(hRes)) return OpInfo.ErrorOccurred(hRes); }
CReleaseMe _2(pClassProv);
// Set up a new per-task hook.
// ===========================
_IWmiCoreWriteHook *pHook = 0; hRes = m_pCoreSvc->NewPerTaskHook(&pHook); if (FAILED(hRes)) return OpInfo.ErrorOccurred(hRes); CReleaseMe _(pHook); HRESULT hHookResult = 0;
// First, try repository.
// ======================
if (m_bRepositOnly || fIsInternal || m_pProvFact == NULL) { if (!Allowed(WBEM_FULL_WRITE_REP)) return OpInfo.ErrorOccurred(WBEM_E_ACCESS_DENIED);
if (pHook) pHook->PrePut(WBEM_FLAG_CLASS_PUT, lFlags, pCtx, 0, m_pThisNamespace, v.GetStr(), (_IWmiObject *)pObj);
hRes = CRepository::PutObject(m_pSession, m_pNsHandle, IID_IWbemClassObject, pObj, lFlags);
if (pHook) pHook->PostPut(WBEM_FLAG_CLASS_PUT, hRes, pCtx, 0, m_pThisNamespace, v.GetStr() , (_IWmiObject *)pObj, NULL);
return OpInfo.ErrorOccurred(hRes); }
hRes = CRepository::GetObject( m_pSession, m_pNsHandle, v.GetStr(), 0, &pStaticClassDef );
CReleaseMe _1(pStaticClassDef);
if (SUCCEEDED(hRes)) { bInRepository = TRUE;
if (pStaticClassDef != 0) { // Remove all the amended qualifiers
// =================================
if (lFlags & WBEM_FLAG_USE_AMENDED_QUALIFIERS ) { int nRes = SplitLocalized( (CWbemObject*) pObj, (CWbemObject*) pStaticClassDef ); if (FAILED(nRes)) { return pSink->Return(nRes); } } } else { return OpInfo.ErrorOccurred(WBEM_E_CRITICAL_ERROR); } }
// Build up a synchronous sink to receive the class.
// =================================================
pSyncSink = CSynchronousSink::Create(); if (pSyncSink == NULL) return OpInfo.ErrorOccurred(WBEM_E_OUT_OF_MEMORY); pSyncSink->AddRef(); CReleaseMe _3(pSyncSink);
// Try to put it.
// ==============
// If the class was in the repository, we are merely advising dynamic
// class providers that the class is going away.
// ==================================================================
if (bInRepository) lFlags |= WBEM_FLAG_ADVISORY;
if (!Allowed(WBEM_WRITE_PROVIDER)) hRes = WBEM_E_ACCESS_DENIED; else hRes = pClassProv->PutClassAsync(pObj, lFlags & ~WBEM_FLAG_USE_AMENDED_QUALIFIERS, pCtx, pSyncSink);
if (FAILED(hRes) && hRes != WBEM_E_NOT_FOUND) return OpInfo.ErrorOccurred(hRes);
pSyncSink->Block(); pSyncSink->GetStatus(&hRes, NULL, &pErrorObj);
if (SUCCEEDED(hRes)&&(!bInRepository)) { pSink->Return(hRes, pErrorObj); if (pErrorObj) pErrorObj->Release(); return hRes; }
if (FAILED(hRes) && hRes != WBEM_E_NOT_FOUND) { pSink->Return(hRes, pErrorObj); if (pErrorObj) pErrorObj->Release(); return hRes; }
// If here, we can go ahead with it.
// =================================
if (!Allowed(WBEM_FULL_WRITE_REP)) return OpInfo.ErrorOccurred(WBEM_E_ACCESS_DENIED);
if (pHook) { pHook->PrePut(WBEM_FLAG_CLASS_PUT, lFlags, pCtx, 0, m_pThisNamespace, v.GetStr(), (_IWmiObject *)pObj); }
hRes = CRepository::PutObject(m_pSession, m_pNsHandle, IID_IWbemClassObject, pObj, lFlags);
// Workaround for forceupdate and instances problem
if ( WBEM_E_CLASS_HAS_INSTANCES == hRes && ( lRealFlags & WBEM_FLAG_UPDATE_FORCE_MODE ) ) { _variant_t v; hRes = pObj->Get( L"__CLASS", 0L, &v, NULL, NULL ); if ( SUCCEEDED( hRes ) && V_VT( &v ) == VT_BSTR ) { hRes = DeleteObject( V_BSTR( &v ), 0L, pCtx, NULL ); if ( SUCCEEDED( hRes ) ) { hRes = CRepository::PutObject(m_pSession, m_pNsHandle, IID_IWbemClassObject, pObj, lFlags); } } else { hRes = WBEM_E_CLASS_HAS_INSTANCES; } }
if (pHook) { pHook->PostPut(WBEM_FLAG_CLASS_PUT, hRes, pCtx, 0, m_pThisNamespace, v.GetStr() , (_IWmiObject *)pObj, NULL); }
return OpInfo.ErrorOccurred(hRes); }
//***************************************************************************
//
//***************************************************************************
HRESULT CWbemNamespace::Exec_CancelAsyncCall( IWbemObjectSink* pSink ) {
_IWmiArbitrator *pArb = CWmiArbitrator::GetUnrefedArbitrator(); HRESULT hRes = pArb->CancelTasksBySink(0, IID_IWbemObjectSink, pSink); return hRes; }
//***************************************************************************
//
//***************************************************************************
HRESULT CWbemNamespace::Exec_CancelProvAsyncCall( IWbemServices* pProv, IWbemObjectSink* pSink ) { // Call to the actual provider
HRESULT hRes = pProv->CancelAsyncCall( pSink ); return hRes; }
//***************************************************************************
//
// CWbemNamespace::Exec_PutInstance
//
// Actually stores the instance in the database. If the class is dynamic, the
// call is propagated to the provider.
// Raises instance creation or modification event.
//
// Parameters and return values are exacly the same as those for PutInstance
// as described in help
//
//***************************************************************************
HRESULT CWbemNamespace::Exec_PutInstance( IWbemClassObject* pInst, long lFlags, IWbemContext* pCtx, CBasicObjectSink* pSink ) { TIMETRACE(TimeTraces::PutInstance); HRESULT hRes = CheckNs(); if (FAILED(hRes)) return hRes;
if (NULL == pSink) return WBEM_E_INVALID_PARAMETER; if(pInst == NULL) return pSink->Return(WBEM_E_INVALID_PARAMETER);
COperationError OpInfo(pSink, L"PutInstance", L""); if (!OpInfo.IsOk()) return pSink->Return(WBEM_E_OUT_OF_MEMORY);
CWbemObject *pObj = (CWbemObject *) pInst; HRESULT hres;
_variant_t v; hRes = pObj->Get(L"__RELPATH", 0, &v, NULL, NULL); if (FAILED(hRes)) return OpInfo.ErrorOccurred(hRes); if(VT_BSTR == V_VT(&v)) { if (wcslen_max(V_BSTR(&v),g_PathLimit) > g_PathLimit) return OpInfo.ErrorOccurred(WBEM_E_QUOTA_VIOLATION); }
if (!pObj->IsInstance()) return OpInfo.ErrorOccurred(WBEM_E_INVALID_OBJECT);
if (!pObj->IsKeyed()) return OpInfo.ErrorOccurred(WBEM_E_NO_KEY);
if (pObj->IsLimited()) return OpInfo.ErrorOccurred(WBEM_E_INVALID_OBJECT);
if (pObj->IsClientOnly()) return OpInfo.ErrorOccurred(WBEM_E_INVALID_OBJECT);
// Check if localization bits are set, and if so, that the
// AMENDED_QUALIFIERS flag was specified.
if ( ((CWbemObject*) pObj)->IsLocalized() && !( lFlags & WBEM_FLAG_USE_AMENDED_QUALIFIERS ) ) { return OpInfo.ErrorOccurred( WBEM_E_AMENDED_OBJECT ); }
if((lFlags & WBEM_FLAG_UPDATE_ONLY) == 0) { // Make sure that put extensions are not used without UPDATE_ONLY
// ==============================================================
BOOL bExtended; hres = GetContextBoolean(pCtx, L"__PUT_EXTENSIONS", &bExtended); if(FAILED(hres) || bExtended) return OpInfo.ErrorOccurred(WBEM_E_INVALID_CONTEXT); }
BSTR strPropName = NULL; CSysFreeMeRef fmref(strPropName); if(!pObj->ValidateRange(&strPropName)) { OpInfo.SetParameterInfo(strPropName); // throws
return OpInfo.ErrorOccurred(WBEM_E_INVALID_PROPERTY); }
// Build the key string.
// =====================
CVar vClass; hres = pObj->GetClassName(&vClass); // throw
if (FAILED(hres)) return OpInfo.ErrorOccurred(WBEM_E_INVALID_OBJECT);
OpInfo.SetParameterInfo(vClass.GetLPWSTR()); // throws
// Get the class definition
// ========================
IWbemClassObject* pErrorObj = NULL; IWbemClassObject* pClassObj = NULL; hres = Exec_GetObjectByPath(vClass.GetLPWSTR(), 0, pCtx,&pClassObj, &pErrorObj); CReleaseMe rmErrObj(pErrorObj); CReleaseMe rm1(pClassObj); if(hres == WBEM_E_NOT_FOUND) hres = WBEM_E_INVALID_CLASS;
if(FAILED(hres)) return OpInfo.ErrorOccurred(hres, pErrorObj);
CWbemClass *pClassDef = (CWbemClass*)pClassObj;
// Dont allow write of old security classes. This prevents
// a nefarious user from trying to slip in some extra rights
if (wbem_wcsicmp(vClass.GetLPWSTR(), L"__NTLMUser") == 0 || wbem_wcsicmp(vClass.GetLPWSTR(), L"__NTLMGroup") == 0) { if (!Allowed(WRITE_DAC)) return OpInfo.ErrorOccurred(WBEM_E_ACCESS_DENIED); if((lFlags & WBEM_FLAG_ONLY_STATIC) == 0) { return PutSecurityClassInstances(vClass.GetLPWSTR(), pInst , pSink, pCtx, lFlags); } }
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Dont allow write on the __thisnamespace instance -- except during an upgrade in setup
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if (wbem_wcsicmp(vClass.GetLPWSTR(), L"__thisnamespace") == 0 && !IsNtSetupRunning()) { return OpInfo.ErrorOccurred(WBEM_E_INVALID_OPERATION); }
// Make sure that the instance and the class match
// ===============================================
// SJS - Amendment is the same as Abstract
if( pClassDef->IsAmendment() || pClassDef->IsAbstract() || !pClassDef->IsKeyed() ) { return OpInfo.ErrorOccurred(WBEM_E_INVALID_OPERATION); }
if(!((CWbemInstance*)pObj)->IsInstanceOf(pClassDef)) // trow
{ return OpInfo.ErrorOccurred(WBEM_E_INVALID_CLASS); }
// Verify provider validity
// ========================
// Only administrators can change provider registration
// RAID# 566241
// ==================================
if(pObj->InheritsFrom(L"__Provider") == S_OK || pObj->InheritsFrom(L"__ProviderRegistration") == S_OK) { HANDLE hAccess; hres = GetAccessToken(hAccess); if ( FAILED (hres) ) { if ( hres != 0x80041007 ) { return OpInfo.ErrorOccurred(WBEM_E_ACCESS_DENIED); } } else { if ( !IsAdmin(hAccess)) { CloseHandle ( hAccess ); return OpInfo.ErrorOccurred(WBEM_E_ACCESS_DENIED); } CloseHandle ( hAccess ); } }
// While the class may not be dynamically provided, some of the
// properties might be.
// ============================================================
hres = GetOrPutDynProps(pObj, PUT, pClassDef->IsDynamic()); if(FAILED(hres)) { ERRORTRACE((LOG_WBEMCORE, "Failed to pre-process an instance of %S using " "a property provider. Error code: %X\n", vClass.GetLPWSTR(), hres)); }
// Recursively Put in all the right places
// ======================================
CCombiningSink* pCombSink = new CCombiningSink(OpInfo.GetSink()); if(pCombSink == NULL) return OpInfo.ErrorOccurred(WBEM_E_OUT_OF_MEMORY); pCombSink->AddRef(); CReleaseMe rm2(pCombSink);
return RecursivePutInstance((CWbemInstance*)pObj, pClassDef, lFlags, pCtx, pCombSink, TRUE); }
//***************************************************************************
//
//***************************************************************************
HRESULT CWbemNamespace::RecursivePutInstance( CWbemInstance* pInst, CWbemClass* pClassDef, long lFlags, IWbemContext* pCtx, CBasicObjectSink* pSink, BOOL bLast ) { HRESULT hRes;
// See if any action is required at this level
// ===========================================
if (pClassDef->IsAbstract() || pClassDef->IsAmendment() || !pClassDef->IsKeyed()) return WBEM_S_FALSE;
// See if we need to go up
// =======================
BOOL bParentTookCareOfItself = TRUE;
if (pClassDef->IsDynamic()) { // Get the parent class
// ====================
CVar vParentName; pClassDef->GetSuperclassName(&vParentName); if (!vParentName.IsNull()) { IWbemClassObject* pParentClass = NULL; IWbemClassObject* pErrorObj = NULL; hRes = Exec_GetObjectByPath(vParentName.GetLPWSTR(), 0, pCtx,&pParentClass, &pErrorObj); CReleaseMe rm1(pParentClass); CReleaseMe rm2(pErrorObj); if (FAILED(hRes)) { pSink->Return(hRes, pErrorObj); return hRes; }
// Get it to put it's portion
// ==========================
hRes = RecursivePutInstance(pInst, (CWbemClass*)pParentClass,lFlags, pCtx, pSink, FALSE); if(FAILED(hRes)) return hRes;
if(hRes == WBEM_S_FALSE) bParentTookCareOfItself = FALSE; } }
// Parent Puts have been taken care of. Call it on our own class.
// ==============================================================
// Convert the instance to the right class
// =======================================
CWbemInstance* pNewInst = NULL; pInst->ConvertToClass(pClassDef, &pNewInst); CReleaseMe rm1((IWbemClassObject*)pNewInst);
if (pNewInst == NULL) { ERRORTRACE((LOG_WBEMCORE, "Failed to convert an instance to a base class\n")); return pSink->Return(WBEM_E_CRITICAL_ERROR); }
if (pClassDef->IsDynamic()) { // Check if we need to do a put at this level
// ==========================================
if (!bLast && (lFlags & WBEM_FLAG_UPDATE_ONLY)) { hRes = IsPutRequiredForClass(pClassDef, pInst, pCtx, bParentTookCareOfItself); if (FAILED(hRes)) return pSink->Return(hRes); if (hRes == WBEM_S_FALSE) { // No need to put this class
// =========================
return pSink->Return(WBEM_S_NO_ERROR); } }
// Get the provider name.
// ======================
CVar vProv; hRes = pClassDef->GetQualifier(L"Provider", &vProv); if (FAILED(hRes) || vProv.GetType() != VT_BSTR) { return pSink->Return(WBEM_E_INVALID_PROVIDER_REGISTRATION); }
// Access the provider cache. First check permission
// ==================================================
if (!Allowed(WBEM_WRITE_PROVIDER)) return pSink->Return(WBEM_E_ACCESS_DENIED);
CSynchronousSink* pSyncSink = CSynchronousSink::Create(pSink); if(pSyncSink == NULL) return pSink->Return(WBEM_E_OUT_OF_MEMORY); pSyncSink->AddRef(); CReleaseMe rmSync(pSyncSink);
IWbemServices *pProv = 0; if(m_pProvFact == NULL) return pSink->Return(WBEM_E_CRITICAL_ERROR);
WmiInternalContext t_InternalContext ; ZeroMemory ( & t_InternalContext , sizeof ( t_InternalContext ) ) ; // SEC:REVIEWED 2002-03-22 : OK
hRes = m_pProvFact->GetProvider(
t_InternalContext , 0, // lFlags
pCtx, 0, m_wszUserName, m_wsLocale, 0, // IWbemPath pointer
vProv, // Provider
IID_IWbemServices, (LPVOID *) &pProv );
if (FAILED(hRes)) return pSink->Return(hRes);
CReleaseMe _(pProv);
pProv->PutInstanceAsync(pNewInst, lFlags& ~WBEM_FLAG_USE_AMENDED_QUALIFIERS, pCtx, pSyncSink);
pSyncSink->Block();
IWbemClassObject* pErrorObj = NULL; BSTR str; pSyncSink->GetStatus(&hRes, &str, &pErrorObj); CSysFreeMe sfm(str); CReleaseMe rmErrObj(pErrorObj); rmSync.release();
// It is ok if the upper levels report "provider not capable".
// ===========================================================
if (!bLast && hRes == WBEM_E_PROVIDER_NOT_CAPABLE) hRes = 0;
if (FAILED(hRes)) { COperationError OpInfo(pSink, L"PutInstance", L""); if (!OpInfo.IsOk()) return WBEM_E_OUT_OF_MEMORY;
OpInfo.ProviderReturned(vProv.GetLPWSTR(), hRes, pErrorObj); return hRes; } else if (str) { pSink->SetStatus(0, hRes, str, NULL); }
// Provider passes back NULL, we should construct the instance path and return to client
// NT RAID: 186286 [marioh]
// ======================================================================================
else { BSTR str = NULL; LPWSTR wszPath = pNewInst->GetRelPath(); if (wszPath ) { str = SysAllocString(wszPath); delete [] wszPath; }
pSink->SetStatus(0, hRes, str, NULL); SysFreeString(str); }
return WBEM_S_NO_ERROR; }
// The class is not dynamically provided.
// ======================================
hRes = ((CWbemInstance*)pNewInst)->PlugKeyHoles(); if (FAILED(hRes)) return pSink->Return(hRes);
// Get the path.
// =============
CVar vClass; hRes = pNewInst->GetClassName(&vClass); if (FAILED(hRes)) return pSink->Return(WBEM_E_OUT_OF_MEMORY);
WCHAR * ClassNameStr = vClass.GetLPWSTR();
// Check permissions for writes on system classes.
// ===============================================
bool derivedFromSys = false; HRESULT hr = IsDerivedFromSystem(*pNewInst, &derivedFromSys); if (FAILED(hr)) return pSink->Return(hr);
if (derivedFromSys) { if (!Allowed(WBEM_FULL_WRITE_REP)) return pSink->Return(WBEM_E_ACCESS_DENIED); } else if (!Allowed(WBEM_PARTIAL_WRITE_REP)) { return pSink->Return(WBEM_E_ACCESS_DENIED); }
CVARIANT v; hRes = pNewInst->Get(L"__RELPATH", 0, &v, 0, 0); if(FAILED(hRes)) return pSink->Return(hRes); if(v.GetType() != VT_BSTR) return pSink->Return(WBEM_E_CRITICAL_ERROR); // Set up a new per-task hook.
// ===========================
_IWmiCoreWriteHook *pHook = 0; hRes = m_pCoreSvc->NewPerTaskHook(&pHook); if (FAILED(hRes)) return pSink->Return(hRes); CReleaseMe _(pHook); HRESULT hHookResult = 0;
// See if the instance already exists.
// ===================================
IWbemClassObject *pExistingObject = 0; hRes = CRepository::GetObject(m_pSession, m_pScopeHandle, v.GetStr(),0, &pExistingObject); CReleaseMe _2(pExistingObject);
if (FAILED(hRes)) { // If we here, we failed to get it from the repository. Thus, it needs to be created from scratch.
// ================================================================================================
// Remove all the amended qualifiers
// =================================
if (lFlags & WBEM_FLAG_USE_AMENDED_QUALIFIERS ) { int nRes = SplitLocalized(pNewInst); if (FAILED(nRes)) return pSink->Return(nRes); }
if((lFlags & WBEM_MASK_CREATE_UPDATE) == WBEM_FLAG_UPDATE_ONLY) { return pSink->Return(WBEM_E_NOT_FOUND); }
// As a special case, see if the object is
// of class <__NAMESPACE>. If so, create a new namespace
// for it.
// ======================================================
if ((wbem_wcsicmp(vClass.GetLPWSTR(), L"__NAMESPACE") == 0) || (CRepository::InheritsFrom(m_pSession, m_pNsHandle, L"__NAMESPACE", vClass.GetLPWSTR()) == 0)) { hRes = CreateNamespace(pNewInst); if (FAILED(hRes)) return pSink->Return(hRes); } // Not a __NAMESPACE or derivative.
// ================================
else { // If here, the object didn't already exist in the repository, so we
// can add it to the database.
// ==================================================================
// Check if this instance makes any sense to
// hook callbacks.
// =========================================
hRes = DecorateObject(pNewInst); if (FAILED(hRes)) return pSink->Return(hRes); IWbemClassObject* pInstObj = pNewInst; IWbemClassObject* pOldObj = 0;
if (pHook) { // If there are hooks, try them and note whether callback is required.
// ===================================================================
hHookResult = pHook->PrePut(WBEM_FLAG_INST_PUT, lFlags, pCtx, 0, m_pThisNamespace, ClassNameStr, pNewInst ); }
if (FAILED(hHookResult)) { return pSink->Return(hHookResult); }
if (hHookResult == WBEM_S_POSTHOOK_WITH_BOTH) { CRepository::GetObject(m_pSession, m_pNsHandle, v.GetStr(), 0, &pOldObj); }
// Actually create it in the database
// ==================================
hRes = CRepository::PutObject(m_pSession, m_pScopeHandle, IID_IWbemClassObject, LPVOID(pNewInst), DWORD(lFlags));
if (pHook) pHook->PostPut(WBEM_FLAG_INST_PUT, hRes, pCtx, 0, m_pThisNamespace, ClassNameStr, pNewInst, (_IWmiObject *) pOldObj);
delete pOldObj;
if (FAILED(hRes)) { return pSink->Return(hRes); } } }
// If here, the object was already in the repository and requires updating.
// ========================================================================
else { if((lFlags & WBEM_MASK_CREATE_UPDATE) == WBEM_FLAG_CREATE_ONLY) { return pSink->Return(WBEM_E_ALREADY_EXISTS); }
// Remove all the amended qualifiers
// =================================
if (lFlags & WBEM_FLAG_USE_AMENDED_QUALIFIERS ) { int nRes = SplitLocalized(pNewInst, (CWbemObject *) pExistingObject); if (FAILED(nRes)) { return pSink->Return(nRes); } }
// Check if this update makes any sense to the ESS
// ===============================================
hRes = DecorateObject(pNewInst); if (FAILED(hRes)) return pSink->Return(hRes); IWbemClassObject* pInstObj = pNewInst;
// Check pre-hook.
// ===============
if (pHook) { // If there are hooks, try them and note whether callback is required.
// ===================================================================
hHookResult = pHook->PrePut(WBEM_FLAG_INST_PUT, lFlags, pCtx, 0, m_pThisNamespace, ClassNameStr, pNewInst ); }
if (FAILED(hHookResult)) return pSink->Return(hHookResult);
// Actually create it in the database
// ==================================
hRes = CRepository::PutObject(m_pSession, m_pScopeHandle, IID_IWbemClassObject, LPVOID(pNewInst), DWORD(lFlags));
// Post put.
// =========
if (pHook) pHook->PostPut(WBEM_FLAG_INST_PUT, hRes, pCtx, 0, m_pThisNamespace, ClassNameStr, pNewInst, (_IWmiObject *) pExistingObject);
if (FAILED(hRes)) return pSink->Return(hRes); }
// Assign appropriate value to the path
// ====================================
LPWSTR wszPath = pNewInst->GetRelPath(); BSTR str = SysAllocString(wszPath); delete [] wszPath;
pSink->SetStatus(0, WBEM_S_NO_ERROR, str, NULL); SysFreeString(str);
return WBEM_NO_ERROR; }
//***************************************************************************
//
//***************************************************************************
HRESULT CWbemNamespace::CreateNamespace(CWbemInstance *pNewInst) { //
// internal interface throws
//
CVar vNsName; HRESULT hRes = pNewInst->GetProperty(L"Name", &vNsName); if (FAILED(hRes) || vNsName.IsNull()) { return WBEM_E_INVALID_NAMESPACE; }
// verify that this name is valid
// ==============================
if (!IsValidElementName(vNsName.GetLPWSTR(),g_PathLimit-NAMESPACE_ADJUSTMENT)) { return WBEM_E_INVALID_NAMESPACE; }
if (!Allowed(WBEM_FULL_WRITE_REP)) { return WBEM_E_ACCESS_DENIED; }
//Get a new session for transactioning purposes...
IWmiDbSession *pSession = NULL; IWmiDbSessionEx *pSessionEx = NULL;
hRes = CRepository::GetNewSession(&pSession); if (FAILED(hRes)) return hRes;
//Get an EX version that supports transactioning...
pSession->QueryInterface(IID_IWmiDbSessionEx, (void**)&pSessionEx); if (pSessionEx) { pSession->Release(); pSession = pSessionEx; } CReleaseMe relMe1(pSession);
//If we have transactionable session, use it!
if (pSessionEx) { hRes = pSessionEx->BeginWriteTransaction(0); if (FAILED(hRes)) { return hRes; } }
try { // Build the new namespace name.
// =============================
// Create the namespace
// =====================
if (SUCCEEDED(hRes)) hRes = CRepository::PutObject(pSession, m_pScopeHandle, IID_IWbemClassObject, LPVOID(pNewInst), 0);
// Set the default instances.
// ===============================
CWbemNamespace* pNewNs = NULL;
if (SUCCEEDED(hRes)) pNewNs = CWbemNamespace::CreateInstance();
if (SUCCEEDED(hRes) && pNewNs != NULL) { int iLen = 2; if(m_pThisNamespace) iLen += wcslen(m_pThisNamespace); // SEC:REVIEWED 2002-03-22 : OK; null terminator is there by prior precondition
if(vNsName.GetLPWSTR()) iLen += wcslen(vNsName.GetLPWSTR()); // SEC:REVIEWED 2002-03-22 : OK; provably ok or we couldn't be here
WCHAR * pTemp = new WCHAR[iLen]; if(pTemp) { *pTemp = L'\0'; if(m_pThisNamespace) { StringCchCopyW(pTemp, iLen, m_pThisNamespace); StringCchCatW(pTemp, iLen, L"\\"); } if(vNsName.GetLPWSTR()) StringCchCatW(pTemp, iLen, vNsName.GetLPWSTR());
//Initialize the namespace object
hRes = pNewNs->Initialize(pTemp,GetUserName(), 0, 0, FALSE, TRUE, // SEC:REVIEWED 2002-03-22 : OK
NULL, 0xFFFFFFFF, TRUE, pSession); delete pTemp; } else { hRes = WBEM_E_OUT_OF_MEMORY; }
if(SUCCEEDED(hRes)) { hRes = CRepository::EnsureNsSystemInstances(pSession, pNewNs->m_pNsHandle, pSession, m_pNsHandle); }
if (SUCCEEDED(hRes)) hRes = InitializeSD(pSession);
pNewNs->Release(); } else if (SUCCEEDED(hRes)) { hRes = WBEM_E_OUT_OF_MEMORY; } } catch (CX_MemoryException &) { hRes = WBEM_E_OUT_OF_MEMORY; } catch (...) { ExceptionCounter c; ERRORTRACE((LOG_WBEMCORE, "Namespace Creation of <%S> caused a very critical error!\n", vNsName.GetLPWSTR())); hRes = WBEM_E_CRITICAL_ERROR; } if (FAILED(hRes)) { ERRORTRACE((LOG_WBEMCORE, "Namespace Creation of <%S> caused an error <0x%X>!\n", vNsName.GetLPWSTR(), hRes)); if (pSessionEx) pSessionEx->AbortTransaction(0); } else { hRes = DecorateObject(pNewInst); if (FAILED(hRes)) { if (pSessionEx) pSessionEx->AbortTransaction(0); } else { if (pSessionEx) { hRes = pSessionEx->CommitTransaction(0); } } }
return hRes; }
//***************************************************************************
//
// CWbemNamespace::Exec_DeleteInstance
//
// Actually deletes the instance from the database. No instance provider
// support. Raises instance deletion event.
//
// Parameters and return values are exacly the same as those for DeleteInstance
// as described in help
//
//***************************************************************************
HRESULT CWbemNamespace::Exec_DeleteInstance( READONLY LPWSTR wszObjectPath, long lFlags, IWbemContext* pCtx, CBasicObjectSink* pSink ) { TIMETRACE(TimeTraces::DeleteInstance); return DeleteSingleInstance(wszObjectPath, lFlags, pCtx, pSink); }
//***************************************************************************
//
//***************************************************************************
//
HRESULT CWbemNamespace::DeleteSingleInstance( READONLY LPWSTR wszObjectPath, long lFlags, IWbemContext* pCtx, CBasicObjectSink* pSink ) { HRESULT hRes; int nRes;
COperationError OpInfo(pSink, L"DeleteInstance", wszObjectPath); if ( !OpInfo.IsOk() ) return WBEM_E_OUT_OF_MEMORY;
// Parse the object path to get the class involved.
// ================================================
ParsedObjectPath* pOutput = 0; CObjectPathParser p; int nStatus = p.Parse(wszObjectPath, &pOutput); OnDeleteObj<ParsedObjectPath*,CObjectPathParser, void (CObjectPathParser:: *)(ParsedObjectPath *pOutput), &CObjectPathParser::Free> FreeMe(&p,pOutput);
if (nStatus != 0 || !pOutput->IsInstance()) { return OpInfo.ErrorOccurred(WBEM_E_INVALID_OBJECT_PATH); }
// Exception for __WinMgmtIdentification
if (!wbem_wcsicmp(pOutput->m_pClass, L"__CIMOMIdentification") || !wbem_wcsicmp(pOutput->m_pClass, L"__SystemSecurity") || !wbem_wcsicmp(pOutput->m_pClass, L"__ADAPStatus" ) ) { return OpInfo.ErrorOccurred(WBEM_E_INVALID_OPERATION); }
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Dont allow deletion on the __thisnamespace instance
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if (wbem_wcsicmp(pOutput->m_pClass, L"__thisnamespace") == 0 ) { return OpInfo.ErrorOccurred(WBEM_E_INVALID_OPERATION); }
// Special case for the old security classes
// ==========================================
if (wbem_wcsicmp(pOutput->m_pClass, L"__NTLMUser") == 0 || wbem_wcsicmp(pOutput->m_pClass, L"__NTLMGroup") == 0) { if (!Allowed(WRITE_DAC)) { return OpInfo.ErrorOccurred(WBEM_E_ACCESS_DENIED); } if((lFlags & WBEM_FLAG_ONLY_STATIC) == 0) { return DeleteSecurityClassInstances(pOutput, pSink, pCtx,lFlags); } }
// As a special case, see if the object is
// of class <__NAMESPACE>. If so, (TEMP) disallow deletion.
// =========================================================
WString wsNamespaceName;
if (wbem_wcsicmp(pOutput->m_pClass, L"__NAMESPACE") == 0 || CRepository::InheritsFrom(m_pSession, m_pScopeHandle, L"__NAMESPACE", pOutput->m_pClass) == 0 )
{ if (!Allowed(WBEM_FULL_WRITE_REP)) { return OpInfo.ErrorOccurred(WBEM_E_ACCESS_DENIED); }
if (pOutput->m_dwNumKeys != 1) { return OpInfo.ErrorOccurred(WBEM_E_INVALID_OBJECT_PATH); }
KeyRef* pKey = pOutput->m_paKeys[0]; if (pKey->m_pName != NULL && wbem_wcsicmp(pKey->m_pName, L"name")) { return OpInfo.ErrorOccurred(WBEM_E_INVALID_OBJECT_PATH); }
if (V_VT(&pKey->m_vValue) != VT_BSTR) { return OpInfo.ErrorOccurred(WBEM_E_INVALID_OBJECT_PATH); }
// Prevent deletion of standard namespaces.
// ========================================
if (wbem_wcsicmp(m_pThisNamespace, L"ROOT") == 0) { BSTR pNs = V_BSTR(&pKey->m_vValue); if (!pNs) { return OpInfo.ErrorOccurred(WBEM_E_INVALID_OBJECT_PATH); } if (wbem_wcsicmp(pNs, L"SECURITY") == 0) { return OpInfo.ErrorOccurred(WBEM_E_ACCESS_DENIED); } if (wbem_wcsicmp(pNs, L"DEFAULT") == 0) { return OpInfo.ErrorOccurred(WBEM_E_ACCESS_DENIED); } }
// Set up hook.
// ============
_IWmiCoreWriteHook *pHook = 0; HRESULT hRes = m_pCoreSvc->NewPerTaskHook(&pHook); CReleaseMe _(pHook); HRESULT hHookResult = 0; LPWSTR pszClassName = 0; IWbemPath *pPath = 0;
CVectorDeleteMe<WCHAR> vdmClassName(&pszClassName);
if (pHook) { // Parse the object path.
// ======================
hRes = m_pCoreSvc->CreatePathParser(0, &pPath); if (FAILED(hRes)) { return OpInfo.ErrorOccurred(hRes); }
CReleaseMe _3Path(pPath);
hRes = pPath->SetText(WBEMPATH_CREATE_ACCEPT_ALL, wszObjectPath); if (FAILED(hRes)) { return OpInfo.ErrorOccurred(hRes); }
ULONG uBuf = 0; hRes = pPath->GetClassName(&uBuf, 0); if (FAILED(hRes)) { return OpInfo.ErrorOccurred(hRes); }
pszClassName = new wchar_t[uBuf+1]; if (pszClassName == 0) { return OpInfo.ErrorOccurred(WBEM_E_OUT_OF_MEMORY); }
hRes = pPath->GetClassName(&uBuf, pszClassName); if (FAILED(hRes)) { return OpInfo.ErrorOccurred(hRes); }
// If there are hooks, try them and note whether callback is required.
// ===================================================================
hHookResult = pHook->PreDelete(WBEM_FLAG_INST_DELETE, lFlags, pCtx, pPath, m_pThisNamespace, pszClassName);
if (FAILED(hHookResult)) { return OpInfo.ErrorOccurred(hHookResult); }
pPath->AddRef(); }
CReleaseMe _2Path(pPath);
// Ensure the object can be reached so that we can delete it.
// ==========================================================
IWbemClassObject *pExistingObject = 0; hRes = CRepository::GetObject(m_pSession, m_pScopeHandle, wszObjectPath, 0, &pExistingObject);
if (FAILED(hRes)) { return OpInfo.ErrorOccurred(hRes); }
CReleaseMe _2(pExistingObject);
if (hRes == WBEM_S_NO_ERROR) // new test
{ // Check if we may
// ===============
if (!Allowed(WBEM_FULL_WRITE_REP)) { return OpInfo.ErrorOccurred(WBEM_E_ACCESS_DENIED); }
// Go ahead and try the deletion.
// ==============================
WString sNamespace = "__Namespace='"; sNamespace += V_BSTR(&pKey->m_vValue); sNamespace += "'";
hRes = CRepository::DeleteByPath(m_pSession, m_pScopeHandle, LPWSTR(sNamespace), 0);
// Call post hook.
// ===============
if (pHook) pHook->PostDelete(WBEM_FLAG_INST_DELETE, hRes, pCtx, pPath, m_pThisNamespace, pszClassName, (_IWmiObject *) pExistingObject);
// Decide what to do if things didn't work out.
// ============================================
if (FAILED(hRes)) { return OpInfo.ErrorOccurred(hRes); } } else { return OpInfo.ErrorOccurred(hRes); }
wsNamespaceName = V_BSTR(&pKey->m_vValue);
return OpInfo.ErrorOccurred(WBEM_S_NO_ERROR); }
// See if the class is dynamic
// ===========================
CWbemObject *pClassDef = 0; IWbemClassObject* pErrorObj = NULL; IWbemClassObject* pClassObj = NULL;
HRESULT hres = Exec_GetObjectByPath(pOutput->m_pClass, 0, pCtx,&pClassObj, &pErrorObj); CReleaseMe rmErrObj(pErrorObj); CReleaseMe rmClsDef(pClassObj);
if(hres == WBEM_E_NOT_FOUND) hres = WBEM_E_INVALID_CLASS;
if(FAILED(hres)) { OpInfo.ErrorOccurred(hres, pErrorObj); return WBEM_S_NO_ERROR; } pClassDef = (CWbemObject*)pClassObj;
CVar vDynFlag; hres = pClassDef->GetQualifier(L"Dynamic", &vDynFlag); if (SUCCEEDED(hres) && vDynFlag.GetType() == VT_BOOL && vDynFlag.GetBool()) { // Get the provider name.
CVar vProv; hres = pClassDef->GetQualifier(L"Provider", &vProv); if (FAILED(hres) || vProv.GetType() != VT_BSTR) { return OpInfo.ErrorOccurred(WBEM_E_INVALID_PROVIDER_REGISTRATION); }
if (!Allowed(WBEM_WRITE_PROVIDER)) return OpInfo.ErrorOccurred(WBEM_E_ACCESS_DENIED);
// Access the provider cache.
// ==========================
IWbemServices *pProv = 0; HRESULT hRes; if(m_pProvFact == NULL) return OpInfo.ErrorOccurred(WBEM_E_CRITICAL_ERROR);
WmiInternalContext t_InternalContext ; ZeroMemory ( & t_InternalContext , sizeof ( t_InternalContext ) );
hRes = m_pProvFact->GetProvider(t_InternalContext , 0, // lFlags
pCtx, 0, m_wszUserName, m_wsLocale, 0, // IWbemPath pointer
vProv, // Provider
IID_IWbemServices, (LPVOID *) &pProv);
if (FAILED(hRes)) { return OpInfo.ErrorOccurred(hRes); }
CReleaseMe rmProv(pProv);
hRes = pProv->DeleteInstanceAsync( wszObjectPath, lFlags& ~WBEM_FLAG_USE_AMENDED_QUALIFIERS, pCtx, OpInfo.GetSink());
return WBEM_S_NO_ERROR; }
// The class is not dynamically provided.
// ======================================
// Only administrators can change provider registration
// RAID# 566241
// ==================================
if(pClassDef->InheritsFrom(L"__Provider") == S_OK || pClassDef->InheritsFrom(L"__ProviderRegistration") == S_OK) { HANDLE hAccess; hres = GetAccessToken (hAccess); if ( FAILED (hres) ) { if ( hres != 0x80041007 ) { return OpInfo.ErrorOccurred(WBEM_E_ACCESS_DENIED); } } else { if ( !IsAdmin(hAccess)) { CloseHandle ( hAccess ); return OpInfo.ErrorOccurred(WBEM_E_ACCESS_DENIED); } CloseHandle ( hAccess ); } }
bool derivedFromSys = false; HRESULT hr = IsDerivedFromSystem(*pClassDef, &derivedFromSys); if (FAILED(hr)) return pSink->Return(hr);
if (derivedFromSys) { if (!Allowed(WBEM_FULL_WRITE_REP)) return pSink->Return(WBEM_E_ACCESS_DENIED); } else if (!Allowed(WBEM_PARTIAL_WRITE_REP)) { return pSink->Return(WBEM_E_ACCESS_DENIED); }
rmClsDef.release();
// If here, it is a normal object. First retrieve
// the object for the event subsystem, then go ahead and delete it.
// ================================================================
// Prehook.
// ========
_IWmiCoreWriteHook *pHook = 0; hRes = m_pCoreSvc->NewPerTaskHook(&pHook); if (FAILED(hRes)) return OpInfo.ErrorOccurred(hRes); CReleaseMe rmHook(pHook); HRESULT hHookResult = 0; LPWSTR pszClassName = 0; IWbemPath *pPath = 0; CReleaseMeRef<IWbemPath*> rmPath(pPath); CVectorDeleteMe<WCHAR> vdmClassName(&pszClassName);
if (pHook) { // Parse the object path.
hRes = m_pCoreSvc->CreatePathParser(0, &pPath); if (FAILED(hRes)) return OpInfo.ErrorOccurred(hRes);
hRes = pPath->SetText(WBEMPATH_CREATE_ACCEPT_ALL, wszObjectPath); if (FAILED(hRes)) return OpInfo.ErrorOccurred(hRes);
ULONG uBuf = 0; hRes = pPath->GetClassName(&uBuf, 0); if (FAILED(hRes)) return OpInfo.ErrorOccurred(hRes);
pszClassName = new wchar_t[uBuf+1]; if (pszClassName == 0) return OpInfo.ErrorOccurred(WBEM_E_OUT_OF_MEMORY);
hRes = pPath->GetClassName(&uBuf, pszClassName); if (FAILED(hRes)) return OpInfo.ErrorOccurred(hRes);
// If there are hooks, try them and note whether callback is required.
// ===================================================================
hHookResult = pHook->PreDelete(WBEM_FLAG_INST_DELETE, lFlags, pCtx, pPath,m_pThisNamespace, pszClassName);
if (FAILED(hHookResult)) return OpInfo.ErrorOccurred(hHookResult);
}
// If anybody wants to see the old object, get it.
IWbemClassObject *pDoomedInstance = NULL ; if (hHookResult == WBEM_S_POSTHOOK_WITH_OLD) { hRes = CRepository::GetObject(m_pSession, m_pScopeHandle, wszObjectPath,0, &pDoomedInstance); if (FAILED(hRes)) return OpInfo.ErrorOccurred(hRes); } CReleaseMe _Doomed (pDoomedInstance) ;
hRes = CRepository::DeleteByPath(m_pSession, m_pScopeHandle, wszObjectPath, 0); // new
// Posthook.
if (pHook) pHook->PostDelete(WBEM_FLAG_INST_DELETE, hRes, pCtx, pPath, m_pThisNamespace, pszClassName, (_IWmiObject *) pDoomedInstance);
if ( FAILED (hRes) ) return OpInfo.ErrorOccurred(hRes); return OpInfo.ErrorOccurred(WBEM_NO_ERROR); }
//***************************************************************************
//
// CWbemNamespace::Exec_CreateInstanceEnum
//
// Actually creates the enumerator for all instances of a given class,
// optionally recursively. Interacts with instance providers. Class provider
// interaction works, but is sparsely tested.
//
// Parameters and return values are exacly the same as those for
// CreateInstanceEnum as described in help
//
//***************************************************************************
HRESULT CWbemNamespace::Exec_CreateInstanceEnum( LPWSTR wszClass, long lFlags, IWbemContext* pCtx, CBasicObjectSink* pSink ) { TIMETRACE(TimeTraces::CreateInstanceEnum);
COperationError OpInfo(pSink, L"CreateInstanceEnum", wszClass); if ( !OpInfo.IsOk() ) return WBEM_E_OUT_OF_MEMORY;
// Make sure the name of the class is a name
// =========================================
if(wcschr(wszClass, L':')) return OpInfo.ErrorOccurred(WBEM_E_INVALID_CLASS);
// Create equivalent query
// =======================
WString wsQuery; wsQuery += L"select * from "; wsQuery += wszClass;
if((lFlags & WBEM_MASK_DEPTH) == WBEM_FLAG_SHALLOW) { wsQuery += L" where __CLASS = \""; wsQuery += wszClass; wsQuery += L"\""; }
CErrorChangingSink* pErrSink = new CErrorChangingSink(OpInfo.GetSink(),WBEM_E_INVALID_QUERY, WBEM_E_INVALID_CLASS); if(pErrSink == NULL) return OpInfo.ErrorOccurred(WBEM_E_OUT_OF_MEMORY); CReleaseMe rmErrorChange(pErrSink);
// Execute it
CQueryEngine::ExecQuery(this,L"WQL",(LPWSTR)wsQuery,lFlags,pCtx,pErrSink);
return WBEM_S_NO_ERROR; }
//***************************************************************************
//
//***************************************************************************
/*
void CWbemNamespace::SetUserName(LPWSTR wName) { try { delete m_wszUserName; m_wszUserName = (wName) ? Macro_CloneLPWSTR(wName):NULL; } catch(...) { ExceptionCounter c; m_wszUserName = 0; } } */
//***************************************************************************
//
//***************************************************************************
HRESULT CWbemNamespace::GetObjectByFullPath( READONLY LPWSTR wszObjectPath, IWbemPath * pOutput, long lFlags, IWbemContext* pCtx, CBasicObjectSink* pSink ) {
// Get the namespace part of the path
DWORD dwSizeNamespace = 0; HRESULT hres = pOutput->GetText(WBEMPATH_GET_NAMESPACE_ONLY, &dwSizeNamespace, NULL); if(FAILED(hres)) return hres;
LPWSTR wszNewNamespace = new WCHAR[dwSizeNamespace]; if(wszNewNamespace == NULL) return WBEM_E_OUT_OF_MEMORY; CDeleteMe<WCHAR> dm1(wszNewNamespace);
hres = pOutput->GetText(WBEMPATH_GET_NAMESPACE_ONLY, &dwSizeNamespace, wszNewNamespace); if(FAILED(hres)) return hres;
// Get the relative part of the path
DWORD dwSizeRelative = 0; hres = pOutput->GetText(WBEMPATH_GET_RELATIVE_ONLY, &dwSizeRelative, NULL); if(FAILED(hres)) return hres;
LPWSTR wszRelativePath = new WCHAR[dwSizeRelative]; if(wszRelativePath == NULL) return WBEM_E_OUT_OF_MEMORY; CDeleteMe<WCHAR> dm2(wszRelativePath);
hres = pOutput->GetText(WBEMPATH_GET_RELATIVE_ONLY, &dwSizeRelative, wszRelativePath); if(FAILED(hres)) return hres;
if (pOutput->IsLocal(ConfigMgr::GetMachineName())) { // In win2k, we allowed \\.\root\default:whatever, but not root\default:whatever
// So, the following additional test was added
ULONGLONG uFlags; hres = pOutput->GetInfo(0, &uFlags); if(SUCCEEDED(hres)) { if((uFlags & WBEMPATH_INFO_PATH_HAD_SERVER) == 0) return pSink->Return(WBEM_E_INVALID_OBJECT_PATH); }
bool bAlreadyAuthenticated = (m_dwSecurityFlags & SecFlagWin9XLocal) != 0; CWbemNamespace* pNewLocal = CWbemNamespace::CreateInstance(); if(pNewLocal == NULL) return WBEM_E_OUT_OF_MEMORY; hres = pNewLocal->Initialize(wszNewNamespace, m_wszUserName, (bAlreadyAuthenticated) ? m_dwSecurityFlags : 0, (bAlreadyAuthenticated) ? m_dwPermission : 0, m_bForClient, false, m_pszClientMachineName, m_dwClientProcessID, FALSE,NULL); if (FAILED(hres)) { pNewLocal->Release(); return hres; } else if (pNewLocal->GetStatus()) { hres = pNewLocal->GetStatus(); pNewLocal->Release(); return hres; }
// check for security if this isnt the local 9x case
if(!bAlreadyAuthenticated) { DWORD dwAccess = pNewLocal->GetUserAccess(); if((dwAccess & WBEM_ENABLE) == 0) { delete pNewLocal; return WBEM_E_ACCESS_DENIED; } else pNewLocal->SetPermissions(dwAccess); }
if(pNewLocal->GetStatus()) { hres = pNewLocal->GetStatus(); delete pNewLocal; return pSink->Return(hres); }
#if 0
pNewLocal->AddRef(); #endif
pNewLocal->SetLocale(GetLocale());
hres = pNewLocal->Exec_GetObject(wszRelativePath, lFlags, pCtx, pSink); pNewLocal->Release(); return hres; } else { // Disable remote retrieval for V1
// ===============================
return pSink->Return(WBEM_E_NOT_SUPPORTED); } }
//***************************************************************************
//
// CWbemNamespace::Exec_GetObjectByPath
//
// Actually retrieves an object (a class or an instance) from the database.
// Interacts properly with class and instance providers and uses property
// providers for post-processing (See GetOrPutDynProps).
//
// Parameters and return values are exacly the same as those for GetObject
// as described in help
//
//***************************************************************************
HRESULT CWbemNamespace::Exec_GetObjectByPath( READONLY LPWSTR wszObjectPath, long lFlags, IWbemContext* pCtx, NEWOBJECT IWbemClassObject** ppObj, NEWOBJECT IWbemClassObject** ppErrorObj ) { TIMETRACE(TimeTraces::GetObjectByPath); HRESULT hres = WBEM_S_NO_ERROR;
CSynchronousSink* pSyncSink = CSynchronousSink::Create(); if(pSyncSink == NULL) return WBEM_E_OUT_OF_MEMORY; pSyncSink->AddRef(); IWbemClassObject* pErrorObj = NULL; IWbemClassObject* pObj = NULL;
hres = Exec_GetObject(wszObjectPath, lFlags, pCtx, pSyncSink); if (SUCCEEDED(hres)) { pSyncSink->Block(); pSyncSink->GetStatus(&hres, NULL, &pErrorObj);
if(SUCCEEDED(hres)) { if(pSyncSink->GetObjects().GetSize() < 1) { pSyncSink->Release(); ERRORTRACE((LOG_WBEMCORE, "Sync sink returned success with no objects!\n")); return WBEM_E_CRITICAL_ERROR; } pObj = pSyncSink->GetObjects()[0]; pObj->AddRef(); } }
pSyncSink->Release();
if(ppObj) *ppObj = pObj; else if(pObj) pObj->Release();
if(ppErrorObj) *ppErrorObj = pErrorObj; else if(pErrorObj) pErrorObj->Release();
return hres; }
//***************************************************************************
//
//***************************************************************************
HRESULT CWbemNamespace::Exec_GetObject( READONLY LPWSTR wszObjectPath, long lFlags, IWbemContext* pCtx, CBasicObjectSink* pSink) {
TIMETRACE(TimeTraces::GetObject); // Create a sink that will merge the localized qualifiers
// over the top of the default qualifiers (if specified)
// ======================================================
CLocaleMergingSink *pLocaleSink = NULL;
HRESULT hres = WBEM_S_NO_ERROR; if (wszObjectPath && wszObjectPath[0] && wszObjectPath[0] != L'_') // SEC:REVIEWED 2002-03-22 : OK; prior testing ensures that this is valid
{ if ((lFlags & WBEM_FLAG_USE_AMENDED_QUALIFIERS)) { pLocaleSink = new CLocaleMergingSink(pSink, m_wsLocale, m_pThisNamespace); if(pLocaleSink == NULL) return pSink->Return(WBEM_E_OUT_OF_MEMORY); else { pLocaleSink->AddRef(); pSink = pLocaleSink; } } } CReleaseMe rm(pLocaleSink);
COperationError OpInfo(pSink, L"GetObject", wszObjectPath?wszObjectPath:L""); if (!OpInfo.IsOk()) return pSink->Return(WBEM_E_OUT_OF_MEMORY);
// Check if the path is NULL --- that's valid
// ==========================================
if (wszObjectPath == NULL || wszObjectPath[0] == 0) // SEC:REVIEWED 2002-03-22 : OK; null terminator provably exists
{ //
// BUGBUG consider using CoCreateInstance instead of new CWbemClass
//
CWbemClass * pNewObj = new CWbemClass; if(NULL == pNewObj) return OpInfo.ErrorOccurred(WBEM_E_OUT_OF_MEMORY); CReleaseMe rm_((IWbemClassObject*)pNewObj); hres = pNewObj->InitEmpty(0); if (FAILED(hres)) return OpInfo.ErrorOccurred(hres);
IWbemClassObject* pObj = pNewObj; pSink->Indicate(1, &pObj); return OpInfo.ErrorOccurred(WBEM_NO_ERROR); }
// here we are sure the path is not null
if (wcslen_max(wszObjectPath,g_PathLimit) > g_PathLimit) return OpInfo.ErrorOccurred(WBEM_E_QUOTA_VIOLATION);
// Parse the object path to get the class involved.
// ================================================
IWbemPath *pPath = ConfigMgr::GetNewPath(); if (pPath == 0) { return OpInfo.ErrorOccurred(WBEM_E_OUT_OF_MEMORY); }
CReleaseMe _1(pPath); hres = pPath->SetText(WBEMPATH_CREATE_ACCEPT_ALL, wszObjectPath); if (FAILED(hres)) { return OpInfo.ErrorOccurred(WBEM_E_INVALID_OBJECT_PATH); }
ULONGLONG uResponse; hres = pPath->GetInfo(0, &uResponse); if (FAILED(hres) || ( (uResponse & WBEMPATH_INFO_IS_INST_REF) == 0 && (uResponse & WBEMPATH_INFO_IS_CLASS_REF) == 0)) { return OpInfo.ErrorOccurred(WBEM_E_INVALID_OBJECT_PATH); }
if (!pPath->IsRelative(ConfigMgr::GetMachineName(), m_pThisNamespace)) { // This path points to another namespace. Delegate to it instead
// =============================================================
hres = GetObjectByFullPath(wszObjectPath, pPath, lFlags, pCtx, OpInfo.GetSink());
return OpInfo.ErrorOccurred(hres); }
BOOL bInstance = (uResponse & WBEMPATH_INFO_IS_INST_REF);
// The repository code can't handle paths like root\default:classname
// So if there is a colon, pass a pointer to one past it
WCHAR * pRelativePath = wszObjectPath; for(WCHAR * pTest = wszObjectPath;*pTest;pTest++) { if(*pTest == L':') { // In win2k, we allowed \\.\root\default:whatever, but not root\default:whatever
// So, the following additional test was added
if((uResponse & WBEMPATH_INFO_PATH_HAD_SERVER) == 0) return OpInfo.ErrorOccurred(WBEM_E_INVALID_OBJECT_PATH);
pRelativePath = pTest+1; break; } else if (*pTest==L'=') break; //got to key part...
}
if (bInstance) { CFinalizingSink* pFinalSink = new CFinalizingSink(this, OpInfo.GetSink()); if(pFinalSink == NULL) return OpInfo.ErrorOccurred(WBEM_E_OUT_OF_MEMORY); pFinalSink->AddRef(); CReleaseMe rmFinal(pFinalSink);
hres = Exec_GetInstance(pRelativePath, pPath, lFlags, pCtx, pFinalSink); if (FAILED(hres)) return OpInfo.ErrorOccurred(hres); } else { hres = Exec_GetClass(pRelativePath, lFlags, pCtx, OpInfo.GetSink()); if (FAILED(hres)) return OpInfo.ErrorOccurred(hres); }
return hres; }
//***************************************************************************
//
//***************************************************************************
HRESULT CWbemNamespace::Exec_GetInstance(LPCWSTR wszObjectPath, IWbemPath* pParsedPath, long lFlags, IWbemContext* pCtx, CBasicObjectSink* pSink) { if (pParsedPath->IsSameClassName(L"__NTLMUser") || pParsedPath->IsSameClassName(L"__NTLMGroup")) { if((lFlags & WBEM_FLAG_ONLY_STATIC) == 0) {
ParsedObjectPath* pOutput = 0; // todo, convert to use new parser
CObjectPathParser p; int nStatus = p.Parse(wszObjectPath, &pOutput); if (nStatus != 0) { p.Free(pOutput); return WBEM_E_INVALID_OBJECT_PATH; }
HRESULT hr = GetSecurityClassInstances(pOutput, pSink, pCtx,lFlags); p.Free(pOutput); return hr; } }
// Try static database first
// =========================
if((lFlags & WBEM_FLAG_NO_STATIC) == 0) { IWbemClassObject *pObj = 0; HRESULT hRes = CRepository::GetObject(m_pSession, m_pScopeHandle, wszObjectPath, lFlags, &pObj);
if (SUCCEEDED(hRes)) { hRes = WBEM_S_NO_ERROR; pSink->Add(pObj); pObj->Release(); return pSink->Return(hRes); }
}
// Try dynamic
// ===========
return DynAux_GetInstance((LPWSTR)wszObjectPath, lFlags, pCtx, pSink); }
//***************************************************************************
//
//***************************************************************************
HRESULT CWbemNamespace::Exec_GetClass( LPCWSTR pszClassName, long lFlags, IWbemContext* pCtx, CBasicObjectSink* pSink ) { HRESULT hRes = 0; IWbemClassObject* pErrorObj = 0; IWbemServices *pClassProv = 0; CSynchronousSink* pSyncSink = 0; BSTR bstrClass = 0; IWbemClassObject* pResultObj = 0;
if (pszClassName == 0 || pSink == 0) return pSink->Return(WBEM_E_INVALID_PARAMETER);
if (!m_bRepositOnly && m_pProvFact) { hRes = m_pProvFact->GetClassProvider( 0, // lFlags
pCtx, m_wszUserName, m_wsLocale, m_pThisNamespace, // IWbemPath pointer
0, IID_IWbemServices, (LPVOID *) &pClassProv );
if (FAILED(hRes)) return pSink->Return(hRes); }
CReleaseMe _1(pClassProv);
// First, try repository. If it's there, end of story.
// ====================================================
if ((lFlags & WBEM_FLAG_NO_STATIC) == 0) { if (m_pNsHandle) { hRes = CRepository::GetObject( m_pSession, m_pNsHandle, pszClassName, 0, &pResultObj ); } else // Something drastically wrong
{ hRes = WBEM_E_CRITICAL_ERROR; return pSink->Return(hRes); }
if (SUCCEEDED(hRes) && pResultObj) { pSink->Add(pResultObj); pResultObj->Release(); return pSink->Return(hRes); } }
// If we are in repository-only mode, we don't bother
// with dynamic classes.
// ===================================================
if (m_bRepositOnly || m_pProvFact == NULL) return pSink->Return(WBEM_E_NOT_FOUND);
// If here, try the dynamic class providers.
// =========================================
// Build up a synchronous sink to receive the class.
// =================================================
pSyncSink = CSynchronousSink::Create(); if (pSyncSink == NULL) return pSink->Return(WBEM_E_OUT_OF_MEMORY); pSyncSink->AddRef(); CReleaseMe _2(pSyncSink);
// Try to get it.
// ==============
bstrClass = SysAllocString(pszClassName); if (bstrClass == 0) return pSink->Return(WBEM_E_OUT_OF_MEMORY); CSysFreeMe sfm(bstrClass);
{ CDecoratingSink * pDecore = new CDecoratingSink(pSyncSink, this); if(pDecore == NULL) return pSink->Return(WBEM_E_OUT_OF_MEMORY); pDecore->AddRef(); CReleaseMe rmDecor(pDecore); hRes = pClassProv->GetObjectAsync(bstrClass, lFlags & ~WBEM_FLAG_USE_AMENDED_QUALIFIERS, pCtx, pDecore); }
if (FAILED(hRes)) return pSink->Return(hRes);
pSyncSink->Block(); pSyncSink->GetStatus(&hRes, NULL, &pErrorObj);
if (FAILED(hRes)) { pSink->Return(hRes, pErrorObj); if (pErrorObj) pErrorObj->Release(); return hRes; }
// Otherwise, somebody claimed to have supplied it. Do we really believe them? No choice.
// =======================================================================================
if(pSyncSink->GetObjects().GetSize() < 1) { ERRORTRACE((LOG_WBEMCORE, "Sync sink returned success with no objects!\n")); return pSink->Return(WBEM_E_CRITICAL_ERROR); } pResultObj = pSyncSink->GetObjects()[0]; pSink->Add(pResultObj); pSink->Return(WBEM_S_NO_ERROR);
return hRes; }
//***************************************************************************
//
//***************************************************************************
// ok
HRESULT CWbemNamespace::ExecNotificationQuery( const BSTR QueryLanguage, const BSTR Query, long lFlags, IWbemContext* pCtx, IEnumWbemClassObject** ppEnum ) { try { HRESULT hRes = CheckNs(); if (FAILED(hRes)) return hRes;
DEBUGTRACE((LOG_WBEMCORE, "CALL CWbemNamespace::ExecNotificationQuery\n" " BSTR QueryLanguage = %S\n" " BSTR Query = %S\n" " lFlags = 0x%X\n" " IEnumWbemClassObject **pEnum = 0x%X\n", QueryLanguage, Query, lFlags, ppEnum ));
// Validate parameters
// ===================
if (ppEnum == NULL) return WBEM_E_INVALID_PARAMETER; *ppEnum = NULL;
if ((lFlags & WBEM_FLAG_RETURN_IMMEDIATELY) == 0) return WBEM_E_INVALID_PARAMETER;
if ((lFlags & WBEM_FLAG_FORWARD_ONLY) == 0) return WBEM_E_INVALID_PARAMETER;
if (lFlags & ~WBEM_FLAG_USE_AMENDED_QUALIFIERS & ~WBEM_RETURN_IMMEDIATELY & ~WBEM_FLAG_FORWARD_ONLY #ifdef _WBEM_WHISTLER_UNCUT
& ~WBEM_FLAG_MONITOR #endif
) return WBEM_E_INVALID_PARAMETER;
// Create Finalizer.
// =================
_IWmiFinalizer *pFnz = 0; hRes = CreateSyncFinalizer(pCtx, &pFnz); if (FAILED(hRes)) return hRes; CReleaseMe _1(pFnz);
ULONG uTaskType = WMICORE_TASK_EXEC_NOTIFICATION_QUERY; if (lFlags & WBEM_RETURN_IMMEDIATELY) uTaskType |= WMICORE_TASK_TYPE_SEMISYNC; else uTaskType |= WMICORE_TASK_TYPE_SYNC;
// Do the work.
// ============
hRes = _ExecNotificationQueryAsync(uTaskType, pFnz, 0, QueryLanguage, Query, lFlags & ~WBEM_RETURN_IMMEDIATELY & ~WBEM_FLAG_FORWARD_ONLY, pCtx, NULL);
if (FAILED(hRes)) { return hRes; }
if ((lFlags & WBEM_RETURN_IMMEDIATELY) == 0) pFnz->GetOperationResult(0, INFINITE, &hRes);
if (SUCCEEDED(hRes)) { IEnumWbemClassObject* pEnum = NULL; hRes = pFnz->GetResultObject(lFlags, IID_IEnumWbemClassObject, (LPVOID*)&pEnum); if (FAILED(hRes)) return hRes; CReleaseMe _2(pEnum);
if (SUCCEEDED(hRes)) { *ppEnum = pEnum; pEnum->AddRef(); // Counteract CReleaseMe
} }
return hRes; } catch(...) { ExceptionCounter c; return WBEM_E_CRITICAL_ERROR; } }
//
//
// this function can throw or return
//
//////////////////////////////////////////////////////////
HRESULT CWbemNamespace::_ExecNotificationQueryAsync( IN ULONG uInternalFlags, IN _IWmiFinalizer *pFnz, IN _IWmiCoreHandle *phTask, IN const BSTR strQueryLanguage, IN const BSTR strQuery, IN long lFlags, IN IWbemContext __RPC_FAR *pCtx, IN IWbemObjectSink __RPC_FAR *pHandler ) {
HRESULT hRes = CheckNs(); if (FAILED(hRes)) return hRes; if (!Allowed(WBEM_ENABLE)) return WBEM_E_ACCESS_DENIED;
DEBUGTRACE((LOG_WBEMCORE, "CALL CWbemNamespace::_ExecNotificationQueryAsync\n" " BSTR QueryLanguage = %S\n" " BSTR Query = %S\n" " lFlags = 0x%X\n" " IWbemObjectSink* pHandler = 0x%X\n", strQueryLanguage, strQuery, lFlags, pHandler));
// Parameter validation.
// =====================
if (pFnz == 0 && pHandler == 0) return WBEM_E_INVALID_PARAMETER; if (strQueryLanguage == 0 || strQuery == 0 || strQueryLanguage[0] == 0) return WBEM_E_INVALID_PARAMETER; if (strQuery[0] == 0 ) return WBEM_E_UNPARSABLE_QUERY;
if (wcslen_max(strQuery,g_QueryLimit) > g_QueryLimit) return WBEM_E_QUOTA_VIOLATION;
if (lFlags & ~WBEM_FLAG_SEND_STATUS & ~WBEM_FLAG_USE_AMENDED_QUALIFIERS ) return WBEM_E_INVALID_PARAMETER;
m_bForClient=FALSE; // Forces a cheap fast-track
// Create Finalizer.
// =================
IWbemObjectSink *pPseudoSink = 0; if (pFnz == 0) { hRes = CreateAsyncFinalizer(pCtx, pHandler, &pFnz, &pPseudoSink); if (FAILED(hRes)) return hRes; } else // borrowed finalizer
{ hRes = pFnz->NewInboundSink(0, &pPseudoSink); if (FAILED(hRes)) return hRes; pFnz->AddRef(); }
CReleaseMe _1(pPseudoSink); CReleaseMe _2(pFnz);
// Add the request to the queue.
// =============================
IWbemEventSubsystem_m4* pEss = ConfigMgr::GetEssSink(); CReleaseMe _3(pEss); if (pEss == 0) { return WBEM_E_NOT_SUPPORTED; // ESS must be disabled
}
HANDLE hEssValidate = CreateEvent(NULL,FALSE,FALSE,NULL); if (NULL == hEssValidate) return WBEM_E_OUT_OF_MEMORY; CCloseMe cm(hEssValidate);
HRESULT hResEssCheck = 0; wmilib::auto_ptr<CAsyncReq_ExecNotificationQueryAsync> pReq; pReq.reset(new CAsyncReq_ExecNotificationQueryAsync(this, pEss, strQueryLanguage, strQuery, lFlags, pPseudoSink, pCtx, &hResEssCheck, hEssValidate));
if (NULL == pReq.get()) return WBEM_E_OUT_OF_MEMORY; if ( NULL == pReq->GetContext() ) return WBEM_E_OUT_OF_MEMORY;
hRes = InitNewTask(pReq.get(), pFnz, uInternalFlags, pReq->GetContext(), pHandler); if (FAILED(hRes)) return hRes;
_1.release(); // Enqueue the request.
hRes = ConfigMgr::EnqueueRequest(pReq.get());
if (FAILED(hRes)) { pFnz->CancelTask (0); return hRes; }
pReq.release(); // queue took ownership
// In this case, we have to wait long enough for ESS to accept the task.
WaitForSingleObject(hEssValidate, INFINITE);
// If ESS failed, we should cancel the task
// ========================================
if ( FAILED (hResEssCheck) ) { pFnz->CancelTask(0); } return hResEssCheck; }
//***************************************************************************
//
//***************************************************************************
// done
HRESULT CWbemNamespace::ExecNotificationQueryAsync( IN const BSTR strQueryLanguage, IN const BSTR strQuery, IN long lFlags, IN IWbemContext __RPC_FAR *pCtx, IN IWbemObjectSink __RPC_FAR *pHandler ) { try { return _ExecNotificationQueryAsync(WMICORE_TASK_TYPE_ASYNC | WMICORE_TASK_EXEC_NOTIFICATION_QUERY, 0, 0, strQueryLanguage, strQuery, lFlags, pCtx, pHandler); } catch (...) { ExceptionCounter c; return WBEM_E_CRITICAL_ERROR; } }
//***************************************************************************
//
//***************************************************************************
//
HRESULT CWbemNamespace::GetImplementationClass( IWbemClassObject * pTestClass, LPWSTR wszMethodName, IWbemContext* pCtx, IWbemClassObject ** ppClassObj ) { try { // If the method is disabled, or implemented in this class, we are done!
// =====================================================================
CVar Var; CWbemClass * pClassDef = (CWbemClass *)pTestClass;
HRESULT hres = pClassDef->GetMethodQualifier(wszMethodName, L"DISABLED", &Var); if(hres == S_OK && Var.GetBool() == VARIANT_TRUE) return WBEM_E_METHOD_DISABLED;
hres = pClassDef->GetMethodQualifier(wszMethodName, L"IMPLEMENTED", &Var); if(hres == S_OK && Var.GetBool() == VARIANT_TRUE) { // The test class is correct, return it
pTestClass->AddRef(); *ppClassObj = pTestClass; return S_OK; } // Not done, get the name of the parent class.
SCODE hRes = pClassDef->GetSystemPropertyByName(L"__superclass", &Var); if(hRes != S_OK) return WBEM_E_CRITICAL_ERROR;
if(Var.GetType() != VT_BSTR) return WBEM_E_METHOD_NOT_IMPLEMENTED; // no superclass --- no implementation
BSTR bstrParent = Var.GetBSTR(); if(bstrParent == NULL) return WBEM_E_CRITICAL_ERROR; // NULL, but not VT_NULL
if(wcslen(bstrParent) < 1) { SysFreeString(bstrParent); return WBEM_E_FAILED; // empty parent name????
}
IWbemClassObject * pParent = NULL; hres = Exec_GetObjectByPath(bstrParent, 0, pCtx, &pParent, NULL); SysFreeString(bstrParent); if(FAILED(hres)) return WBEM_E_FAILED; // class provider failure or weird interaction
hRes = GetImplementationClass(pParent, wszMethodName, pCtx, ppClassObj); pParent->Release(); return hRes;
} catch(CX_Exception &) { return WBEM_E_FAILED; } }
//***************************************************************************
//
// CWbemNamespace::Exec_ExecMethod
//
// Executes a method. If the method is not tagged by the [bypass_getobject]
// qualifier, the method is passed directly to the method provider. Otherwise,
// a GetObject call is done first to ensure the instance is valid.
//
//***************************************************************************
//
HRESULT CWbemNamespace::Exec_ExecMethod( LPWSTR wszObjectPath, LPWSTR wszMethodName, long lFlags, IWbemClassObject *pInParams, IWbemContext *pCtx, CBasicObjectSink* pSink ) { TIMETRACE(TimeTraces::ExecMethod); // Lotsa useful variables.
// =======================
HRESULT hRes; IWbemClassObject* pClassDef = NULL; IWbemClassObject* pImplementationClass = NULL; IWbemPath *pPath = 0; IWbemQualifierSet *pQSet = 0; IWbemClassObject* pErrorObj = NULL; BOOL bPathIsToClassObject = FALSE; LPWSTR pszClassName = 0; ULONGLONG uInf = 0;
// Set up a sink error object and check it.
COperationError OpInfo(pSink, L"ExecMethod", wszObjectPath); if ( !OpInfo.IsOk() ) return WBEM_E_OUT_OF_MEMORY;
// Parse the path to the object.
// =============================
// Backwards compatibility - parsing a NULL path returns WBEM_E_INVALID_OBJECT_PATH
if ( NULL == wszObjectPath || NULL == *wszObjectPath ) { return OpInfo.ErrorOccurred( WBEM_E_INVALID_METHOD ); }
hRes = m_pCoreSvc->CreatePathParser(0, &pPath); if (FAILED(hRes)) return OpInfo.ErrorOccurred(hRes); CReleaseMe _1(pPath);
hRes = pPath->SetText(WBEMPATH_CREATE_ACCEPT_ALL, wszObjectPath); if (FAILED(hRes)) return OpInfo.ErrorOccurred(hRes);
ULONG uBuf = 0; hRes = pPath->GetClassName(&uBuf, 0); // Discover the buffer size
if (FAILED(hRes)) return OpInfo.ErrorOccurred(hRes);
pszClassName = new wchar_t[uBuf+1]; // Allocate a buffer for the class name
if (pszClassName == 0) return OpInfo.ErrorOccurred(WBEM_E_OUT_OF_MEMORY);
wmilib::auto_buffer <wchar_t> _2(pszClassName); // Auto-delete buffer
hRes = pPath->GetClassName(&uBuf, pszClassName); // Get class name
if (FAILED(hRes)) return OpInfo.ErrorOccurred(hRes);
// Find out if a path to an instance or a class.
// ==============================================
hRes = pPath->GetInfo(0, &uInf); if (FAILED(hRes)) return OpInfo.ErrorOccurred(hRes);
if (uInf & WBEMPATH_INFO_IS_INST_REF) bPathIsToClassObject = FALSE; else bPathIsToClassObject = TRUE;
// Get the class definition. We'll need it whether or not we validate the
// instance or not.
// =======================================================================
hRes = Exec_GetObjectByPath(pszClassName, (lFlags & WBEM_FLAG_USE_AMENDED_QUALIFIERS), pCtx, &pClassDef, &pErrorObj);
if (FAILED(hRes)) { OpInfo.ErrorOccurred(hRes, pErrorObj); if (pErrorObj) pErrorObj->Release(); return hRes; }
CReleaseMe _3(pClassDef);
// Now see if the method exists and if the class definition
// has the [bypass_getobject] qualifier on that method.
// ========================================================
hRes = pClassDef->GetMethodQualifierSet(wszMethodName, &pQSet); if (FAILED(hRes)) { // Means the method doesn't even exist
if ( WBEM_E_NOT_FOUND == hRes ) { hRes = WBEM_E_INVALID_METHOD; }
return OpInfo.ErrorOccurred(hRes); } CReleaseMe _4(pQSet);
hRes = pQSet->Get(L"bypass_getobject", 0, 0, 0);
if (hRes == WBEM_E_NOT_FOUND) { // If here, we are going to get the object pointed to by the path first to ensure it is
// valid. Note that the object may be either an instance or class object
//
// First, merge in the __GET_EXT_KEYS_ONLY during the GetObject calls to allow
// the provider to quickly verify the existence of the object. We don't
// actually care about the property values other than the keys. We use
// a copy of the context object, as we want to merge in KEYS_ONLY behavior
// for the next call only.
// ============================================================================
IWbemClassObject *pVerifiedObj = 0; IWbemContext *pCopy = 0;
if (pCtx) pCtx->Clone(&pCopy); hRes = MergeGetKeysCtx(pCopy); if (FAILED(hRes)) return OpInfo.ErrorOccurred(hRes);
// If here, we are verifying the object exists before passing the
// control to the method handler.
// ==============================================================
hRes = Exec_GetObjectByPath(wszObjectPath, lFlags, pCopy, &pVerifiedObj, &pErrorObj);
if (pCopy) pCopy->Release();
if (FAILED(hRes)) { OpInfo.ErrorOccurred(hRes, pErrorObj); if (pErrorObj) pErrorObj->Release(); return hRes; }
// If here, the class or instance exists!!
// =======================================
pVerifiedObj->Release(); } else if (FAILED(hRes)) { return OpInfo.ErrorOccurred(hRes); }
// If this is the special internal security object, handle it internally
// ======================================================================
CVar Value; hRes = ((CWbemClass *) pClassDef)->GetSystemPropertyByName(L"__CLASS", &Value); if (hRes == S_OK && Value.GetType() == VT_BSTR && !Value.IsDataNull()) if (!wbem_wcsicmp(Value.GetLPWSTR(), L"__SystemSecurity")) return SecurityMethod(wszMethodName, lFlags, pInParams, pCtx, pSink);
// Make sure we have security.
// ===========================
if (!Allowed(WBEM_METHOD_EXECUTE)) return OpInfo.ErrorOccurred(WBEM_E_ACCESS_DENIED);
// Now, we locate the exact implementation of the method. After all, the
// subclass may have been very lazy and relied on its parent implementation,
// the way many kids rely on their parents for gas money.
// =========================================================================
hRes = GetImplementationClass(pClassDef, wszMethodName, pCtx, &pImplementationClass); if (FAILED(hRes)) return OpInfo.ErrorOccurred(hRes);
// The "pImplementatinClass" now points to the class object where the methods is implemented
// =========================================================================================
CReleaseMe rm2(pImplementationClass); CWbemClass * pImplementationDef = (CWbemClass*)pImplementationClass;
// Make sure that class paths are only used with static methods.
// =============================================================
CVar Var; if (bPathIsToClassObject) { hRes = pImplementationDef->GetMethodQualifier(wszMethodName, L"STATIC", &Var); if (hRes != S_OK || Var.GetBool() != VARIANT_TRUE) { return OpInfo.ErrorOccurred(WBEM_E_INVALID_METHOD_PARAMETERS); } }
// Get the provider name.
// ======================
CVar vProv; hRes = pImplementationDef->GetQualifier(L"Provider", &vProv);
if (FAILED(hRes) || vProv.GetType() != VT_BSTR) return OpInfo.ErrorOccurred(WBEM_E_INVALID_PROVIDER_REGISTRATION);
// Adjust the path to reference the class of implementation
// ========================================================
CVar vImpClassName; hRes = pImplementationDef->GetClassName(&vImpClassName); if (FAILED(hRes) || vImpClassName.GetType() != VT_BSTR) return OpInfo.ErrorOccurred(WBEM_E_CRITICAL_ERROR);
BSTR strNewPath = CQueryEngine::AdjustPathToClass(wszObjectPath, vImpClassName.GetLPWSTR()); if (strNewPath == NULL) return OpInfo.ErrorOccurred(WBEM_E_CRITICAL_ERROR);
CSysFreeMe sfm1(strNewPath);
// Load the provider and execute it.
// ==================================
CMethodSink * pMethSink = new CMethodSink(OpInfo.GetSink()); if(pMethSink == NULL) return OpInfo.ErrorOccurred(WBEM_E_OUT_OF_MEMORY); pMethSink->AddRef(); CReleaseMe _5(pMethSink);
// Find provider.
// ==============
IWbemServices *pProv = 0; if(m_pProvFact == NULL) hRes = WBEM_E_CRITICAL_ERROR; else { WmiInternalContext t_InternalContext ; ZeroMemory ( & t_InternalContext , sizeof ( t_InternalContext ) ) ; // SEC:REVIEWED 2002-03-22 : OK
hRes = m_pProvFact->GetProvider(
t_InternalContext , 0, // lFlags
pCtx, 0, m_wszUserName, m_wsLocale, 0, // IWbemPath pointer
vProv, // Provider
IID_IWbemServices, (LPVOID *) &pProv ); }
if (FAILED(hRes)) { return pSink->Return(hRes); }
CReleaseMe _(pProv);
hRes = pProv->ExecMethodAsync( strNewPath, wszMethodName, lFlags& ~WBEM_FLAG_USE_AMENDED_QUALIFIERS, pCtx, pInParams, pMethSink );
return hRes; }
//***************************************************************************
//
// CWbemNamespace::GetOrPutDynProps
//
// Processes an instance to see if any properties have been marked
// as 'dynamic'.
//
// Short-circuit logic is in effect. The instance as a whole must be
// marked with the following Qualifier to signal that the instance has
// dynamic properties which need evaluation:
//
// "DYNPROPS" (VT_BOOL) = VARIANT_TRUE
//
// Optionally, the instance may contain:
// "INSTANCECONTEXT" VT_BSTR = <provider specific string>
//
// In addition, each dynamic property is marked
//
// "DYNAMIC" VT_BOOL VARIANT_TRUE
// "LOCATORCLSID" VT_BSTR CLSID of the provider
// "PROPERTYCONTEXT" VT_BSTR <provider specific string>
//
// "INSTANCECONTEXT" and "PROPERTYCONTEXT" are not checked by this code,
// since they are optional for each provider.
//
// PARAMETERS:
//
// IWbemClassObject* pObj The object to fill in dynamic properties
// in.
// Operation op Can be GET or PUT depending on what is
// needed.
// bool bIsDynamic True if a dynamically provided class. Note that it
// would be very strange to have a dynamic class with
// dynamic properties.
// RETURN VALUES:
// <WBEM_NO_ERROR> No provider was involved or if a provider was
// involved, properties were all evaluated.
//
// <WBEM_E_INVALID_OBJECT>
// Object was marked as dynamic, but other Qualifiers were missing.
//
// <WBEM_E_PROVIDER_NOT_FOUND>
// One or more of the specified providers could not be found.
//
// <WBEM_E_PROVIDER_FAILURE>
// One or more providers were not able to provide the properties.
//
// <WBEM_E_CRITICAL_ERROR>
//
//***************************************************************************
HRESULT CWbemNamespace::GetOrPutDynProps( IWbemClassObject *pObj, Operation op, BOOL bIsDynamic ) { HRESULT hRes; IWbemContext *pCtx = 0; CVar vDynTest; _IWmiDynamicPropertyResolver *pResolver = 0; IWbemQualifierSet *pQSet = 0; IWbemClassObject *pClassDef = 0; CVARIANT v;
// Examine the instance to see if there are any dynamic properties.
// ================================================================
hRes = pObj->GetQualifierSet(&pQSet); if (FAILED(hRes)) return WBEM_NO_ERROR; CReleaseMe _1(pQSet);
hRes = pQSet->Get(L"DYNPROPS", 0, &v, 0); if (FAILED(hRes)) return WBEM_S_NO_ERROR; if (v.GetBool() == FALSE) return WBEM_S_NO_ERROR;
v.Clear(); hRes = pObj->Get(L"__CLASS", 0, &v, 0, 0); if (FAILED(hRes)) return hRes;
// Get the class definition for the object.
// Must be static.
// ========================================
hRes = CRepository::GetObject( m_pSession, m_pNsHandle, v.GetStr(), 0, &pClassDef );
CReleaseMe _2(pClassDef); if (FAILED(hRes)) return hRes;
// Access provider subsystem to do the dirty work.
// ================================================
if (m_pProvFact == NULL) hRes = WBEM_E_CRITICAL_ERROR; else { pCtx = ConfigMgr::GetNewContext(); if ( pCtx == NULL ) return WBEM_E_OUT_OF_MEMORY;
hRes = m_pProvFact->GetDynamicPropertyResolver ( 0, // lFlags
pCtx, // context
m_wszUserName, m_wsLocale, IID__IWmiDynamicPropertyResolver, (LPVOID *)&pResolver); }
CReleaseMe _1_pCtx (pCtx) ;
if (FAILED(hRes)) return hRes;
CReleaseMe _3(pResolver);
// Determine if a put or a get.
// ============================
if (op == GET) { hRes = pResolver->Read(pCtx, pClassDef, &pObj); } else if (op == PUT) { hRes = pResolver->Write(pCtx, pClassDef, pObj); } else return WBEM_E_INVALID_PARAMETER;
return hRes; }
//***************************************************************************
//
// AddKey
//
// Adds a keyname/value pair to a normalized path
//
// throw CX_MemoryException
//
//***************************************************************************
HRESULT AddKey(WString & wNormalString, WCHAR * pwsKeyName, VARIANT *pvKeyValue, int & iNumKey, CWbemInstance* pClassDef) { if(iNumKey++ > 0) wNormalString += L","; // prepend comma for all but the first key
wNormalString += pwsKeyName; wNormalString += "="; if(pvKeyValue->vt == VT_BSTR) { wNormalString += L"\"";
// if there are any quotes, they must be prepended with a back slash;
// Also, any back slashes should be doubled up.
int iLen = 1; // one for the terminator;
WCHAR * pTest; for(pTest = pvKeyValue->bstrVal;*pTest; pTest++, iLen++) if(*pTest == L'\"' || *pTest == L'\\') iLen++; WCHAR * pString = new WCHAR[iLen]; if(pString == NULL) throw CX_MemoryException(); wmilib::auto_buffer<WCHAR> rm_(pString);
WCHAR * pTo = pString; for(pTest = pvKeyValue->bstrVal;*pTest; pTest++, pTo++) { if(*pTest == L'\"' || *pTest == L'\\') { *pTo = L'\\'; pTo++; } *pTo = *pTest; } *pTo = 0;
wNormalString += pString; wNormalString += L"\""; return S_OK; } if(pvKeyValue->vt != VT_EMPTY && pvKeyValue->vt != VT_NULL) {
// special case for large unsigned numbers
if(pvKeyValue->vt == VT_I4 && pvKeyValue->lVal < 0) { CIMTYPE ct; HRESULT hRes = pClassDef->Get(pwsKeyName, 0, NULL, &ct, NULL); if(hRes == S_OK && ct == CIM_UINT32) { WCHAR wBuff[32]; StringCchPrintfW(wBuff, 32, L"%u",pvKeyValue->lVal); wNormalString += wBuff; return S_OK; } }
_variant_t var; HRESULT hRes = VariantChangeType(&var, pvKeyValue, 0, VT_BSTR); if(hRes == S_OK) { wNormalString += var.bstrVal; }
return hRes; } return WBEM_E_INVALID_OBJECT_PATH; }
//***************************************************************************
//
// NormalizeObjectPath
//
// Creates a normalized object path for passing to providers.
//***************************************************************************
HRESULT NormalizeObjectPath(ParsedObjectPath*pOutput, WString & wNormalString, CWbemInstance* pClassDef) { try { HRESULT hRes;
// For singleton, so long as the class is singleton
if(pOutput->m_bSingletonObj) { CVar Singleton; hRes = pClassDef->GetQualifier(L"SINGLETON", &Singleton); if (hRes == 0 && Singleton.GetBool() != 0) { wNormalString = pOutput->m_pClass; wNormalString += "=@"; return S_OK; } else return WBEM_E_INVALID_OBJECT_PATH; }
int iKeyNum = 0; int iNumMatch = 0; // number of keys in the path which were found in the class def
// Start off by writting the class name followe by a dot
wNormalString = pOutput->m_pClass; wNormalString += L".";
CWStringArray ClassKeyNames; if(!pClassDef->GetKeyProps(ClassKeyNames)) return WBEM_E_INVALID_CLASS;
// For each key in the class definition
for(int iClassKey = 0; iClassKey < ClassKeyNames.Size(); iClassKey++) { // look for the class key in the path
bool bClassKeyIsInPath = false; int iPathKey;
for(iPathKey = 0; iPathKey < pOutput->m_dwNumKeys; iPathKey++) { KeyRef * key = pOutput->m_paKeys[iPathKey]; if(key->m_pName == 0 && ClassKeyNames.Size() == 1 && pOutput->m_dwNumKeys==1) { bClassKeyIsInPath = true; break; } else if(key->m_pName && !wbem_wcsicmp(key->m_pName, ClassKeyNames[iClassKey])) { bClassKeyIsInPath = true; break; } } if(bClassKeyIsInPath) { iNumMatch++; // todo, check type
KeyRef * key = pOutput->m_paKeys[iPathKey]; hRes = AddKey(wNormalString, ClassKeyNames[iClassKey], &key->m_vValue, iKeyNum, pClassDef); if(FAILED(hRes)) return hRes; } else { // If the key has a default value, then use it
_variant_t var; hRes = pClassDef->Get(ClassKeyNames[iClassKey], 0, &var, NULL, NULL); if(FAILED(hRes) || var.vt == VT_EMPTY || var.vt == VT_NULL) return WBEM_E_INVALID_OBJECT_PATH; hRes = AddKey(wNormalString, ClassKeyNames[iClassKey], &var, iKeyNum,pClassDef); if(FAILED(hRes)) return hRes; } }
if(iNumMatch == pOutput->m_dwNumKeys) return S_OK; else return WBEM_E_INVALID_OBJECT_PATH; } catch (CX_MemoryException &) {
return WBEM_E_OUT_OF_MEMORY; } }
//***************************************************************************
//
// CWbemNamespace::DynAux_GetInstance
//
// Retrieves an instance identified by its path from the dynamic provider
// registered for that class.
//
// PARAMETERS:
//
// IN DWORD dwNamespace Namespace handle to the current
// namespace (see objdb.h)
// IN LPWSTR pObjectPath Object path to the instance.
// IN long lFlags Flags. Propagated to provider.
// OUT IWbemClassObject** pObj Destination for the class definition.
// The caller must release this object
// if the call is successful.
// OUT IWbemClassObject** ppErrorObj Destination for the error object. May
// be NULL. Otherwise, the returned
// pointer must be released if not NULL.
// RETURN VALUES:
//
// WBEM_S_NO_ERROR Success.
// WBEM_E_NOT_FOUND No such instance, says provider, or the
// class is not dynamic.
// WBEM_E_INVALID_PARAMETER One or more parameters are invalid.
// WBEM_E_INVALID_CLASS The class specified in the path does not
// exist.
// WBEM_E_FAILED Unexpected error occured.
// WBEM_E_PROVIDER_NOT_FOUND Provider for this class could not be
// located --- not registered with us or COM.
// WBEM_E_PROVIDER_FAILURE Provider reported an error while looking
// for this object.
// WBEM_E_PROVIDER_NOT_CAPABLE Provider for this class is not capable of
// getting objects by path.
//
//***************************************************************************
HRESULT CWbemNamespace::DynAux_GetInstance( IN LPWSTR wszObjectPath, IN long lFlags, IN IWbemContext* pCtx, IN CBasicObjectSink* pSink ) { // Parse the object path to get the class involved.
// ================================================
ParsedObjectPath* pOutput = 0; CObjectPathParser p; int nStatus = p.Parse(wszObjectPath, &pOutput); OnDeleteObj<ParsedObjectPath*,CObjectPathParser, void (CObjectPathParser:: *)(ParsedObjectPath *), &CObjectPathParser::Free> FreeMe(&p,pOutput);
if(CObjectPathParser::NoError != nStatus || !pOutput->IsInstance()) return pSink->Return(WBEM_E_INVALID_OBJECT_PATH);
HRESULT hres = WBEM_E_FAILED; IWbemClassObject* pErrorObj = NULL; CReleaseMeRef<IWbemClassObject*> rmErrObj(pErrorObj); CSetStatusOnMe SetMe(pSink,hres,pErrorObj);
// See if this class is actually provided dynamically
BSTR strClass = SysAllocString(pOutput->m_pClass); if (NULL == strClass) { return hres = WBEM_E_OUT_OF_MEMORY; } CSysFreeMe sfm(strClass);
CWbemInstance *pClassDef = 0; IWbemClassObject* pClassObj = NULL;
hres = Exec_GetObjectByPath(strClass, lFlags & WBEM_FLAG_USE_AMENDED_QUALIFIERS, pCtx,&pClassObj, NULL); if(FAILED(hres)) { hres = (hres == WBEM_E_NOT_FOUND) ? WBEM_E_INVALID_CLASS : WBEM_E_FAILED; return hres; }
CReleaseMe rm(pClassObj); pClassDef = (CWbemInstance*)pClassObj;
WString wNormalPath; hres = NormalizeObjectPath(pOutput, wNormalPath, pClassDef); if(FAILED(hres)) return hres;
if(!pClassDef->IsKeyed()) return hres = WBEM_E_INVALID_CLASS;
// Make sure that this class is not static ---
// i.e. either dynamic or abstract
// ===========================================
CVar vDynamic; hres = pClassDef->GetQualifier(L"Dynamic", &vDynamic); if(FAILED(hres) || vDynamic.GetType() != VT_BOOL || !vDynamic.GetBool()) { // Not dynamic. Check if it is abstract
// ====================================
CVar vAbstract; hres = pClassDef->GetQualifier(L"Abstract", &vAbstract); if(FAILED(hres) || vAbstract.GetType() != VT_BOOL || !vAbstract.GetBool()) return hres = WBEM_E_NOT_FOUND; }
// Build the class hierarchy
// =========================
wmilib::auto_ptr<CDynasty> pDynasty; hres = DynAux_BuildClassHierarchy(strClass, lFlags, pCtx, pDynasty,&pErrorObj); if(FAILED(hres)) return hres;
rmErrObj.release(); // set it to null anyway
// If direct read is requested, only ask the provider in question.
// ===============================================================
if (lFlags & WBEM_FLAG_DIRECT_READ) { DynAux_GetSingleInstance((CWbemClass*) pClassObj,lFlags, wszObjectPath, pCtx, pSink); } else { // Create merging sink
hres = WBEM_E_OUT_OF_MEMORY; // pre-set the failure
CSingleMergingSink* pMergeSink = new CSingleMergingSink(pSink, strClass); // throw
if(pMergeSink == NULL) return hres; pMergeSink->AddRef(); CReleaseMe rm(pMergeSink);
// Ask all providers
DynAux_AskRecursively(pDynasty.get(), lFlags, wNormalPath, pCtx,pMergeSink); }
SetMe.dismiss(); return WBEM_S_NO_ERROR; }
//***************************************************************************
//
//***************************************************************************
HRESULT CWbemNamespace::DynAux_AskRecursively(CDynasty* pDynasty, long lFlags, LPWSTR wszObjectPath, IWbemContext* pCtx, CBasicObjectSink* pSink) { // Convert the path to the new class
// =================================
BSTR strNewPath = CQueryEngine::AdjustPathToClass(wszObjectPath, pDynasty->m_wszClassName); if(strNewPath == NULL) return pSink->Return(WBEM_E_INVALID_OBJECT_PATH); CSysFreeMe sfm(strNewPath);
// Get this provider's object
// ==========================
DynAux_GetSingleInstance((CWbemClass*)pDynasty->m_pClassObj,lFlags, strNewPath, pCtx, pSink);
// Get the children's objects
// ==========================
for(int i = 0; i < pDynasty->m_Children.Size(); i++) { CDynasty* pChildDyn = (CDynasty*)pDynasty->m_Children.GetAt(i);
DynAux_AskRecursively(pChildDyn, lFlags, wszObjectPath, pCtx,pSink); }
return WBEM_S_NO_ERROR; }
//***************************************************************************
//
//***************************************************************************
HRESULT CWbemNamespace::DynAux_GetSingleInstance(CWbemClass* pClassDef, long lFlags, LPWSTR wszObjectPath, IWbemContext* pCtx, CBasicObjectSink* pSink) {
COperationError OpInfo(pSink, L"GetObject", wszObjectPath, FALSE); // the ctor calls setstatus in bad luck case
if (!OpInfo.IsOk()) return WBEM_E_OUT_OF_MEMORY;
// Verify that the class is indeed dynamic
// =======================================
if(!pClassDef->IsDynamic()) return OpInfo.ErrorOccurred(WBEM_E_NOT_FOUND);
CVar vProvName; HRESULT hres = pClassDef->GetQualifier(L"Provider", &vProvName); if(FAILED(hres) || vProvName.GetType() != VT_BSTR) return OpInfo.ErrorOccurred(WBEM_E_INVALID_PROVIDER_REGISTRATION);
OpInfo.SetProviderName(vProvName.GetLPWSTR()); //throw
// Access the provider cache.
// ==========================
IWbemServices *pProv = 0; HRESULT hRes; if(m_pProvFact == NULL) hRes = WBEM_E_CRITICAL_ERROR; else { WmiInternalContext t_InternalContext ; ZeroMemory ( & t_InternalContext , sizeof ( t_InternalContext ) ) ; // SEC:REVIEWED 2002-03-22 : OK
hRes = m_pProvFact->GetProvider(
t_InternalContext , 0, // lFlags
pCtx, 0, m_wszUserName, m_wsLocale, 0, // IWbemPath pointer
vProvName, // Provider
IID_IWbemServices, (LPVOID *) &pProv ); }
if (FAILED(hRes)) { return pSink->Return(hRes); }
CReleaseMe _(pProv); CDecoratingSink * pDecore = new CDecoratingSink(OpInfo.GetSink(), this); if(pDecore == NULL) return pSink->Return(WBEM_E_OUT_OF_MEMORY); pDecore->AddRef(); CReleaseMe cdecor(pDecore);
hRes = pProv->GetObjectAsync(wszObjectPath, lFlags& ~WBEM_FLAG_USE_AMENDED_QUALIFIERS, pCtx, pDecore);
return hRes; }
//***************************************************************************
//
// CWbemNamespace::DynAux_GetInstances
//
// Gets all instances from the provider specified in the class
// definition. Does no inheritance joins; this is a simple retrieval
// of all instances from the specified class.
//
// Preconditions:
// 1. The class <pClassDef> is known to be marked 'dynamic', but no
// other verification has been done on the class definition.
// 2. <pClassDef> is not NULL.
//
// Postconditions:
// 1. <aInstances> is empty on all error conditions.
//
// PARAMETERS:
//
// READONLY CWbemObject *pClassDef The definition of the class to retrieve
// instances of.
// long lFlags The flags (deep/shallow)
// CFlexArray &aInstances Destination for the instances.
// IWbemClassObject** ppErrorObj Destination for the error object. If
// not NULL, an error object may be placed
// here. It is the caller's responsibility
// to release it if not NULL.
// RETURN VALUES:
//
// WBEM_NO_ERROR No errors. This includes a no-error situation
// with zero instances returned.
// WBEM_E_INVALID_PROVIDE_REGISTRATION Provider registration for this
// class is incomplete.
// WBEM_E_PROVIDER_NOT_FOUND Provider could not be located. It is not
// registered with us or with COM.
// WBEM_E_PROVIDER_NOT_CAPABLE Provider is not capable of enumerating
// instances.
// WBEM_E_FAILED Unexpected error has occured.
//
//***************************************************************************
HRESULT CWbemNamespace::DynAux_GetInstances(
READONLY CWbemObject *pClassDef, long lFlags, IWbemContext* pCtx, CBasicObjectSink* pSink , BOOL bComplexQuery ) { // First, get the current task -
// if there isn't one, then we are on an WbemESS thread
// ESS use to issue "internal" queries that are processes without arbitration
CWbemRequest* pCurrReq = CWbemQueue::GetCurrentRequest(); CWmiTask * pCurrTask = pCurrReq?((CWmiTask *)pCurrReq->m_phTask):NULL; // We'll need the finalizer in case we need to cancel something
HRESULT hr; _IWmiFinalizer* pMainFnz = NULL; if (pCurrTask) { hr = pCurrTask->GetFinalizer( &pMainFnz ); if (FAILED(hr)) return hr; } CReleaseMe rm( pMainFnz ); CWmiMerger* pWmiMerger = NULL;
// Check if query arbitration is enabled
if ( ConfigMgr::GetEnableQueryArbitration() && pCurrTask) { // Get the arbitrated query pointer and cast to a merger as appropriate
_IWmiArbitratedQuery* pArbQuery = NULL;
hr = pCurrTask->GetArbitratedQuery( 0L, &pArbQuery );
if ( SUCCEEDED( hr ) ) { hr = pArbQuery->IsMerger();
if ( SUCCEEDED( hr ) ) { pWmiMerger = (CWmiMerger*) pArbQuery; } else { pArbQuery->Release(); } }
// Clear errors
hr = WBEM_S_NO_ERROR;
} // IF Query arbitration enabled
CReleaseMe rmMerger( (_IWmiArbitratee*) pWmiMerger );
// Perform correct handling based on whether or not we have a merger
if ( pWmiMerger ) { hr = pWmiMerger->RegisterArbitratedInstRequest( pClassDef, lFlags, pCtx, pSink, bComplexQuery, this );
if (FAILED( hr)) if (pMainFnz) pMainFnz->CancelTask( 0 ); return hr; }
//
// when the query arbitration is not enabled we fall here
//
CAsyncReq_DynAux_GetInstances * pReq; pReq = new CAsyncReq_DynAux_GetInstances (this, pClassDef, lFlags, pCtx, pSink);
if ( pReq == NULL) { if (pMainFnz) pMainFnz->CancelTask ( 0 ); return WBEM_E_OUT_OF_MEMORY; }
if ( NULL == pReq->GetContext() ) { if (pMainFnz) pMainFnz->CancelTask ( 0 ); delete pReq; return WBEM_E_OUT_OF_MEMORY; }
// Set the task for the request - we'll just use the existing one if any
pReq->m_phTask = pCurrTask; if (pReq->m_phTask) pReq->m_phTask->AddRef(); hr = ConfigMgr::EnqueueRequest(pReq);
if (FAILED(hr)) { if (pMainFnz) pMainFnz->CancelTask ( 0 ); delete pReq; }
return hr;
}
//***************************************************************************
//
// CWbemNamespace::DynAux_GetInstances
//
// Gets all instances from the provider specified in the class
// definition. Does no inheritance joins; this is a simple retrieval
// of all instances from the specified class.
//
// Preconditions:
// 1. The class <pClassDef> is known to be marked 'dynamic', but no
// other verification has been done on the class definition.
// 2. <pClassDef> is not NULL.
//
// Postconditions:
// 1. <aInstances> is empty on all error conditions.
//
// PARAMETERS:
//
// READONLY CWbemObject *pClassDef The definition of the class to retrieve
// instances of.
// long lFlags The flags (deep/shallow)
// CFlexArray &aInstances Destination for the instances.
// IWbemClassObject** ppErrorObj Destination for the error object. If
// not NULL, an error object may be placed
// here. It is the caller's responsibility
// to release it if not NULL.
// RETURN VALUES:
//
// WBEM_NO_ERROR No errors. This includes a no-error situation
// with zero instances returned.
// WBEM_E_INVALID_PROVIDE_REGISTRATION Provider registration for this
// class is incomplete.
// WBEM_E_PROVIDER_NOT_FOUND Provider could not be located. It is not
// registered with us or with COM.
// WBEM_E_PROVIDER_NOT_CAPABLE Provider is not capable of enumerating
// instances.
// WBEM_E_FAILED Unexpected error has occured.
//
//***************************************************************************
HRESULT CWbemNamespace::Exec_DynAux_GetInstances( READONLY CWbemObject *pClassDef, long lFlags, IWbemContext* pCtx, CBasicObjectSink* pSink ) {
COperationError OpInfo(pSink, L"CreateInstanceEnum", L"", FALSE); if ( !OpInfo.IsOk() ) return pSink->Return(WBEM_E_OUT_OF_MEMORY); CVar vProv; CVar vClassName; // Get the provider name.
// ======================
try // internal fastprox interfaces throw
{ HRESULT hres = pClassDef->GetQualifier(L"Provider", &vProv); if (FAILED(hres) || vProv.GetType() != VT_BSTR) return OpInfo.ErrorOccurred(WBEM_E_INVALID_PROVIDER_REGISTRATION); if (FAILED(pClassDef->GetClassName(&vClassName))) return pSink->Return(WBEM_E_OUT_OF_MEMORY); OpInfo.SetParameterInfo(vClassName.GetLPWSTR()); } catch(CX_MemoryException &) { return pSink->Return(WBEM_E_OUT_OF_MEMORY); }
// Access Provider Subsystem.
// ==========================
IWbemServices *pProv = 0; HRESULT hRes;
if (m_pProvFact == NULL) hRes = WBEM_E_CRITICAL_ERROR; else { WmiInternalContext t_InternalContext ; ZeroMemory ( & t_InternalContext , sizeof ( t_InternalContext ) );
hRes = m_pProvFact->GetProvider( t_InternalContext , 0, // lFlags
pCtx, 0, m_wszUserName, m_wsLocale, 0, // IWbemPath pointer
vProv, // Provider
IID_IWbemServices, (LPVOID *) &pProv); }
if (FAILED(hRes)) return pSink->Return(hRes); CReleaseMe _1(pProv);
// Set up the sink chain to be delivered to the provider.
// The code & destruct sequence is critical and the
// refcounting is very carefully thought out. Do not
// change this code unless you know exactly what you are
// doing. And don't even change it then.
// ======================================================
CProviderSink *pProvSink = new CProviderSink(1, vClassName.GetLPWSTR()); if (pProvSink == 0) return pSink->Return(WBEM_E_OUT_OF_MEMORY); CReleaseMe _3(pProvSink);
CDecoratingSink * pDecore = new CDecoratingSink(pSink, this); if (pDecore == NULL) return pSink->Return(WBEM_E_OUT_OF_MEMORY); pProvSink->SetNextSink(pDecore);
// Before calling the provider, map the provider to the
// task so that we can cancel it proactively, if required.
// =======================================================
hRes = ((CWmiArbitrator *) m_pArb)->MapProviderToTask(0, pCtx, pProv, pProvSink); if (FAILED(hRes)) return pSink->Return(hRes);
// Now tell the provider to start enumerating.
hRes = pProv->CreateInstanceEnumAsync(vClassName.GetLPWSTR(), lFlags & ~WBEM_FLAG_USE_AMENDED_QUALIFIERS, pCtx, pProvSink );
return hRes; }
//***************************************************************************
//
// CWbemNamespace::DynAux_ExecQueryAsync
//
// Executes a SQL-1 query against a dynamic instance provider for the class
// in the query.
//
// PARAMETERS:
//
// IN DWORD dwNamespace Namespace handle to the current
// namespace (see objdb.h)
// IN CWbemObject* pClassDef Class definition of the class in the
// query. Must be dynamic.
// IN LPWSTR Query The query string.
// IN LPWSTR QueryFormat The query language. Must be WQL.
// IN long lFlags The flags. Not used.
// OUT CFlexArray &aInstances Destinatino for the instances found.
// OUT IWbemClassObject** ppErrorObj Destination for the error object. IF
// not NULL, an error object may be placed
// here. In this case, it is the caller's
// responsibility to release it.
// RETURN VALUES:
//
// WBEM_S_NO_ERROR Success (even though there may not be
// any instances).
// WBEM_E_INVALID_PROVIDE_REGISTRATION Provider registration for this
// class is incomplete.
// WBEM_E_PROVIDER_NOT_FOUND Provider could not be located. It is not
// registered with us or with COM.
// WBEM_E_PROVIDER_NOT_CAPABLE Provider is not capable of enumerating
// instances.
// WBEM_E_FAILED Unexpected error has occured.
//
//***************************************************************************
HRESULT CWbemNamespace::DynAux_ExecQueryAsync (
CWbemObject* pClassDef, LPWSTR Query, LPWSTR QueryFormat, long lFlags, IWbemContext* pCtx, CBasicObjectSink* pSink, BOOL bComplexQuery ) { // First, get the current task - if there isn't one, something
// is very wrong.
CWbemRequest* pCurrReq = CWbemQueue::GetCurrentRequest();
_DBG_ASSERT( NULL != pCurrReq && NULL != pCurrReq->m_phTask );
if ( NULL == pCurrReq || NULL == pCurrReq->m_phTask ) { return WBEM_E_FAILED; }
// We'll need the finalizer in case we need to cancel something
_IWmiFinalizer* pMainFnz = NULL; HRESULT hr = ((CWmiTask*) pCurrReq->m_phTask)->GetFinalizer( &pMainFnz ); CReleaseMe rm( pMainFnz );
if ( SUCCEEDED( hr ) ) { CWmiMerger* pWmiMerger = NULL;
// Check if query arbitration is enabled
if ( ConfigMgr::GetEnableQueryArbitration() ) { // Get the arbitrated query pointer and cast to a merger as appropriate
_IWmiArbitratedQuery* pArbQuery = NULL;
hr = ((CWmiTask*) pCurrReq->m_phTask)->GetArbitratedQuery( 0L, &pArbQuery );
if ( SUCCEEDED( hr ) ) { hr = pArbQuery->IsMerger();
if ( SUCCEEDED( hr ) ) { pWmiMerger = (CWmiMerger*) pArbQuery; } else { pArbQuery->Release(); } }
// Clear errors
hr = WBEM_S_NO_ERROR;
} // IF Query arbitration enabled
// Auto cleanup
CReleaseMe rm( (_IWmiArbitratee*) pWmiMerger );
// Perform correct handling based on whether or not we have a merger
if ( NULL != pWmiMerger ) { hr = pWmiMerger->RegisterArbitratedQueryRequest( pClassDef, lFlags, Query, QueryFormat, pCtx, pSink, this );
if (FAILED(hr)) { pMainFnz->CancelTask ( 0 ); }
} else { CAsyncReq_DynAux_ExecQueryAsync *pReq = 0; try { pReq = new CAsyncReq_DynAux_ExecQueryAsync ( this, pClassDef, Query, QueryFormat, lFlags, pCtx, pSink ); } catch(CX_Exception &) { pReq = 0; }
if (pReq == NULL) { pMainFnz->CancelTask ( 0 ); return WBEM_E_OUT_OF_MEMORY; }
if ( NULL == pReq->GetContext() ) { pMainFnz->CancelTask ( 0 ); delete pReq; return WBEM_E_OUT_OF_MEMORY; }
hr = pReq->Initialize () ; if ( SUCCEEDED ( hr ) ) {
// Set the task for the request - we'll just use the existing one
pCurrReq->m_phTask->AddRef(); pReq->m_phTask = pCurrReq->m_phTask; hr = ConfigMgr::EnqueueRequest(pReq);
if (FAILED(hr)) { pMainFnz->CancelTask ( 0 ); delete pReq; }
} // IF Request Initialized
else { pMainFnz->CancelTask ( 0 ); delete pReq; }
}
}
return hr; }
//***************************************************************************
//
// CWbemNamespace::DynAux_ExecQueryAsync
//
// Executes a SQL-1 query against a dynamic instance provider for the class
// in the query.
//
// PARAMETERS:
//
// IN DWORD dwNamespace Namespace handle to the current
// namespace (see objdb.h)
// IN CWbemObject* pClassDef Class definition of the class in the
// query. Must be dynamic.
// IN LPWSTR Query The query string.
// IN LPWSTR QueryFormat The query language. Must be WQL.
// IN long lFlags The flags. Not used.
// OUT CFlexArray &aInstances Destinatino for the instances found.
// OUT IWbemClassObject** ppErrorObj Destination for the error object. IF
// not NULL, an error object may be placed
// here. In this case, it is the caller's
// responsibility to release it.
// RETURN VALUES:
//
// WBEM_S_NO_ERROR Success (even though there may not be
// any instances).
// WBEM_E_INVALID_PROVIDE_REGISTRATION Provider registration for this
// class is incomplete.
// WBEM_E_PROVIDER_NOT_FOUND Provider could not be located. It is not
// registered with us or with COM.
// WBEM_E_PROVIDER_NOT_CAPABLE Provider is not capable of enumerating
// instances.
// WBEM_E_FAILED Unexpected error has occured.
//
//***************************************************************************
HRESULT CWbemNamespace::Exec_DynAux_ExecQueryAsync (
CWbemObject* pClassDef, LPWSTR Query, LPWSTR QueryFormat, long lFlags, IWbemContext* pCtx, CBasicObjectSink* pSink ) {
COperationError OpInfo(pSink, L"ExecQuery", Query, FALSE); if (! OpInfo.IsOk()) return pSink->Return(WBEM_E_OUT_OF_MEMORY);
// Get the provider name.
// ======================
CVar vProv; HRESULT hres = pClassDef->GetQualifier(L"Provider", &vProv); if (FAILED(hres) || vProv.GetType() != VT_BSTR) return OpInfo.ErrorOccurred(WBEM_E_INVALID_PROVIDER_REGISTRATION);
// Access the provider cache.
// ==========================
IWbemServices *pProv = 0; HRESULT hRes; if(m_pProvFact == NULL) hRes = WBEM_E_CRITICAL_ERROR; else { WmiInternalContext t_InternalContext ; ZeroMemory ( & t_InternalContext , sizeof ( t_InternalContext ) ) ; // SEC:REVIEWED 2002-03-22 : OK
hRes = m_pProvFact->GetProvider(
t_InternalContext , 0, // lFlags
pCtx, 0, m_wszUserName, m_wsLocale, 0, // IWbemPath pointer
vProv, // Provider
IID_IWbemServices, (LPVOID *) &pProv ); }
if (FAILED(hRes)) { return pSink->Return(hRes); }
CReleaseMe _1(pProv);
// Set up the sink chain to be delivered to the provider.
// The code & destruct sequence is critical and the
// refcounting is very carefully thought out. Do not
// change this code unless you know exactly what you are
// doing. And don't even change it then.
// ======================================================
CProviderSink *pProvSink = new CProviderSink(1, Query); if (pProvSink == 0) return pSink->Return(WBEM_E_OUT_OF_MEMORY); CReleaseMe _3(pProvSink);
CDecoratingSink * pDecore = new CDecoratingSink(pSink, this); if (pDecore == NULL) return pSink->Return(WBEM_E_OUT_OF_MEMORY); pProvSink->SetNextSink(pDecore);
// Before calling the provider, map the provider to the
// task so that we can cancel it proactively, if required.
// =======================================================
hRes = ((CWmiArbitrator *) m_pArb)->MapProviderToTask(0, pCtx, pProv, pProvSink); if (FAILED(hRes)) return pSink->Return(hRes);
// Now tell the provider to start enumerating.
hRes = pProv->ExecQueryAsync(QueryFormat, Query, lFlags& ~WBEM_FLAG_USE_AMENDED_QUALIFIERS, pCtx, pProvSink);
return hRes; }
//***************************************************************************
//
// CWbemNamespace::DynAux_ExecQueryAsync
//
// Executes a SQL-1 query against a dynamic instance provider for the class
// in the query.
//
// PARAMETERS:
//
// IN DWORD dwNamespace Namespace handle to the current
// namespace (see objdb.h)
// IN CWbemObject* pClassDef Class definition of the class in the
// query. Must be dynamic.
// IN LPWSTR Query The query string.
// IN LPWSTR QueryFormat The query language. Must be WQL.
// IN long lFlags The flags. Not used.
// OUT CFlexArray &aInstances Destinatino for the instances found.
// OUT IWbemClassObject** ppErrorObj Destination for the error object. IF
// not NULL, an error object may be placed
// here. In this case, it is the caller's
// responsibility to release it.
// RETURN VALUES:
//
// WBEM_S_NO_ERROR Success (even though there may not be
// any instances).
// WBEM_E_INVALID_PROVIDE_REGISTRATION Provider registration for this
// class is incomplete.
// WBEM_E_PROVIDER_NOT_FOUND Provider could not be located. It is not
// registered with us or with COM.
// WBEM_E_PROVIDER_NOT_CAPABLE Provider is not capable of enumerating
// instances.
// WBEM_E_FAILED Unexpected error has occured.
//
//***************************************************************************
HRESULT CWbemNamespace::DynAux_ExecQueryExtendedAsync(
LPWSTR wsProvider, LPWSTR Query, LPWSTR QueryFormat, long lFlags, IWbemContext* pCtx, CComplexProjectionSink* pSink ) { COperationError OpInfo(pSink, L"ExecQuery", Query, FALSE); if ( !OpInfo.IsOk() ) return WBEM_E_OUT_OF_MEMORY;
// Access the provider cache.
// ==========================
IWbemServices *pProv = 0; HRESULT hRes; if(m_pProvFact == NULL) hRes = WBEM_E_CRITICAL_ERROR; else { WmiInternalContext t_InternalContext ; ZeroMemory ( & t_InternalContext , sizeof ( t_InternalContext ) ) ; // SEC:REVIEWED 2002-03-22 : OK
hRes = m_pProvFact->GetProvider(
t_InternalContext , 0, // lFlags
pCtx, 0, m_wszUserName, m_wsLocale, 0, // IWbemPath pointer
wsProvider, // provider name
IID_IWbemServices, (LPVOID *) &pProv ); }
if (FAILED(hRes)) { return pSink->Return(hRes); }
CReleaseMe _(pProv);
_IWmiProviderConfiguration *t_Configuration = NULL ; hRes = pProv->QueryInterface ( IID__IWmiProviderConfiguration , ( void ** ) & t_Configuration ) ; if ( SUCCEEDED ( hRes ) ) { CReleaseMe _1(t_Configuration);
VARIANT t_Variant ; VariantInit ( & t_Variant ) ;
hRes = t_Configuration->Query (
this , lFlags& ~WBEM_FLAG_USE_AMENDED_QUALIFIERS , pCtx , WBEM_PROVIDER_CONFIGURATION_CLASS_ID_INSTANCE_PROVIDER_REGISTRATION , WBEM_PROVIDER_CONFIGURATION_PROPERTY_ID_EXTENDEDQUERY_SUPPORT , & t_Variant ) ;
if ( SUCCEEDED ( hRes ) ) { if ( t_Variant.boolVal == VARIANT_TRUE ) { CDecoratingSink * pDecore = new CDecoratingSink(pSink, this); if(pDecore == NULL) return pSink->Return(WBEM_E_OUT_OF_MEMORY); pDecore->AddRef(); CReleaseMe cdecor(pDecore);
hRes = pProv->ExecQueryAsync(QueryFormat, Query, lFlags& ~WBEM_FLAG_USE_AMENDED_QUALIFIERS, pCtx, pDecore); } else { hRes = WBEM_E_INVALID_QUERY ; }
VariantClear ( & t_Variant ) ; } else { hRes = WBEM_E_UNEXPECTED ; } } else { hRes = WBEM_E_UNEXPECTED ; }
return hRes; }
//***************************************************************************
//
// CWbemNamespace::Static_QueryRepository
//
// Performs query against the repository. This only happens if there is an
// associated task. If not, then we execute the query on the same thread.
//
// PARAMETERS:
//
// READONLY CWbemObject *pClassDef The definition of the class to retrieve
// instances of.
// long lFlags The flags (deep/shallow)
//
// RETURN VALUES:
//
// WBEM_NO_ERROR No errors. This includes a no-error situation
// with zero instances returned.
// WBEM_E_INVALID_PROVIDE_REGISTRATION Provider registration for this
// class is incomplete.
// WBEM_E_PROVIDER_NOT_FOUND Provider could not be located. It is not
// registered with us or with COM.
// WBEM_E_PROVIDER_NOT_CAPABLE Provider is not capable of enumerating
// instances.
// WBEM_E_FAILED Unexpected error has occured.
//
//***************************************************************************
HRESULT CWbemNamespace::Static_QueryRepository(
READONLY CWbemObject *pClassDef, long lFlags, IWbemContext* pCtx, CBasicObjectSink* pSink , QL_LEVEL_1_RPN_EXPRESSION* pParsedQuery, LPCWSTR pwszClassName, CWmiMerger* pWmiMerger ) {
HRESULT hr = WBEM_S_NO_ERROR;
// First, get the current task and request. If there isn't one, we're most
// likely being called on an ESS callback, and will just perform the call on
// this thread.
CWbemRequest* pCurrReq = CWbemQueue::GetCurrentRequest();
if ( NULL != pCurrReq && NULL != pCurrReq->m_phTask && ConfigMgr::GetEnableQueryArbitration() ) { // We'll need the finalizer in case we need to cancel something
_IWmiFinalizer* pMainFnz = NULL; HRESULT hr = ((CWmiTask*) pCurrReq->m_phTask)->GetFinalizer( &pMainFnz ); CReleaseMe rm( pMainFnz );
if ( SUCCEEDED( hr ) ) { //
// creates the CMergerDynReq_Static_GetInstances
// creates the Merger Request Manager
// adds the request to the Request Manager
//
hr = pWmiMerger->RegisterArbitratedStaticRequest( pClassDef, lFlags, pCtx, pSink, this, pParsedQuery );
if (FAILED(hr)) { pMainFnz->CancelTask ( 0 ); }
} // IF Got Finalizer
// In the case of an error we should do a setstatus of the error. Otherwise, the setstatus will occur
// when the new request is processed.
if ( FAILED( hr ) ) { pSink->SetStatus( 0L, hr, 0L, NULL ); } } else { // If we're here, then we should disallow merger specific throttling since
// this request is happening through an internal thread without following
// the request/task hierarchy, meaning that there shouldn't be a hierarchy
// we need to worry about for this class, so don't let the merger do any
// internal throttling
pWmiMerger->EnableMergerThrottling( false );
int nRes = CQueryEngine::ExecAtomicDbQuery( GetNsSession(), GetNsHandle(), GetScope(), pwszClassName, pParsedQuery, pSink, this );
if (nRes == CQueryEngine::invalid_query) hr = WBEM_E_INVALID_QUERY; else if(nRes != 0) hr = WBEM_E_FAILED; else hr = WBEM_S_NO_ERROR;
pSink->SetStatus( 0L, hr, 0L, NULL );
}
return hr; }
//***************************************************************************
//
// CWbemNamespace::DecorateObject
//
// Sets the origin information on a given object to reflect this namespace
// and this server. See CWbemObject::Decorate in fastobj.h for details.
// THIS FUNCTION CAN ONLY DECORATE CWbemObject POINTERS, NOT OTHER PEOPLE'S
// IMPLEMENTATIONS of IWbemClassObject.
//
// PARAMETERS:
//
// IWbemClassObject* pObject The object to decorate.
//
// RETURN VALUES:
//
// WBEM_S_NO_ERROR Success
// WBEM_E_INVALID_PARAMETER pObject == NULL.
//
//***************************************************************************
HRESULT CWbemNamespace::DecorateObject(IWbemClassObject* pObject) { if(pObject == NULL) return WBEM_E_INVALID_PARAMETER;
return ((CWbemObject*)pObject)->Decorate(ConfigMgr::GetMachineName(), m_pThisNamespace); }
//***************************************************************************
//
//***************************************************************************
typedef std::vector<CDynasty*, wbem_allocator<CDynasty*> > CDynastyPtrArray; typedef std::map<LPWSTR, CDynasty*, wcsiless, wbem_allocator<CDynasty*> > CCDynastyMap;
HRESULT AddAllMembers(CDynasty* pDynasty, CCDynastyMap& Map) { // Catch any exceptions the allocator might throw
try { Map[pDynasty->m_wszClassName] = pDynasty; } catch(CX_MemoryException &) { return WBEM_E_OUT_OF_MEMORY; }
HRESULT hr = WBEM_S_NO_ERROR;
CFlexArray* pChildren = &pDynasty->m_Children; for(int i = 0; SUCCEEDED(hr) && i < pChildren->Size(); i++) { hr = AddAllMembers((CDynasty*)pChildren->GetAt(i), Map); } return hr; }
//***************************************************************************
//
// CWbemNamespace::DynAux_BuildClassHierarchy
//
// Recursively builds the hierarchy of classes derived from a given one.
// The structure used to represent the hierarchy -- CDynasty is described
// in objdb.h
//
// PARAMETERS:
//
// IN LPWSTR wszClassName The name of the parent class.
// IN LONG lFlags If SHALLOW, just the class itself is
// returned. If DEEP, recursive enumeration
// is performed.
// OUT CDynasty** ppDynasty Destination for the tree. The caller must
// delete the pointer on success.
//
// RETURN VALUES:
//
// WBEM_S_NO_ERROR Success
// Any of the return values returned by GetObject or CreateClassEnum,
// as documented in the help file.
//
//***************************************************************************
HRESULT CWbemNamespace::DynAux_BuildClassHierarchy( IN LPWSTR wszClassName, IN LONG lFlags, IN IWbemContext* pCtx, OUT wmilib::auto_ptr<CDynasty> & pDynasty, OUT IWbemClassObject** ppErrorObj) { HRESULT hres; *ppErrorObj = NULL;
// Get the list of classes from all class providers
// ================================================
CSynchronousSink* pSyncSink = CSynchronousSink::Create(); if(pSyncSink == NULL) return WBEM_E_OUT_OF_MEMORY; pSyncSink->AddRef(); CReleaseMe rm1(pSyncSink);
hres = Exec_CreateClassEnum(wszClassName, lFlags | WBEM_FLAG_NO_STATIC, pCtx, pSyncSink); pSyncSink->Block(); pSyncSink->GetStatus(&hres, NULL, ppErrorObj);
if(FAILED(hres)) return hres;
// Get the static dynasty
// ======================
wmilib::auto_ptr<CDynasty> pMainDynasty;
HRESULT hRes = CRepository::BuildClassHierarchy(m_pSession, m_pNsHandle, wszClassName, lFlags & WBEM_MASK_DEPTH, pMainDynasty);
if (hRes == WBEM_E_NOT_FOUND) { IWbemClassObject* pObj; HRESULT hres = Exec_GetObjectByPath(wszClassName, lFlags, pCtx, &pObj, ppErrorObj); if(FAILED(hres)) return hres; CReleaseMe rmClassObj(pObj); pMainDynasty.reset(CDynasty::Create(pObj)); if(NULL == pMainDynasty.get()) return WBEM_E_OUT_OF_MEMORY; if(pMainDynasty->m_pClassObj == NULL) { ERRORTRACE((LOG_WBEMCORE, "Provider returned invalid class for %S\n",wszClassName)); return WBEM_E_PROVIDER_FAILURE; } hRes = S_OK; } if (FAILED(hRes)) return hRes;
CRefedPointerArray<IWbemClassObject> &rProvidedClasses = pSyncSink->GetObjects();
// Create a map of class names to their dynasties
// ==============================================
CCDynastyMap mapClasses; hres = AddAllMembers(pMainDynasty.get(), mapClasses); if ( FAILED(hres)) return hres;
CDynastyPtrArray aProvidedDyns;
try { aProvidedDyns.reserve(rProvidedClasses.GetSize()); } catch(CX_MemoryException &) { return WBEM_E_OUT_OF_MEMORY; }
for(int i = 0; i < rProvidedClasses.GetSize(); i++) { CDynasty* pNew = CDynasty::Create(rProvidedClasses[i]); if(pNew == NULL) return WBEM_E_OUT_OF_MEMORY; if(pNew->m_pClassObj == NULL) { delete pNew; ERRORTRACE((LOG_WBEMCORE, "Provider returned invalid class!\n")); continue; }
// The vector or the map may throw exceptions
try { mapClasses[pNew->m_wszClassName] = pNew; aProvidedDyns.push_back(pNew); } catch(CX_MemoryException &) { return WBEM_E_OUT_OF_MEMORY; }
}
// Go through it once and add all classes to their parent's dynasty
// ================================================================
for(CDynastyPtrArray::iterator it = aProvidedDyns.begin(); it != aProvidedDyns.end(); it++) { CDynasty* pDyn = *it; CVar vParent; CWbemObject *pObj = (CWbemObject *) pDyn->m_pClassObj;
if(FAILED(pObj->GetSuperclassName(&vParent)) || vParent.IsNull()) { ERRORTRACE((LOG_WBEMCORE,"Provider returned top-level class %S as a child " "of %S\n", pDyn->m_wszClassName, wszClassName)); continue; }
CCDynastyMap::iterator itParent = mapClasses.find(vParent.GetLPWSTR());
if((itParent == mapClasses.end())) { if(wbem_wcsicmp(pDyn->m_wszClassName, wszClassName)) { ERRORTRACE((LOG_WBEMCORE,"Provider returned class %S without parent!\n", vParent.GetLPWSTR())); } continue; } CDynasty* pParentDyn = itParent->second; pParentDyn->AddChild(pDyn); }
// Build the chain up to the highest keyed parent
// ==============================================
pDynasty = pMainDynasty; hres = DynAux_BuildChainUp( pCtx, pDynasty, ppErrorObj);
return hres; }
//***************************************************************************
//
//***************************************************************************
HRESULT CWbemNamespace::DynAux_BuildChainUp( IN IWbemContext* pCtx, OUT wmilib::auto_ptr<CDynasty> & pTop, OUT IWbemClassObject** ppErrorObj) { *ppErrorObj = NULL;
// Go up while there is a key at this level and we are dynamic
// ===========================================================
while( pTop->IsDynamic() && pTop->IsKeyed()) { CVar vParentName; CWbemObject *pObj = (CWbemObject *) pTop->m_pClassObj;
if(FAILED(pObj->GetSuperclassName(&vParentName)) || vParentName.IsNull()) { // Top level --- time to quit
// ==========================
return WBEM_S_NO_ERROR; }
IWbemClassObject* pParent; HRESULT hres = Exec_GetObjectByPath(vParentName.GetLPWSTR(), 0,pCtx,&pParent, ppErrorObj); if(FAILED(hres)) return hres;
if(pParent == NULL) return WBEM_E_PROVIDER_FAILURE;
// SJS - Amendment is the same as Abstract
if(!((CWbemClass*)pParent)->IsKeyed() || ((CWbemClass*)pParent)->IsAbstract() || ((CWbemClass*)pParent)->IsAmendment() ) { // We are it
// =========
pParent->Release(); return WBEM_S_NO_ERROR; }
// Extend the dynasty by this class
// ================================
wmilib::auto_ptr<CDynasty> pNew( CDynasty::Create(pParent)); if (NULL == pNew.get()) return WBEM_E_OUT_OF_MEMORY; pParent->Release(); if(pNew->m_pClassObj == NULL) { return WBEM_E_PROVIDER_FAILURE; } pNew->AddChild(pTop.get()); pTop.release(); pTop.reset(pNew.release()); }
return WBEM_S_NO_ERROR; }
//***************************************************************************
//
//***************************************************************************
HRESULT CWbemNamespace::IsPutRequiredForClass(CWbemClass* pClass, CWbemInstance* pInst, IWbemContext* pCtx, BOOL bParentTakenCareOf) { HRESULT hres;
// Get the per-property put information out of the context
// =======================================================
BOOL bRestrictedPut = FALSE; BOOL bStrictNulls = FALSE; BOOL bPropertyList = FALSE; CWStringArray awsProperties;
hres = GetContextPutExtensions(pCtx, bRestrictedPut, bStrictNulls, bPropertyList, awsProperties); if(FAILED(hres)) return hres;
if(bRestrictedPut && bStrictNulls && !bPropertyList) { // All properties must be put, even the NULL ones
// ==============================================
return WBEM_S_NO_ERROR; }
// Enumerate all properties of the class
// =====================================
long lEnumFlags = 0; if(bParentTakenCareOf) { // Only look at local (non-propagated) properties
// ==============================================
lEnumFlags = WBEM_FLAG_LOCAL_ONLY; } else { // We are in charge of our parent's properties
// ===========================================
lEnumFlags = WBEM_FLAG_NONSYSTEM_ONLY; }
pClass->BeginEnumeration(lEnumFlags); BSTR strName = NULL; while((hres = pClass->Next(0, &strName, NULL, NULL, NULL)) == S_OK) { hres = DoesNeedToBePut(strName, pInst, bRestrictedPut, bStrictNulls, bPropertyList, awsProperties); SysFreeString(strName); if(hres == WBEM_S_NO_ERROR) { // Found a needed property
// =======================
return WBEM_S_NO_ERROR; } if(FAILED(hres)) return hres; }
// No properties of this class need to be put
// ==========================================
return WBEM_S_FALSE; }
//***************************************************************************
//
//***************************************************************************
HRESULT CWbemNamespace::DoesNeedToBePut(LPCWSTR wszName, CWbemInstance* pInst, BOOL bRestrictedPut, BOOL bStrictNulls, BOOL bPropertyList, CWStringArray& awsProperties) { HRESULT hres;
// Check if the property is a key
// ==============================
CVar vKey; pInst->GetPropQualifier((LPWSTR)wszName, L"key", &vKey); if(vKey.GetType() == VT_BOOL && vKey.GetBool()) { // It's a key --- no such thing as updating its value, and this code
// only applies to updates.
// =================================================================
return WBEM_S_FALSE; }
// Determine if NULLness and or membership in the list play any role
// =================================================================
BOOL bCheckNullness = FALSE; BOOL bCheckMembership = FALSE;
if(bRestrictedPut) { bCheckNullness = !bStrictNulls; bCheckMembership = bPropertyList; } else { bCheckNullness = TRUE; bCheckMembership = FALSE; }
// Check NULLness and/or membership if required
// ============================================
BOOL bNullnessChecked = FALSE; BOOL bMembershipChecked = FALSE;
if(bCheckNullness) { CVar vVal; hres = pInst->GetNonsystemPropertyValue((LPWSTR)wszName, &vVal); if(FAILED(hres)) return hres;
bNullnessChecked = !vVal.IsNull(); } else bNullnessChecked = TRUE;
if(bCheckMembership) { int nIndex = awsProperties.FindStr(wszName, CWStringArray::no_case); bMembershipChecked = (nIndex >= 0); } else bMembershipChecked = TRUE;
// Make sure that both NULLness and membership either checked out or were
// not required
// ======================================================================
if(bMembershipChecked && bNullnessChecked) { return WBEM_S_NO_ERROR; } else { return WBEM_S_FALSE; } }
//***************************************************************************
//
//***************************************************************************
HRESULT CWbemNamespace::GetContextPutExtensions(IWbemContext* pCtx, BOOL& bRestrictedPut, BOOL& bStrictNulls, BOOL& bPropertyList, CWStringArray& awsProperties) { HRESULT hres;
if(pCtx == NULL) { //
// Default is: no restructions, which makes the rest of the properties
// irrelevant
//
bRestrictedPut = FALSE; return WBEM_S_NO_ERROR; }
// Initialize out-params
// =====================
bRestrictedPut = FALSE; bStrictNulls = FALSE; bPropertyList = FALSE; awsProperties.Empty();
// Check if the context is even present
// ====================================
if(pCtx == NULL) return WBEM_S_NO_ERROR;
// Check if put extensions are specified
// =====================================
hres = GetContextBoolean(pCtx, L"__PUT_EXTENSIONS", &bRestrictedPut); if(FAILED(hres)) return hres;
if(!bRestrictedPut) return WBEM_S_NO_ERROR;
// Check if NULLs are strict
// =========================
hres = GetContextBoolean(pCtx, L"__PUT_EXT_STRICT_NULLS", &bStrictNulls); if(FAILED(hres)) return hres;
// Check if the list of properties is available
// ============================================
VARIANT v; VariantInit(&v); CClearMe cm1(&v);
hres = pCtx->GetValue(L"__PUT_EXT_PROPERTIES", 0, &v); if(FAILED(hres)) { if(hres == WBEM_E_NOT_FOUND) { return WBEM_S_NO_ERROR; } else { ERRORTRACE((LOG_WBEMCORE, "Error retrieving list of properties " "from context: %X\n", hres)); return hres; } }
if(V_VT(&v) != (VT_BSTR | VT_ARRAY)) { ERRORTRACE((LOG_WBEMCORE, "Invalid type is used for " "the list of properties in the context: must be " "string array. The value will be ignored\n")); return WBEM_S_NO_ERROR; }
bPropertyList = TRUE;
// Transfer property names to the array
// ====================================
CSafeArray saProperties(V_ARRAY(&v), VT_BSTR, CSafeArray::no_delete | CSafeArray::bind);
for(int i = 0; i < saProperties.Size(); i++) { BSTR strProp = saProperties.GetBSTRAt(i); CSysFreeMe sfm(strProp); if (strProp) { if (CFlexArray::no_error != awsProperties.Add(strProp)) return WBEM_E_OUT_OF_MEMORY; } }
return WBEM_S_NO_ERROR; }
//***************************************************************************
//
//***************************************************************************
HRESULT CWbemNamespace::GetContextBoolean(IWbemContext* pCtx, LPCWSTR wszName, BOOL* pbValue) { HRESULT hres; *pbValue = FALSE;
//
// NULL context means "FALSE"
//
if(pCtx == NULL) return WBEM_S_NO_ERROR;
VARIANT v; VariantInit(&v); CClearMe cm1(&v);
hres = pCtx->GetValue((LPWSTR)wszName, 0, &v); if(FAILED(hres)) { if(hres == WBEM_E_NOT_FOUND) { return WBEM_S_NO_ERROR; } else { ERRORTRACE((LOG_WBEMCORE, "Error retrieving context property %S:" " %X\n", wszName, hres)); return hres; } }
if(V_VT(&v) != VT_BOOL) { ERRORTRACE((LOG_WBEMCORE, "Invalid type is used for " "%S property of the context: must be " "boolean. The value will be ignored\n", wszName)); return WBEM_S_NO_ERROR; }
if(V_BOOL(&v) != VARIANT_TRUE) { return WBEM_S_NO_ERROR; }
*pbValue = TRUE; return WBEM_S_NO_ERROR; }
//***************************************************************************
//
//***************************************************************************
STDMETHODIMP CWbemNamespace::FindKeyRoot(LPCWSTR wszClassName, IWbemClassObject** ppKeyRootClass) { //
// Check if the namespace is still valid (returns if not)
//
HRESULT hRes = CheckNs(); if (FAILED(hRes)) return hRes;
//
// Call on the database to do the job
//
hRes = CRepository::FindKeyRoot(m_pSession, m_pNsHandle, wszClassName, ppKeyRootClass);
return hRes; }
//***************************************************************************
//
//***************************************************************************
STDMETHODIMP CWbemNamespace::GetNormalizedPath( BSTR pstrPath, BSTR* pstrStandardPath ) { //
// Check if the namespace is still valid (returns if not)
//
HRESULT hRes = CheckNs(); if (FAILED(hRes)) return hRes;
//
// check parameters.
//
if ( NULL == pstrPath || NULL == pstrStandardPath ) { return WBEM_E_INVALID_PARAMETER; }
HRESULT hres; *pstrStandardPath = NULL;
// Parse it
// ========
CObjectPathParser Parser; ParsedObjectPath* pPath;
int nRes = Parser.Parse(pstrPath, &pPath);
if( nRes != CObjectPathParser::NoError ) { return WBEM_E_INVALID_OBJECT_PATH; }
CDeleteMe<ParsedObjectPath> dm(pPath);
//
// Figure out the class that defined the key
//
IWbemClassObject* pKeyRootClass = NULL;
hres = FindKeyRoot(pPath->m_pClass, &pKeyRootClass);
if(FAILED(hres)) { return hres; }
CReleaseMe rm(pKeyRootClass);
_IWmiObject* pWmiObject = NULL; hres = pKeyRootClass->QueryInterface(IID__IWmiObject, (void**)&pWmiObject);
if(FAILED(hres)) { return hres; }
CReleaseMe rm1(pWmiObject);
long lHandle = 0L; ULONG uFlags = 0L; WCHAR wszClassName[64]; DWORD dwBuffSize = 64; DWORD dwBuffUsed = 0; BOOL fNull = FALSE; LPWSTR pwszName = wszClassName; LPWSTR pwszDelete = NULL;
// Try to read in the class name. Allocate a buffer if we have to.
hres = pWmiObject->ReadProp( L"__CLASS", 0L, dwBuffSize, NULL, NULL, &fNull, &dwBuffUsed, pwszName );
if ( FAILED( hres ) ) { if ( WBEM_E_BUFFER_TOO_SMALL == hres ) { pwszName = new WCHAR[dwBuffUsed/2];
if ( NULL == pwszName ) { return WBEM_E_OUT_OF_MEMORY; } else { dwBuffSize = dwBuffUsed;
// Try to read in the class name. Allocate a buffer if we have to.
hres = pWmiObject->ReadProp( L"__CLASS", 0L, dwBuffSize, NULL, NULL, &fNull, &dwBuffUsed, pwszName );
if ( FAILED( hres ) ) { delete [] pwszName; return hres; }
// Allows for scoped cleanup only if we alloctaed something
pwszDelete = pwszName; } } else { return hres; } }
//
// Ensures proper cleanup. If we didn't allocate a buffer to delete,
// this pointer will be NULL.
//
CVectorDeleteMe<WCHAR> vdm1(pwszDelete);
// oop
if ( fNull ) { return WBEM_E_INVALID_OPERATION; }
//
// want to normalize out the single key prop exception
//
if ( pPath->m_dwNumKeys == 1 ) { delete pPath->m_paKeys[0]->m_pName; pPath->m_paKeys[0]->m_pName = NULL; }
//
// set the normalized class on the path if different
// than the one in the path.
//
if ( wbem_wcsicmp( pPath->m_pClass, pwszName ) != 0 ) { if ( !pPath->SetClassName( pwszName ) ) { return WBEM_E_OUT_OF_MEMORY; } }
//
// now unparse the normalized path
//
LPWSTR wszNormPath;
nRes = CObjectPathParser::Unparse( pPath, &wszNormPath );
if ( nRes != CObjectPathParser::NoError ) { return WBEM_E_OUT_OF_MEMORY; }
*pstrStandardPath = SysAllocString( wszNormPath );
delete wszNormPath;
return *pstrStandardPath != NULL ? WBEM_S_NO_ERROR : WBEM_E_OUT_OF_MEMORY; }
class CRevertCallSec { BOOL m_bEnabled; IUnknown * m_pCallSec; public: CRevertCallSec(BOOL bEnabled,IUnknown * pCallSec): m_bEnabled(bEnabled), m_pCallSec(pCallSec){}; ~CRevertCallSec(){ if (m_bEnabled){ IUnknown * pOld = NULL; CoSwitchCallContext(m_pCallSec,&pOld); } }; };
//***************************************************************************
//
//***************************************************************************
STDMETHODIMP CWbemNamespace::InternalGetClass( LPCWSTR wszClassName, IWbemClassObject** ppClass) { if (g_bDontAllowNewConnections || m_bShutDown) { return WBEM_E_SHUTTING_DOWN; }
IWbemContext *pContext = NULL ;
CWbemRequest* pReq = CWbemQueue::GetCurrentRequest() ; if (pReq == NULL) { pContext = ConfigMgr::GetNewContext(); if ( pContext == NULL ) return WBEM_E_OUT_OF_MEMORY; } else { pContext = pReq->GetContext(); pContext->AddRef () ; //for CReleaseMe
}
CReleaseMe _1_pContext (pContext) ;
HRESULT hr;
// determine if there is a call context. If there is, then we
// dont do anything.
IServerSecurity * pSec = NULL; IWbemCallSecurity * pCallSec = NULL; IUnknown * pOld = NULL, *pNew = NULL; hr = CoGetCallContext(IID_IServerSecurity, (void**)&pSec); if(SUCCEEDED(hr)) { pSec->Release(); } else { // provider subsystem needs a call context, so create on
pCallSec = CWbemCallSecurity::CreateInst(); if(pCallSec == NULL) return WBEM_E_OUT_OF_MEMORY; } CReleaseMe rm(pCallSec);
// initialize call security for provider sub system
if(pCallSec) { hr = pCallSec->CloneThreadContext(TRUE); if(FAILED(hr)) return hr; hr = CoSwitchCallContext(pCallSec, &pOld); if(FAILED(hr)) return hr; } CRevertCallSec Revert(pCallSec?TRUE:FALSE,pOld); // SEC:REVIEWED 2002-03-22 : Assumes success; why is this here? It is the only occurrence.
hr = Exec_GetObjectByPath((LPWSTR)wszClassName, 0, pContext, ppClass, NULL);
return hr; }
//***************************************************************************
//
//***************************************************************************
STDMETHODIMP CWbemNamespace::InternalGetInstance( LPCWSTR wszPath, IWbemClassObject** ppInstance) { if (g_bDontAllowNewConnections || m_bShutDown) { return WBEM_E_SHUTTING_DOWN; }
IWbemContext *pContext = NULL ;
CWbemRequest* pReq = CWbemQueue::GetCurrentRequest() ; if (pReq == NULL) { pContext = ConfigMgr::GetNewContext(); if ( pContext == NULL ) return WBEM_E_OUT_OF_MEMORY; } else { pContext = pReq->GetContext(); pContext->AddRef () ; //for CReleaseMe
}
CReleaseMe _1_pContext (pContext) ;
return Exec_GetObjectByPath((LPWSTR)wszPath, 0, pContext, ppInstance, NULL); }
//***************************************************************************
//
//***************************************************************************
STDMETHODIMP CWbemNamespace::InternalExecQuery( LPCWSTR wszQueryLanguage, LPCWSTR wszQuery, long lFlags, IWbemObjectSink* pSink) { if (g_bDontAllowNewConnections || m_bShutDown) { return WBEM_E_SHUTTING_DOWN; }
IWbemContext *pContext = NULL ;
CWbemRequest* pReq = CWbemQueue::GetCurrentRequest() ; if (pReq == NULL) { pContext = ConfigMgr::GetNewContext(); if ( pContext == NULL ) return WBEM_E_OUT_OF_MEMORY; } else { pContext = pReq->GetContext(); pContext->AddRef () ; //for CReleaseMe
}
CReleaseMe _1_pContext (pContext) ;
CSimpleWrapperSink ws(pSink); return CQueryEngine::ExecQuery(this, (LPWSTR)wszQueryLanguage, (LPWSTR)wszQuery, lFlags, pContext, &ws); }
//***************************************************************************
//
//***************************************************************************
STDMETHODIMP CWbemNamespace::InternalCreateInstanceEnum( LPCWSTR wszClassName, long lFlags, IWbemObjectSink* pSink) { if (g_bDontAllowNewConnections || m_bShutDown) { return WBEM_E_SHUTTING_DOWN; }
IWbemContext *pContext = NULL ;
CWbemRequest* pReq = CWbemQueue::GetCurrentRequest() ; if (pReq == NULL) { pContext = ConfigMgr::GetNewContext(); if ( pContext == NULL ) return WBEM_E_OUT_OF_MEMORY; } else { pContext = pReq->GetContext(); pContext->AddRef () ; //for CReleaseMe
}
CReleaseMe _1_pContext (pContext) ;
CSimpleWrapperSink ws(pSink); return Exec_CreateInstanceEnum((LPWSTR)wszClassName, lFlags, pContext, &ws); }
//***************************************************************************
//
//***************************************************************************
STDMETHODIMP CWbemNamespace::InternalPutInstance( IWbemClassObject* pInst) { if (g_bDontAllowNewConnections || m_bShutDown) { return WBEM_E_SHUTTING_DOWN; }
IWbemContext *pContext = NULL ;
CWbemRequest* pReq = CWbemQueue::GetCurrentRequest() ; if (pReq == NULL) { pContext = ConfigMgr::GetNewContext(); if ( pContext == NULL ) return WBEM_E_OUT_OF_MEMORY; } else { pContext = pReq->GetContext(); pContext->AddRef () ; //for CReleaseMe
}
CReleaseMe _1_pContext (pContext) ;
CSynchronousSink* pSink = CSynchronousSink::Create(); if(pSink == NULL) return WBEM_E_OUT_OF_MEMORY; pSink->AddRef(); CReleaseMe rm1(pSink);
Exec_PutInstance(pInst, 0, pContext, pSink);
HRESULT hres = WBEM_E_CRITICAL_ERROR; pSink->GetStatus(&hres, NULL, NULL); return hres; }
//***************************************************************************
//
//***************************************************************************
STDMETHODIMP CWbemNamespace::GetDbInstance( LPCWSTR wszDbKey, IWbemClassObject** ppInstance ) { // ESS uses this one
return CRepository::GetObject(m_pSession, m_pScopeHandle, wszDbKey, 0, ppInstance); }
//***************************************************************************
//
//***************************************************************************
STDMETHODIMP CWbemNamespace::GetDbReferences( IWbemClassObject* pEndpoint, IWbemObjectSink* pSink) { LPWSTR wszRelPath = ((CWbemObject*)pEndpoint)->GetRelPath(); CVectorDeleteMe<WCHAR> dm(wszRelPath);
CSimpleWrapperSink ws(pSink);
HRESULT hRes = CRepository::GetInstanceRefs(m_pSession,m_pScopeHandle, wszRelPath, &ws);
return hRes; }
//***************************************************************************
//
//***************************************************************************
HRESULT CWbemNamespace::InternalPutStaticClass( IWbemClassObject* pClass) { if (g_bDontAllowNewConnections || m_bShutDown) { return WBEM_E_SHUTTING_DOWN; }
IWbemContext *pContext = NULL ;
CWbemRequest* pReq = CWbemQueue::GetCurrentRequest() ; if (pReq == NULL) { pContext = ConfigMgr::GetNewContext(); if ( pContext == NULL ) return WBEM_E_OUT_OF_MEMORY; } else { pContext = pReq->GetContext(); pContext->AddRef () ; //for CReleaseMe
}
CReleaseMe _1_pContext (pContext) ;
CSynchronousSink* pSink = CSynchronousSink::Create(); if(pSink == NULL) return WBEM_E_OUT_OF_MEMORY; pSink->AddRef(); CReleaseMe rm1(pSink);
Exec_PutClass( pClass, 0, pContext, pSink, TRUE );
HRESULT hres = WBEM_E_CRITICAL_ERROR; pSink->GetStatus(&hres, NULL, NULL); return hres; }
//***************************************************************************
//
// CWbemNamespace::AdjustPutContext
//
//***************************************************************************
HRESULT CWbemNamespace::AdjustPutContext( IWbemContext *pCtx ) { // See if per-property puts are being used.
// ========================================
HRESULT hRes;
if (pCtx == 0) return WBEM_S_NO_ERROR;
CVARIANT v; hRes = pCtx->GetValue(L"__PUT_EXTENSIONS", 0, &v);
if (SUCCEEDED(hRes)) { // If here, they are being used. Next we have to check and see
// if the reentrancy flag is set or not.
// =============================================================
hRes = pCtx->GetValue(L"__PUT_EXT_CLIENT_REQUEST", 0, &v); if (SUCCEEDED(hRes)) { pCtx->DeleteValue(L"__PUT_EXT_CLIENT_REQUEST", 0); return WBEM_S_NO_ERROR; }
// If here, we have to clear out the put extensions.
// =================================================
pCtx->DeleteValue(L"__PUT_EXTENSIONS", 0); pCtx->DeleteValue(L"__PUT_EXT_CLIENT_REQUEST", 0); pCtx->DeleteValue(L"__PUT_EXT_ATOMIC", 0); pCtx->DeleteValue(L"__PUT_EXT_PROPERTIES", 0); pCtx->DeleteValue(L"__PUT_EXT_STRICT_NULLS", 0); }
return WBEM_S_NO_ERROR; }
//***************************************************************************
//
// CWbemNamespace::MergeGetKeysCtx
//
//***************************************************************************
//
HRESULT CWbemNamespace::MergeGetKeysCtx( IN IWbemContext *pCtx ) { HRESULT hRes; if (pCtx == 0) return WBEM_S_NO_ERROR; CVARIANT v; v.SetBool(TRUE); hRes = pCtx->SetValue(L"__GET_EXTENSIONS", 0, &v); hRes |= pCtx->SetValue(L"__GET_EXT_KEYS_ONLY", 0, &v); hRes |= pCtx->SetValue(L"__GET_EXT_CLIENT_REQUEST", 0, &v); return hRes; }
//***************************************************************************
//
// CWbemNamespace::CheckNs
//
// Does a quick check on the available system resources before allowing
// a new call to proceed. Retries for 30 seconds.
//
//***************************************************************************
//
HRESULT CWbemNamespace::CheckNs() { HRESULT hr = WBEM_S_NO_ERROR;
if (g_bDontAllowNewConnections || m_bShutDown) { return WBEM_E_SHUTTING_DOWN; }
// Quick memory check. If we are strapped for RAM/Pagefile,
// wait a while and try again. Requirements are 1 meg of
// available RAM and 1 meg of available page file.
int nRetries = 0;
for (int i = 0; i < 30; i++) { MEMORYSTATUS ms; GlobalMemoryStatus(&ms);
if (ms.dwMemoryLoad < 99) return WBEM_S_NO_ERROR;
// If here, we have to be careful. The system is loaded at 99%.
// =============================================================
if (nRetries > 30) { // Sixty seconds waiting for enough memory. Give up.
return WBEM_E_OUT_OF_MEMORY; }
DWORD dwPracticalMemory = ms.dwAvailPhys + ms.dwAvailPageFile;
if (dwPracticalMemory < 0x200000) // 2 meg
{ Sleep(2000); // Try a 1 meg allocation to see if will succeed.
LPVOID pTestMem = HeapAlloc(GetProcessHeap(), 0, 0x100000); if (pTestMem == 0) { return WBEM_E_OUT_OF_MEMORY; } // Free the memory. The previous allocation may have
// grown the pagefile and thus we can succeed.
HeapFree(GetProcessHeap(), 0, pTestMem); nRetries++; } else { // If here, we have a load of 99%, yet more than 2 meg of memory
// still available. Now 99% may mean there is a lot of free memory
// because the machine has huge resources or it may mean we are just
// about out of memory completely. We need hard data. If we
// have at least 5 meg anyway, this is clearly adequate, so we just
// break out of the loop and let the call continue.
//
// Otherwise, we have between 2 and 5 meg, which is starting to push
// it. We enter a waiting loop and hope for more memory. After a few
// retries if we continue to have between 2 and 5 meg, we'll let the call
// through and let the arbitrator deal with it, since the system appears
// to have stabilized at this usage.
//
hr = WBEM_S_NO_ERROR;
if (ms.dwAvailPhys < 0x200000) // If low on physical memory back off a bit for recovery via pagefile
Sleep(1000);
if (dwPracticalMemory > 0x100000 * 5) // > 5 meg; break out immediately
break;
// Under 5 meg free, retry a few times to let things clear up and get
// more memory. But, we succeed in the end anyway.
// ==================================================================
Sleep(1000); if (nRetries++ > 5) { hr = WBEM_S_NO_ERROR; break; } } }
return hr; }
//***************************************************************************
//
//***************************************************************************
//
HRESULT CWbemNamespace::UniversalConnect( CWbemNamespace *pParent, IWbemContext *pCtx, LPCWSTR pszNewScope, LPCWSTR pszAssocSelector, LPCWSTR pszUserName, _IWmiCallSec *pCallSec, _IWmiUserHandle *pUser, DWORD dwUserFlags, DWORD dwInternalFlags, DWORD dwSecFlags, DWORD dwPermission, BOOL bForClient, BOOL bRepositOnly, LPCWSTR pszClientMachineName, DWORD dwClientProcessID, IN REFIID riid, OUT LPVOID *pConnection ) { HRESULT hRes; if(dwUserFlags & WBEM_FLAG_CONNECT_REPOSITORY_ONLY) bRepositOnly = TRUE; // Validate.
if (pszNewScope == 0) return WBEM_E_INVALID_PARAMETER;
if (riid != IID_IWbemServices ) return E_NOINTERFACE;
// If no parent, then this is an 'absolute' connect.
// =================================================
if (!pParent) { CWbemNamespace *pNs = CWbemNamespace::CreateInstance(); if (NULL == pNs) return WBEM_E_OUT_OF_MEMORY;
hRes = pNs->Initialize( LPWSTR(pszNewScope), LPWSTR(pszUserName), dwSecFlags, dwPermission, bForClient, bRepositOnly, pszClientMachineName, dwClientProcessID, FALSE, NULL);
if (FAILED(hRes)) { pNs->Release(); return hRes; }
pNs->SetIsProvider((dwUserFlags & WBEM_FLAG_CONNECT_PROVIDERS)?TRUE:FALSE);
*pConnection = pNs; return WBEM_S_NO_ERROR; } else { return WBEM_E_INVALID_OPERATION; }
}
//***************************************************************************
//
// Called by _IWmiCoreServices to establish a connection from the 'outside'.
//
//***************************************************************************
//
HRESULT CWbemNamespace::PathBasedConnect( /* [in] */ LPCWSTR pszPath, /* [in] */ LPCWSTR pszUser, /* [in] */ IWbemContext __RPC_FAR *pCtx, /* [in] */ ULONG uClientFlags, /* [in] */ DWORD dwSecFlags, /* [in] */ DWORD dwPermissions, /* [in] */ ULONG uInternalFlags, /* [in] */ LPCWSTR pszClientMachineName, /* [in] */ DWORD dwClientProcessID, /* [in] */ REFIID riid, /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *pServices ) { HRESULT hRes;
BOOL bForClient = FALSE;
if ((uInternalFlags & WMICORE_CLIENT_ORIGIN_LOCAL) || (uInternalFlags & WMICORE_CLIENT_ORIGIN_REMOTE) || (uInternalFlags & WMICORE_CLIENT_TYPE_ALT_TRANSPORT) ) { bForClient = TRUE; }
hRes = UniversalConnect( 0, // Parent CWbemNamespace; not known
pCtx, // Context
pszPath, // Path
0, // No assoc selector at this point
pszUser, // User
0, // Call security
0, // User handle
uClientFlags, // Flags from client
uInternalFlags, // Internal flags
dwSecFlags, // Copy
dwPermissions, // Copy
bForClient, // For client?
FALSE, // Repository only
pszClientMachineName, dwClientProcessID, riid, pServices );
return hRes; }
//***************************************************************************
//
//***************************************************************************
//
HRESULT CWbemNamespace::InitNewTask( IN CAsyncReq *pReq, IN _IWmiFinalizer *pFnz, IN ULONG uTaskType, IN IWbemContext *pCtx, IN IWbemObjectSink *pAsyncClientSink ) { HRESULT hRes;
if (pReq == 0 || pFnz == 0) return WBEM_E_INVALID_PARAMETER; // Create a task for tracking the operation.
// =========================================
CWmiTask *pNewTask = CWmiTask::CreateTask(); if (pNewTask == 0) return WBEM_E_OUT_OF_MEMORY; CReleaseMe _2(pNewTask);
hRes = pNewTask->Initialize(this, uTaskType, pCtx, pAsyncClientSink,pReq); if (FAILED(hRes)) return hRes;
hRes = pFnz->SetTaskHandle((_IWmiCoreHandle *) pNewTask); if (FAILED(hRes)) return hRes;
pReq->SetTaskHandle((_IWmiCoreHandle *) pNewTask);
return WBEM_S_NO_ERROR; }
//***************************************************************************
//
//***************************************************************************
//
HRESULT CWbemNamespace::CreateSyncFinalizer( IN IWbemContext *pCtx, IN _IWmiFinalizer **pResultFnz ) { HRESULT hRes;
ULONG uFlags = WMI_FNLZR_FLAG_FAST_TRACK;
// Determine calling context to see if the call is reentrant or what.
// ==================================================================
IWbemCausalityAccess *pCaus = 0; if (pCtx != 0) { hRes = pCtx->QueryInterface(IID_IWbemCausalityAccess, (LPVOID *) &pCaus); if (SUCCEEDED(hRes)) { long lNumParents = 0; long lNumSiblings = 0; pCaus->GetHistoryInfo(&lNumParents, &lNumSiblings); if (lNumParents) uFlags = WMI_FNLZR_FLAG_FAST_TRACK; pCaus->Release(); } }
// Create Finalizer.
// =================
_IWmiFinalizer *pFnz = 0; hRes = m_pCoreSvc->CreateFinalizer(0, &pFnz); if (FAILED(hRes)) return hRes; CReleaseMe _(pFnz);
hRes = pFnz->Configure(uFlags, 0); if (FAILED(hRes)) return hRes;
pFnz->AddRef(); *pResultFnz = pFnz; return WBEM_S_NO_ERROR; }
//***************************************************************************
//
//***************************************************************************
//
HRESULT CWbemNamespace::CreateAsyncFinalizer( IWbemContext *pCtx, IWbemObjectSink *pStartingSink, _IWmiFinalizer **pResultFnz, IWbemObjectSink **pResultSinkEx ) { HRESULT hRes;
ULONG uFlags = WMI_FNLZR_FLAG_FAST_TRACK;
if ( m_bForClient ) uFlags = WMI_FNLZR_FLAG_DECOUPLED;
// Determine calling context to see if the call is reentrant or what.
// ==================================================================
IWbemCausalityAccess *pCaus = 0; if (pCtx != 0) { hRes = pCtx->QueryInterface(IID_IWbemCausalityAccess, (LPVOID *) &pCaus); if (SUCCEEDED(hRes)) { long lNumParents = 0; long lNumSiblings = 0; pCaus->GetHistoryInfo(&lNumParents, &lNumSiblings); if (lNumParents) uFlags = WMI_FNLZR_FLAG_FAST_TRACK; pCaus->Release(); } }
// Create Finalizer.
// =================
_IWmiFinalizer *pFnz = 0; hRes = m_pCoreSvc->CreateFinalizer(0, &pFnz); if (FAILED(hRes)) return hRes; CReleaseMe _(pFnz);
hRes = pFnz->Configure(uFlags, 0); if (FAILED(hRes)) return hRes;
hRes = pFnz->SetDestinationSink(0, IID_IWbemObjectSink, (LPVOID) pStartingSink);
if (FAILED(hRes)) return hRes;
hRes = pFnz->NewInboundSink(0, pResultSinkEx); if (FAILED(hRes)) return hRes;
pFnz->AddRef(); *pResultFnz = pFnz; return WBEM_S_NO_ERROR; }
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//
// Native async operations
//
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//
// InstEnum Sync[ ] Async Impl[x] AsyncEntry[x]
// ClassEnum Sync[ ] Async Impl[x] AsyncEntry[x]
//
// PutInst Sync[ ] Async Impl[x] AsyncEntry[x]
// PutClass Sync[ ] Async Impl[x] AsyncEntry[x]
// DelInst Sync[ ] Async Impl[x] AsyncEntry[x]
// DelClass Sync[ ] Async Impl[x] AsyncEntry[x]
//
// GetObject Sync[ ] Async Impl[x] AsyncEntry[x]
//
// ExecQuery Sync[ ] Async Impl[x] AsyncEntry[x]
// ExecMethod Sync[ ] Async Impl[x] AsyncEntry[x]
//
//
//***************************************************************************
//
//***************************************************************************
// ok
HRESULT CWbemNamespace::DeleteClassAsync( const BSTR strClass, long lFlags, IWbemContext* pCtx, IWbemObjectSink* pHandler ) { try { return _DeleteClassAsync( WMICORE_TASK_TYPE_ASYNC | WMICORE_TASK_DELETE_CLASS, 0, 0, strClass, lFlags, pCtx, pHandler ); } catch (...) { ExceptionCounter c; return WBEM_E_CRITICAL_ERROR; } }
//***************************************************************************
//
//***************************************************************************
// ok
HRESULT CWbemNamespace::CreateClassEnumAsync( const BSTR strParent, long lFlags, IWbemContext* pCtx, IWbemObjectSink* pHandler ) { try { return _CreateClassEnumAsync( WMICORE_TASK_TYPE_ASYNC | WMICORE_TASK_ENUM_CLASSES, 0, 0, strParent, lFlags, pCtx, pHandler ); } catch (...) { ExceptionCounter c; return WBEM_E_CRITICAL_ERROR; } }
//***************************************************************************
//
//***************************************************************************
// ok
HRESULT CWbemNamespace::PutClassAsync( READONLY IWbemClassObject* pObj, long lFlags, IWbemContext* pCtx, IWbemObjectSink* pHandler ) { try { return _PutClassAsync( WMICORE_TASK_TYPE_ASYNC | WMICORE_TASK_PUT_CLASS, 0, 0, pObj, lFlags, pCtx, pHandler ); } catch (...) { ExceptionCounter c; return WBEM_E_CRITICAL_ERROR; } }
//***************************************************************************
//
//***************************************************************************
// ok
HRESULT CWbemNamespace::PutInstanceAsync( IWbemClassObject* pInst, long lFlags, IWbemContext* pCtx, IWbemObjectSink* pHandler ) { try { return _PutInstanceAsync(WMICORE_TASK_TYPE_ASYNC| WMICORE_TASK_PUT_INSTANCE, 0, 0, pInst, lFlags, pCtx, pHandler); } catch (...) { ExceptionCounter c; return WBEM_E_CRITICAL_ERROR; } }
//***************************************************************************
//
//***************************************************************************
// ok
HRESULT CWbemNamespace::DeleteInstanceAsync( const BSTR strObjectPath, long lFlags, IWbemContext* pCtx, IWbemObjectSink* pHandler ) { try { return _DeleteInstanceAsync( WMICORE_TASK_TYPE_ASYNC| WMICORE_TASK_DELETE_INSTANCE, 0, 0, strObjectPath, lFlags, pCtx, pHandler ); } catch (...) { ExceptionCounter c; return WBEM_E_CRITICAL_ERROR; } }
//***************************************************************************
//
//***************************************************************************
// ok
HRESULT CWbemNamespace::CreateInstanceEnumAsync( const BSTR strClass, long lFlags, IWbemContext* pCtx, IWbemObjectSink* pHandler ) { try { return _CreateInstanceEnumAsync( WMICORE_TASK_TYPE_ASYNC | WMICORE_TASK_ENUM_INSTANCES, 0, 0, strClass, lFlags, pCtx, pHandler ); } catch (...) { ExceptionCounter c; return WBEM_E_CRITICAL_ERROR; } }
//***************************************************************************
//
//***************************************************************************
// ok
HRESULT CWbemNamespace::ExecQueryAsync( const BSTR strQueryFormat, const BSTR strQuery, long lFlags, IWbemContext* pCtx, IWbemObjectSink* pHandler ) { try { return _ExecQueryAsync(WMICORE_TASK_TYPE_ASYNC | WMICORE_TASK_EXEC_QUERY, 0, 0, strQueryFormat, strQuery, lFlags, pCtx, pHandler); } catch(...) { ExceptionCounter c; return WBEM_E_CRITICAL_ERROR; } }
//***************************************************************************
//
//***************************************************************************
// ok
HRESULT CWbemNamespace::ExecMethodAsync( const BSTR ObjectPath, const BSTR MethodName, long lFlags, IWbemContext *pCtx, IWbemClassObject *pInParams, IWbemObjectSink* pHandler ) { try { return _ExecMethodAsync(WMICORE_TASK_TYPE_ASYNC | WMICORE_TASK_EXEC_METHOD, 0, 0, ObjectPath, MethodName, lFlags, pCtx, pInParams, pHandler); } catch (...) { ExceptionCounter c; return WBEM_E_CRITICAL_ERROR; } }
//***************************************************************************
//
//***************************************************************************
//
HRESULT CWbemNamespace::GetObjectAsync( const BSTR strObjectPath, long lFlags, IWbemContext* pCtx, IWbemObjectSink* pHandler ) { HRESULT hRes = CheckNs(); if (FAILED(hRes)) return hRes; if (!Allowed(WBEM_ENABLE)) return WBEM_E_ACCESS_DENIED;
try { return _GetObjectAsync( WMICORE_TASK_TYPE_ASYNC | WMICORE_TASK_GET_OBJECT, 0, 0, strObjectPath, lFlags, pCtx, pHandler ); } catch (...) { ExceptionCounter c; return WBEM_E_CRITICAL_ERROR; } }
//
// can throw
//
///////////////////////////////////////////////////////////////////////
HRESULT CWbemNamespace::_PutInstanceAsync( IN ULONG uInternalFlags, IN _IWmiFinalizer *pFnz, IN _IWmiCoreHandle *phTask, IWbemClassObject* pInst, long lFlags, IWbemContext* pCtx, IWbemObjectSink* pHandler ) { HRESULT hRes = CheckNs(); if (FAILED(hRes)) return hRes;
DEBUGTRACE((LOG_WBEMCORE, "CALL CWbemNamespace::PutInstanceAsync" " long lFlags = 0x%X\n" " IWbemClassObject *pInst = 0x%X\n" " IWbemObjectSink* pHandler = 0x%X\n", lFlags, pInst, pHandler ));
// Parameter and object validation.
// ================================
if (pFnz == 0 && pHandler == 0) return WBEM_E_INVALID_PARAMETER;
if (pInst == NULL) return WBEM_E_INVALID_PARAMETER;
long lMainFlags = lFlags & ~WBEM_FLAG_SEND_STATUS & ~WBEM_FLAG_USE_AMENDED_QUALIFIERS & ~WBEM_FLAG_OWNER_UPDATE;
if (lMainFlags != WBEM_FLAG_CREATE_ONLY && lMainFlags != WBEM_FLAG_UPDATE_ONLY && lMainFlags != WBEM_FLAG_CREATE_OR_UPDATE) { return WBEM_E_INVALID_PARAMETER; } if (!m_bProvider && (lFlags & WBEM_FLAG_OWNER_UPDATE)) { return WBEM_E_INVALID_PARAMETER; }
if (lFlags & WBEM_FLAG_OWNER_UPDATE) { lFlags -= WBEM_FLAG_OWNER_UPDATE; lFlags += WBEM_FLAG_NO_EVENTS; }
// Check for per-property put context info.
// ========================================
if (pCtx) AdjustPutContext(pCtx);
// Create Finalizer.
// =================
IWbemObjectSink *pPseudoSink = 0; if (pFnz == 0) { hRes = CreateAsyncFinalizer(pCtx, pHandler, &pFnz, &pPseudoSink); if (FAILED(hRes)) return hRes; } else // borrowed finalizer
{ hRes = pFnz->NewInboundSink(0, &pPseudoSink); if (FAILED(hRes)) return hRes; pFnz->AddRef(); }
CReleaseMe _1(pPseudoSink); CReleaseMe _2(pFnz);
// Schedule the request.
// =====================
wmilib::auto_ptr<CAsyncReq_PutInstanceAsync> pReq;
pReq.reset(new CAsyncReq_PutInstanceAsync( this, pInst, lFlags, pPseudoSink, pCtx));
if (NULL == pReq.get()) return WBEM_E_OUT_OF_MEMORY; if (NULL == pReq->GetContext()) return WBEM_E_OUT_OF_MEMORY;
hRes = InitNewTask(pReq.get(), pFnz, uInternalFlags, pReq->GetContext(), pHandler); if (FAILED(hRes)) return hRes;
_1.release(); hRes = ConfigMgr::EnqueueRequest(pReq.get()); if (FAILED(hRes)) { pFnz->CancelTask ( 0 ); return hRes; } pReq.release();
return hRes; }
//
// can throw
//
//////////////////////////////////////////////////////
HRESULT CWbemNamespace::_DeleteClassAsync( IN ULONG uInternalFlags, IN _IWmiFinalizer *pFnz, IN _IWmiCoreHandle *phTask, const BSTR strClassOrg, long lFlags, IWbemContext* pCtx, IWbemObjectSink* pHandler ) { HRESULT hRes = CheckNs(); if (FAILED(hRes)) return hRes;
// Parameter validation.
// =====================
if (pFnz == 0 && pHandler == 0) return WBEM_E_INVALID_PARAMETER;
if (strClassOrg == 0 || strClassOrg[0] == 0) return WBEM_E_INVALID_PARAMETER;
if (wcslen_max(strClassOrg,g_IdentifierLimit) > g_IdentifierLimit) return WBEM_E_QUOTA_VIOLATION;
WCHAR * strClass; if (L'\\' == strClassOrg[0] || L'/' == strClassOrg[0] ) { strClass = wcschr(strClassOrg, L':'); if (NULL == strClass) return WBEM_E_INVALID_OBJECT_PATH; strClass++; if (0 == strClass[0]) return WBEM_E_INVALID_PARAMETER; } else { strClass = strClassOrg; }
if (!m_bProvider && (lFlags & WBEM_FLAG_OWNER_UPDATE)) return WBEM_E_INVALID_PARAMETER;
if (lFlags & ~WBEM_FLAG_SEND_STATUS & ~WBEM_FLAG_OWNER_UPDATE) return WBEM_E_INVALID_PARAMETER;
if (lFlags & WBEM_FLAG_OWNER_UPDATE) { lFlags -= WBEM_FLAG_OWNER_UPDATE; lFlags += WBEM_FLAG_NO_EVENTS; }
// Create Finalizer.
// =================
IWbemObjectSink *pPseudoSink = 0; if (pFnz == 0) { hRes = CreateAsyncFinalizer(pCtx, pHandler, &pFnz, &pPseudoSink); if (FAILED(hRes)) return hRes; } else // borrowed finalizer
{ hRes = pFnz->NewInboundSink(0, &pPseudoSink); if (FAILED(hRes)) return hRes; pFnz->AddRef(); }
CReleaseMe _1(pPseudoSink); CReleaseMe _2(pFnz);
// Create request.
// ===============
wmilib::auto_ptr<CAsyncReq_DeleteClassAsync> pReq; pReq.reset(new CAsyncReq_DeleteClassAsync( this, strClass, lFlags, pPseudoSink, pCtx)); if (pReq.get() == NULL) return WBEM_E_OUT_OF_MEMORY; if (NULL == pReq->GetContext()) return WBEM_E_OUT_OF_MEMORY;
hRes = InitNewTask(pReq.get(), pFnz, uInternalFlags, pReq->GetContext(), pHandler); if (FAILED(hRes)) return hRes;
_1.release(); hRes = ConfigMgr::EnqueueRequest(pReq.get()); if (FAILED(hRes)) { pFnz->CancelTask ( 0 ); return hRes; } pReq.release();
return hRes; }
//***************************************************************************
//
//***************************************************************************
//
HRESULT CWbemNamespace::_CreateClassEnumAsync( IN ULONG uInternalFlags, IN _IWmiFinalizer *pFnz, IN _IWmiCoreHandle *phTask, const BSTR strParent, long lFlags, IWbemContext* pCtx, IWbemObjectSink* pHandler ) { HRESULT hRes = CheckNs(); if (FAILED(hRes)) return hRes; if (!Allowed(WBEM_ENABLE)) return WBEM_E_ACCESS_DENIED;
DEBUGTRACE((LOG_WBEMCORE, "CALL CWbemNamespace::CreateClassEnumAsync\n" " BSTR strParent = %S\n" " long lFlags = 0x%X\n" " IWbemObjectSink* pHandler = 0x%X\n", strParent, lFlags, pHandler ));
// Parameter validation.
// =====================
if (pFnz == 0 && pHandler == 0) return WBEM_E_INVALID_PARAMETER; if (strParent) { if (wcslen_max(strParent,g_IdentifierLimit) > g_IdentifierLimit) return WBEM_E_QUOTA_VIOLATION; }
if (lFlags & ~(WBEM_FLAG_DEEP | WBEM_FLAG_SHALLOW | WBEM_FLAG_SEND_STATUS) & ~WBEM_FLAG_USE_AMENDED_QUALIFIERS) return WBEM_E_INVALID_PARAMETER;
// Create Finalizer.
// =================
IWbemObjectSink *pPseudoSink = 0; if (pFnz == 0) { hRes = CreateAsyncFinalizer(pCtx, pHandler, &pFnz, &pPseudoSink); if (FAILED(hRes)) return hRes; } else // borrowed finalizer
{ hRes = pFnz->NewInboundSink(0, &pPseudoSink); if (FAILED(hRes)) return hRes; pFnz->AddRef(); }
CReleaseMe _1(pPseudoSink); CReleaseMe _2(pFnz);
// Add this request to the queue.
// ==============================
wmilib::auto_ptr<CAsyncReq_CreateClassEnumAsync> pReq; pReq.reset(new CAsyncReq_CreateClassEnumAsync(this, strParent, lFlags, pPseudoSink,pCtx));
if (NULL == pReq.get()) return WBEM_E_OUT_OF_MEMORY; if (NULL == pReq->GetContext()) return WBEM_E_OUT_OF_MEMORY;
hRes = InitNewTask(pReq.get(), pFnz, uInternalFlags, pReq->GetContext(), pHandler); if (FAILED(hRes)) return hRes;
_1.release(); hRes = ConfigMgr::EnqueueRequest(pReq.get()); if (FAILED(hRes)) { pFnz->CancelTask ( 0 ); return hRes; } pReq.release();
return hRes;
}
//***************************************************************************
//
//***************************************************************************
//
HRESULT CWbemNamespace::_PutClassAsync( IN ULONG uInternalFlags, IN _IWmiFinalizer *pFnz, IN _IWmiCoreHandle *phTask, READONLY IWbemClassObject* pObj, long lFlags, IWbemContext* pCtx, IWbemObjectSink* pHandler ) { HRESULT hRes = CheckNs(); if (FAILED(hRes)) return hRes;
CVARIANT vClass; if (pObj) { hRes = pObj->Get(L"__CLASS", 0, &vClass, 0, 0); } DEBUGTRACE((LOG_WBEMCORE, "CALL CWbemNamespace::PutClassAsync\n" " long lFlags = 0x%X\n" " IWbemClassObject *pObj = 0x%X\n" " IWbemObjectSink* pNotify = 0x%X\n" " __CLASS=%S\n", lFlags, pObj, pHandler, vClass.GetStr() ));
if (pFnz == 0 && pHandler == 0) return WBEM_E_INVALID_PARAMETER;
if (pObj == NULL) return WBEM_E_INVALID_PARAMETER;
if(!m_bProvider && (lFlags & WBEM_FLAG_OWNER_UPDATE)) { return WBEM_E_INVALID_PARAMETER; }
long lTestFlags = lFlags & ~WBEM_FLAG_SEND_STATUS & ~WBEM_FLAG_OWNER_UPDATE & ~WBEM_MASK_UPDATE_MODE & ~WBEM_FLAG_USE_AMENDED_QUALIFIERS;
if (!((lTestFlags == WBEM_FLAG_CREATE_OR_UPDATE) || (lTestFlags == WBEM_FLAG_UPDATE_ONLY) || (lTestFlags == WBEM_FLAG_CREATE_ONLY) || (lTestFlags == WBEM_FLAG_UPDATE_SAFE_MODE) || (lTestFlags == WBEM_FLAG_UPDATE_FORCE_MODE) || (lTestFlags == (WBEM_FLAG_UPDATE_ONLY | WBEM_FLAG_UPDATE_SAFE_MODE)) || (lTestFlags == (WBEM_FLAG_UPDATE_ONLY | WBEM_FLAG_UPDATE_FORCE_MODE)))) { return WBEM_E_INVALID_PARAMETER; }
if (lFlags & WBEM_FLAG_OWNER_UPDATE) { lFlags -= WBEM_FLAG_OWNER_UPDATE; lFlags += WBEM_FLAG_NO_EVENTS; }
// Create Finalizer.
// =================
IWbemObjectSink *pPseudoSink = 0; if (pFnz == 0) { hRes = CreateAsyncFinalizer(pCtx, pHandler, &pFnz, &pPseudoSink); if (FAILED(hRes)) return hRes; } else // borrowed finalizer
{ hRes = pFnz->NewInboundSink(0, &pPseudoSink); if (FAILED(hRes)) return hRes; pFnz->AddRef(); }
CReleaseMe _1(pPseudoSink); CReleaseMe _2(pFnz);
// Create request.
// ===============
wmilib::auto_ptr<CAsyncReq_PutClassAsync> pReq; pReq.reset(new CAsyncReq_PutClassAsync(this, pObj, lFlags, pPseudoSink, pCtx)); if (NULL == pReq.get()) return WBEM_E_OUT_OF_MEMORY; if (NULL == pReq->GetContext()) return WBEM_E_OUT_OF_MEMORY;
hRes = InitNewTask(pReq.get(), pFnz, uInternalFlags, pReq->GetContext(), pHandler); if (FAILED(hRes)) return hRes;
_1.release(); hRes = ConfigMgr::EnqueueRequest(pReq.get()); if (FAILED(hRes)) { pFnz->CancelTask ( 0 ); return hRes; } pReq.release();
return hRes; }
//***************************************************************************
//
//***************************************************************************
//
HRESULT CWbemNamespace::_DeleteInstanceAsync( IN ULONG uInternalFlags, IN _IWmiFinalizer *pFnz, IN _IWmiCoreHandle *phTask, READONLY const BSTR strObjectPath, long lFlags, IWbemContext* pCtx, IWbemObjectSink* pHandler ) { HRESULT hRes = CheckNs(); if (FAILED(hRes)) return hRes;
DEBUGTRACE((LOG_WBEMCORE, "CALL CWbemNamespace::DeleteInstance\n" " BSTR ObjectPath = %S\n" " long lFlags = %d\n" " IWbemObjectSink* pHandler = 0x%X\n", strObjectPath, lFlags, pHandler ));
// Parameter validation.
// =====================
if (pFnz == 0 && pHandler == 0) return WBEM_E_INVALID_PARAMETER; if (strObjectPath == 0 || strObjectPath[0] == 0) return WBEM_E_INVALID_PARAMETER; if (wcslen_max(strObjectPath,g_PathLimit) > g_PathLimit) return WBEM_E_QUOTA_VIOLATION; if (!m_bProvider && (lFlags & WBEM_FLAG_OWNER_UPDATE)) { return WBEM_E_INVALID_PARAMETER; }
if (lFlags & ~WBEM_FLAG_SEND_STATUS & ~WBEM_FLAG_OWNER_UPDATE) return WBEM_E_INVALID_PARAMETER;
if (lFlags & WBEM_FLAG_OWNER_UPDATE) { lFlags -= WBEM_FLAG_OWNER_UPDATE; lFlags += WBEM_FLAG_NO_EVENTS; }
// Create Finalizer.
// =================
IWbemObjectSink *pPseudoSink = 0; if (pFnz == 0) { hRes = CreateAsyncFinalizer(pCtx, pHandler, &pFnz, &pPseudoSink); if (FAILED(hRes)) return hRes; } else // borrowed finalizer
{ hRes = pFnz->NewInboundSink(0, &pPseudoSink); if (FAILED(hRes)) return hRes; pFnz->AddRef(); }
CReleaseMe _1(pPseudoSink); CReleaseMe _2(pFnz);
// Create request.
// ===============
wmilib::auto_ptr<CAsyncReq_DeleteInstanceAsync> pReq; pReq.reset(new CAsyncReq_DeleteInstanceAsync(this, strObjectPath, lFlags, pPseudoSink, pCtx));
if (NULL == pReq.get())return WBEM_E_OUT_OF_MEMORY; if ( NULL == pReq->GetContext()) return WBEM_E_OUT_OF_MEMORY;
hRes = InitNewTask(pReq.get(), pFnz, uInternalFlags, pReq->GetContext(), pHandler); if (FAILED(hRes)) return hRes;
_1.release(); hRes = ConfigMgr::EnqueueRequest(pReq.get()); if (FAILED(hRes)) { pFnz->CancelTask ( 0 ); return hRes; } pReq.release();
return hRes; }
//***************************************************************************
//
// CWbemNamespace::CreateInstanceEnumAsync
//
// Schedules an asynchrnous request that eventuall calls
// Exec_CreateInstanceEnum.
//
// Parameters and return values are described in help
//
//***************************************************************************
//
HRESULT CWbemNamespace::_CreateInstanceEnumAsync( IN ULONG uInternalFlags, IN _IWmiFinalizer *pFnz, IN _IWmiCoreHandle *phTask, const BSTR strClass, long lFlags, IWbemContext* pCtx, IWbemObjectSink* pHandler ) { HRESULT hRes = CheckNs(); if (FAILED(hRes)) return hRes; if (!Allowed(WBEM_ENABLE)) return WBEM_E_ACCESS_DENIED;
DEBUGTRACE((LOG_WBEMCORE, "CALL CWbemNamespace::CreateInstanceEnumAsync\n" " BSTR Class = %S\n" " long lFlags = 0x%X\n" " IWbemObjectSink pHandler = 0x%X\n", strClass, lFlags, pHandler ));
// Parameter validation.
// =====================
if (pFnz == 0 && pHandler == 0) return WBEM_E_INVALID_PARAMETER;
if (strClass == 0 || strClass[0] == 0) return WBEM_E_INVALID_PARAMETER;
if (wcslen_max(strClass,g_IdentifierLimit) > g_IdentifierLimit) return WBEM_E_QUOTA_VIOLATION;
if (lFlags & ~(WBEM_FLAG_DEEP | WBEM_FLAG_SHALLOW | WBEM_FLAG_SEND_STATUS | WBEM_FLAG_USE_AMENDED_QUALIFIERS | WBEM_FLAG_DIRECT_READ)) return WBEM_E_INVALID_PARAMETER;
// Create Finalizer.
// =================
IWbemObjectSink *pPseudoSink = 0; if (pFnz == 0) { hRes = CreateAsyncFinalizer(pCtx, pHandler, &pFnz, &pPseudoSink); if (FAILED(hRes)) return hRes; } else // borrowed finalizer
{ hRes = pFnz->NewInboundSink(0, &pPseudoSink); if (FAILED(hRes)) return hRes; pFnz->AddRef(); }
CReleaseMe _1(pPseudoSink); CReleaseMe _2(pFnz);
// Add this request to the async queue.
// ====================================
wmilib::auto_ptr<CAsyncReq_CreateInstanceEnumAsync> pReq; pReq.reset(new CAsyncReq_CreateInstanceEnumAsync(this, strClass, lFlags, pPseudoSink,pCtx)); if (NULL == pReq.get()) return WBEM_E_OUT_OF_MEMORY; if (NULL == pReq->GetContext()) return WBEM_E_OUT_OF_MEMORY;
hRes = InitNewTask(pReq.get(), pFnz, uInternalFlags, pReq->GetContext(), pHandler); if (FAILED(hRes)) return hRes;
_1.release(); hRes = ConfigMgr::EnqueueRequest(pReq.get()); if (FAILED(hRes)) { pFnz->CancelTask ( 0 ); return hRes; } pReq.release();
return hRes; }
//***************************************************************************
//
// CWbemNamespace::ExecQueryAsync
//
// Schedules an asynchronous request that eventually calls
// CQueryEngine::ExecQuery (see qengine.h)
//
// Parameters and return values are described in help
//
//***************************************************************************
//
HRESULT CWbemNamespace::_ExecQueryAsync( IN ULONG uInternalFlags, IN _IWmiFinalizer *pFnz, IN _IWmiCoreHandle *phTask, const BSTR strQueryFormat, const BSTR strQuery, long lFlags, IWbemContext* pCtx, IWbemObjectSink* pHandler ) { HRESULT hRes = CheckNs(); if (FAILED(hRes)) return hRes; if (!Allowed(WBEM_ENABLE)) return WBEM_E_ACCESS_DENIED;
DEBUGTRACE((LOG_WBEMCORE, "CALL CWbemNamespace::ExecQueryAsync\n" " BSTR QueryFormat = %S\n" " BSTR Query = %S\n" " IWbemObjectSink* pHandler = 0x%X\n", strQueryFormat, strQuery, pHandler ));
// Parameter validation.
// =====================
if (pFnz == 0 && pHandler == 0) return WBEM_E_INVALID_PARAMETER;
if (strQueryFormat == 0 || strQuery == 0) return WBEM_E_INVALID_PARAMETER; if ( 0 == strQueryFormat[0] || 0 == strQuery[0]) return WBEM_E_INVALID_PARAMETER;
if (wcslen_max(strQuery,g_QueryLimit) > g_QueryLimit) return WBEM_E_QUOTA_VIOLATION;
if (lFlags & ~WBEM_FLAG_PROTOTYPE & ~WBEM_FLAG_SEND_STATUS & ~WBEM_FLAG_ENSURE_LOCATABLE & ~WBEM_FLAG_USE_AMENDED_QUALIFIERS & ~WBEM_FLAG_KEEP_SHAPE & ~WBEM_FLAG_DIRECT_READ ) return WBEM_E_INVALID_PARAMETER;
// Create Finalizer.
// =================
IWbemObjectSink *pPseudoSink = 0; if (pFnz == 0) { hRes = CreateAsyncFinalizer(pCtx, pHandler, &pFnz, &pPseudoSink); if (FAILED(hRes)) return hRes; } else // borrowed finalizer
{ hRes = pFnz->NewInboundSink(0, &pPseudoSink); if (FAILED(hRes)) return hRes; pFnz->AddRef(); }
CReleaseMe rmPseudoSink(pPseudoSink); CReleaseMe _2(pFnz);
// Add the request to the queue.
// =============================
// will throw CX_MemoryException
wmilib::auto_ptr<CAsyncReq_ExecQueryAsync> pReq; pReq.reset(new CAsyncReq_ExecQueryAsync(this, strQueryFormat, strQuery, lFlags,pPseudoSink, pCtx)); if (NULL == pReq.get()) return WBEM_E_OUT_OF_MEMORY; if ( NULL == pReq->GetContext() ) return WBEM_E_OUT_OF_MEMORY;
hRes = InitNewTask(pReq.get(), pFnz, uInternalFlags, pReq->GetContext(), pHandler); if (FAILED(hRes)) return hRes;
rmPseudoSink.release(); hRes = ConfigMgr::EnqueueRequest(pReq.get()); if (FAILED(hRes)) { pFnz->CancelTask ( 0 ); return hRes; } pReq.release();
return hRes; }
//
//
// CWbemNamespace::_GetObjectAsync
//
// Schedules an asynchrnous request that eventuall calls Exec_GetObjectByPath.
//
// Parameters and return values are described in help
//
// throws or return
//
///////////////////////////////////////////////////////////////
HRESULT CWbemNamespace::_GetObjectAsync( IN ULONG uInternalFlags, IN _IWmiFinalizer *pFnz, IN _IWmiCoreHandle *phTask, const BSTR strObjectPath, long lFlags, IWbemContext* pCtx, IWbemObjectSink* pHandler ) { HRESULT hRes = CheckNs(); if (FAILED(hRes)) return hRes;
DEBUGTRACE((LOG_WBEMCORE, "CALL CWbemNamespace::GetObjectAsync\n" " BSTR ObjectPath = %S\n" " long lFlags = %d\n" " IWbemObjectSink* pHandler = 0x%X\n", strObjectPath, lFlags, pHandler ));
// Parameter validation.
// =====================
if (pFnz == 0 && pHandler == 0) return WBEM_E_INVALID_PARAMETER;
if (lFlags & ~WBEM_FLAG_SEND_STATUS & ~WBEM_FLAG_USE_AMENDED_QUALIFIERS & ~WBEM_FLAG_DIRECT_READ) return WBEM_E_INVALID_PARAMETER;
// Create Finalizer.
// =================
IWbemObjectSink *pPseudoSink = 0; if (pFnz == 0) { hRes = CreateAsyncFinalizer(pCtx, pHandler, &pFnz, &pPseudoSink); if (FAILED(hRes)) return hRes; } else // borrowed finalizer
{ hRes = pFnz->NewInboundSink(0, &pPseudoSink); if (FAILED(hRes)) return hRes; pFnz->AddRef(); // Compensate for CReleaseMe to follow
}
CReleaseMe _1(pPseudoSink); CReleaseMe _2(pFnz);
// Add request to the async queue.
// ===============================
wmilib::auto_ptr<CAsyncReq_GetObjectAsync> pReq; pReq.reset(new CAsyncReq_GetObjectAsync(this, strObjectPath, lFlags, pPseudoSink, pCtx)); if (NULL == pReq.get()) return WBEM_E_OUT_OF_MEMORY; if (NULL == pReq->GetContext()) return WBEM_E_OUT_OF_MEMORY;
hRes = InitNewTask(pReq.get(), pFnz, uInternalFlags, pReq->GetContext(), pHandler); if (FAILED(hRes)) return hRes;
_1.release(); hRes = ConfigMgr::EnqueueRequest(pReq.get()); if (FAILED(hRes)) { pFnz->CancelTask(0); return hRes; } pReq.release();
return hRes; }
//
//
// CWbemNamespace::ExecMethodAsync
//
// can throw
//
//////////////////////////////////////////////////////////
HRESULT CWbemNamespace::_ExecMethodAsync( IN ULONG uInternalFlags, IN _IWmiFinalizer *pFnz, IN _IWmiCoreHandle *phTask, const BSTR ObjectPath, const BSTR MethodName, long lFlags, IWbemContext *pCtx, IWbemClassObject *pInParams, IWbemObjectSink* pHandler ) { HRESULT hRes = CheckNs(); if (FAILED(hRes)) return hRes;
DEBUGTRACE((LOG_WBEMCORE, "CALL CWbemNamespace::ExecMethodAsync\n" " BSTR ObjectPath = %S\n" " BSTR MethodName = %S\n" " long lFlags = %d\n" " IWbemClassObject * pIn = 0x%X\n", ObjectPath, MethodName, lFlags, pInParams ));
// Parameter validation.
// =====================
if (pFnz ==0 && pHandler == 0) return WBEM_E_INVALID_PARAMETER;
if (lFlags & ~WBEM_FLAG_SEND_STATUS) return WBEM_E_INVALID_PARAMETER;
// Create Finalizer.
// =================
IWbemObjectSink *pPseudoSink = 0; if (pFnz == 0) { hRes = CreateAsyncFinalizer(pCtx, pHandler, &pFnz, &pPseudoSink); if (FAILED(hRes)) return hRes; } else // borrowed finalizer
{ hRes = pFnz->NewInboundSink(0, &pPseudoSink); if (FAILED(hRes)) return hRes; pFnz->AddRef(); }
CReleaseMe _1(pPseudoSink); CReleaseMe _2(pFnz);
// Add request to the async queue.
// ===============================
wmilib::auto_ptr<CAsyncReq_ExecMethodAsync> pReq; pReq.reset(new CAsyncReq_ExecMethodAsync(this, ObjectPath, MethodName, lFlags, pInParams, pPseudoSink, pCtx));
if (NULL == pReq.get()) return WBEM_E_OUT_OF_MEMORY; if ( NULL == pReq->GetContext() ) return WBEM_E_OUT_OF_MEMORY;
hRes = InitNewTask(pReq.get(), pFnz, uInternalFlags, pReq->GetContext(), pHandler); if (FAILED(hRes)) return hRes;
_1.release(); hRes = ConfigMgr::EnqueueRequest(pReq.get()); if (FAILED(hRes)) { pFnz->CancelTask ( 0 ); return hRes; } pReq.release();
return hRes; }
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//
// Native sync operations
//
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//***************************************************************************
//
// CWbemNamespace::DeleteClass
//
// Calls DeleteClassAsync and waits for completion
//
// Parameters and return values are described in help
//
//***************************************************************************
//
HRESULT CWbemNamespace::DeleteClass( const BSTR strClass, long lFlags, IWbemContext* pCtx, IWbemCallResult** ppResult ) { HRESULT hRes = CheckNs(); if (FAILED(hRes)) return hRes;
try { DEBUGTRACE((LOG_WBEMCORE, "CALL CWbemNamespace::DeleteClass" " BSTR Class = %S\n" " long lFlags = 0x%X\n", strClass, lFlags ));
// Parameter validation.
// =====================
if (lFlags & ~WBEM_FLAG_RETURN_IMMEDIATELY & ~WBEM_FLAG_OWNER_UPDATE ) return WBEM_E_INVALID_PARAMETER;
if ((lFlags & WBEM_RETURN_IMMEDIATELY) && ppResult == NULL) return WBEM_E_INVALID_PARAMETER;
// Create Finalizer.
// =================
_IWmiFinalizer *pFnz = 0; hRes = CreateSyncFinalizer(pCtx, &pFnz); if (FAILED(hRes)) return hRes; CReleaseMe _1(pFnz);
ULONG uTaskType = WMICORE_TASK_DELETE_CLASS; if (ppResult) uTaskType |= WMICORE_TASK_TYPE_SEMISYNC; else uTaskType |= WMICORE_TASK_TYPE_SYNC;
// Call the async side.
// ====================
hRes = _DeleteClassAsync(uTaskType, pFnz, 0, strClass, lFlags & ~WBEM_RETURN_IMMEDIATELY,pCtx, NULL);
if (FAILED(hRes)) return hRes;
// Check for the two return paradigms.
// ===================================
if ((lFlags & WBEM_RETURN_IMMEDIATELY) == 0) { HRESULT hResTemp = pFnz->GetOperationResult(0, INFINITE, &hRes); if (FAILED(hResTemp)) return hResTemp; } if (ppResult) { hRes = pFnz->GetResultObject(0, IID_IWbemCallResult, (LPVOID *) ppResult); } return hRes; } catch(...) { ExceptionCounter c; return WBEM_E_CRITICAL_ERROR; } }
//***************************************************************************
//
// CWbemNamespace::PutClass
//
// Calls PutClassAsync and waits for completion
//
// Parameters and return values are described in help
//
//***************************************************************************
HRESULT CWbemNamespace::PutClass( READONLY IWbemClassObject* pObj, long lFlags, IWbemContext* pCtx, NEWOBJECT IWbemCallResult** ppResult ) { HRESULT hRes = CheckNs(); if (FAILED(hRes)) return hRes;
CVARIANT vClass; if (pObj) { hRes = pObj->Get(L"__CLASS", 0, &vClass, 0, 0); }
DEBUGTRACE((LOG_WBEMCORE, "CALL CWbemNamespace::PutClass\n" " long lFlags = 0x%X\n" " IWbemClassObject *pObj = 0x%X\n" " __CLASS=%S\n", lFlags, pObj, vClass.GetStr() ));
if (lFlags & ~WBEM_FLAG_RETURN_IMMEDIATELY & ~WBEM_FLAG_OWNER_UPDATE & ~WBEM_FLAG_USE_AMENDED_QUALIFIERS & ~WBEM_FLAG_CREATE_OR_UPDATE & ~WBEM_FLAG_UPDATE_ONLY & ~WBEM_FLAG_CREATE_ONLY & ~WBEM_FLAG_UPDATE_SAFE_MODE & ~WBEM_FLAG_UPDATE_FORCE_MODE ) return WBEM_E_INVALID_PARAMETER;
if ((lFlags & WBEM_RETURN_IMMEDIATELY) && ppResult == NULL) return WBEM_E_INVALID_PARAMETER;
try { if( ((lFlags & WBEM_FLAG_RETURN_IMMEDIATELY) == 0)&&(ppResult==NULL)) { HANDLE hCurrentToken; if(OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &hCurrentToken)) { //
// Got a thread token --- cannot fast-track because otherwise we
// will have a thread token on a thread executing internal code
//
CloseHandle(hCurrentToken); } else if (CWbemQueue::GetCurrentRequest() == NULL) { if (!m_bProvider && (lFlags & WBEM_FLAG_OWNER_UPDATE)) { return WBEM_E_INVALID_PARAMETER; } if (lFlags & WBEM_FLAG_OWNER_UPDATE) { lFlags -= WBEM_FLAG_OWNER_UPDATE; lFlags += WBEM_FLAG_NO_EVENTS; }
IWbemContext *pContext = pCtx ; if (pContext) pContext->AddRef () ; else { pContext = ConfigMgr::GetNewContext(); if ( pContext == NULL ) return WBEM_E_OUT_OF_MEMORY; }
CReleaseMe _1_pContext (pContext) ;
CSynchronousSink *pSyncSink = CSynchronousSink::Create(); if (pSyncSink == NULL) return WBEM_E_OUT_OF_MEMORY; pSyncSink->AddRef(); CReleaseMe _2(pSyncSink);
hRes = Exec_PutClass(pObj, lFlags, pContext, pSyncSink);
// Extract the new object from the sink.
// ======================================
pSyncSink->Block();
IWbemClassObject* pErrorObj = NULL; pSyncSink->GetStatus(&hRes, NULL, &pErrorObj); CReleaseMe rm1(pErrorObj);
if(pErrorObj) { IErrorInfo* pErrorInfo = NULL; pErrorObj->QueryInterface(IID_IErrorInfo,(void**)&pErrorInfo); SetErrorInfo(0, pErrorInfo); pErrorInfo->Release(); }
return hRes; } }
// Create Finalizer.
// =================
_IWmiFinalizer *pFnz = 0; hRes = CreateSyncFinalizer(pCtx, &pFnz); if (FAILED(hRes)) return hRes; CReleaseMe _1(pFnz);
ULONG uTaskType = WMICORE_TASK_PUT_CLASS; if (ppResult) uTaskType |= WMICORE_TASK_TYPE_SEMISYNC; else uTaskType |= WMICORE_TASK_TYPE_SYNC;
// Do the work elsewhere.
// ======================
hRes = _PutClassAsync(uTaskType, pFnz, 0, pObj, lFlags & ~WBEM_RETURN_IMMEDIATELY, pCtx, NULL);
if (FAILED(hRes)) return hRes;
// Check for the two return paradigms.
// ===================================
if ((lFlags & WBEM_RETURN_IMMEDIATELY) == 0) { HRESULT hResTemp = pFnz->GetOperationResult(0, INFINITE, &hRes); if (FAILED(hResTemp)) return hResTemp; } if (ppResult) { hRes = pFnz->GetResultObject(0, IID_IWbemCallResult, (LPVOID *) ppResult); }
return hRes;
} catch(...) // this interface calls the Exec_[MetrhodName] straight
{ ExceptionCounter c; return WBEM_E_CRITICAL_ERROR; } }
//***************************************************************************
//
// CWbemNamespace::CancelAsyncRequest.
//
// Currently a noop, eventually this function will cancel an asynchrnous
// request based on the handle value it returned.
//
// Parameters and return values are described in help
//
//***************************************************************************
HRESULT CWbemNamespace::CancelAsyncCall(IWbemObjectSink* pSink) { HRESULT hRes = CheckNs(); if (FAILED(hRes)) return hRes;
// Note that LOMEM_CHECK is not needed or wanted here
if (pSink == NULL) return WBEM_E_INVALID_PARAMETER;
// Quickly cancel via Arbitrator.
// ===============================
if (m_pArb) { hRes = m_pArb->CancelTasksBySink(WMIARB_CALL_CANCELLED_CLIENT, IID_IWbemObjectSink, pSink); }
return hRes ;
}
//***************************************************************************
//
// CWbemNamespace::PutInstance
//
// Calls PutInstanceAsync and waits for completion
//
// Parameters and return values are described in help
//
//***************************************************************************
HRESULT CWbemNamespace::PutInstance( IWbemClassObject* pInst, long lFlags, IWbemContext* pCtx, IWbemCallResult** ppResult ) { HRESULT hRes = CheckNs(); if (FAILED(hRes)) return hRes;
// Parameter validation.
// =====================
if (lFlags & ~WBEM_RETURN_IMMEDIATELY & ~WBEM_FLAG_USE_AMENDED_QUALIFIERS & ~WBEM_FLAG_OWNER_UPDATE & ~WBEM_FLAG_CREATE_ONLY & ~WBEM_FLAG_UPDATE_ONLY & ~WBEM_FLAG_CREATE_OR_UPDATE ) return WBEM_E_INVALID_PARAMETER;
try { DEBUGTRACE((LOG_WBEMCORE, "CALL CWbemNamespace::PutInstance" " long lFlags = 0x%X\n" " IWbemClassObject *pInst = 0x%X\n", lFlags, pInst)); if( ((lFlags & WBEM_FLAG_RETURN_IMMEDIATELY) == 0)&&(ppResult==NULL)) { // trick for allowing setup to set the SD
AutoRevertSecTlsFlag RevSec ( (LPVOID) 1 ); if ( IsNtSetupRunning() ) { RevSec.SetSecTlsFlag ( (LPVOID) 0 ); }
HANDLE hCurrentToken; if(OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &hCurrentToken)) { //
// Got a thread token --- cannot fast-track because otherwise we
// will have a thread token on a thread executing internal code
//
CloseHandle(hCurrentToken); } else if (CWbemQueue::GetCurrentRequest() == NULL) { IWbemContext *pContext = pCtx ; if (pContext) pContext->AddRef () ; else { pContext = ConfigMgr::GetNewContext(); if ( pContext == NULL ) return WBEM_E_OUT_OF_MEMORY; }
CReleaseMe _1_pContext (pContext) ;
CSynchronousSink *pSyncSink = CSynchronousSink::Create(); if (pSyncSink == NULL) return WBEM_E_OUT_OF_MEMORY;
pSyncSink->AddRef(); CReleaseMe _2(pSyncSink);
if (!m_bProvider && (lFlags & WBEM_FLAG_OWNER_UPDATE)) { return WBEM_E_INVALID_PARAMETER; }
if (lFlags & WBEM_FLAG_OWNER_UPDATE) { lFlags -= WBEM_FLAG_OWNER_UPDATE; lFlags += WBEM_FLAG_NO_EVENTS; }
hRes = Exec_PutInstance(pInst, lFlags, pContext, pSyncSink);
// Extract the new object from the sink.
// ======================================
pSyncSink->Block(); IWbemClassObject* pErrorObj = NULL; pSyncSink->GetStatus(&hRes, NULL, &pErrorObj); CReleaseMe rm1(pErrorObj);
if(pErrorObj) { IErrorInfo* pErrorInfo = NULL; pErrorObj->QueryInterface(IID_IErrorInfo, (void**)&pErrorInfo); SetErrorInfo(0, pErrorInfo); pErrorInfo->Release(); }
return hRes; } }
if ((lFlags & WBEM_RETURN_IMMEDIATELY) && ppResult == NULL) return WBEM_E_INVALID_PARAMETER;
// Create Finalizer.
// =================
_IWmiFinalizer *pFnz = 0; hRes = CreateSyncFinalizer(pCtx, &pFnz); if (FAILED(hRes)) return hRes; CReleaseMe _1(pFnz);
ULONG uTaskType = WMICORE_TASK_PUT_INSTANCE; if (ppResult) uTaskType |= WMICORE_TASK_TYPE_SEMISYNC; else uTaskType |= WMICORE_TASK_TYPE_SYNC;
// Do the work elsewhere.
// ======================
hRes = _PutInstanceAsync(uTaskType, pFnz, 0, pInst, lFlags & ~WBEM_RETURN_IMMEDIATELY, pCtx, NULL);
if (FAILED(hRes)) return hRes;
// Check for the two return paradigms.
// ===================================
if ((lFlags & WBEM_RETURN_IMMEDIATELY) == 0) { HRESULT hResTemp = pFnz->GetOperationResult(0, INFINITE, &hRes); if (FAILED(hResTemp)) return hResTemp; } if (ppResult) { hRes = pFnz->GetResultObject(0, IID_IWbemCallResult, (LPVOID *) ppResult); }
return hRes;
} catch(...) // this interfaces calls the Exec_[MethodName]
{ ExceptionCounter c; return WBEM_E_CRITICAL_ERROR; } }
//***************************************************************************
//
// CWbemNamespace::DeleteInstance
//
// Calls DeleteInstanceAsync and waits for completion
//
// Parameters and return values are described in help
//
//***************************************************************************
HRESULT CWbemNamespace::DeleteInstance( READONLY const BSTR strObjectPath, long lFlags, IWbemContext* pCtx, IWbemCallResult** ppResult ) { HRESULT hRes = CheckNs(); if (FAILED(hRes)) return hRes;
DEBUGTRACE((LOG_WBEMCORE, "CALL CWbemNamespace::DeleteInstance\n" " BSTR ObjectPath = %S\n" " long lFlags = %d\n", strObjectPath, lFlags ));
if (lFlags & ~WBEM_FLAG_RETURN_IMMEDIATELY &~ WBEM_FLAG_OWNER_UPDATE) return WBEM_E_INVALID_PARAMETER;
if((lFlags & WBEM_RETURN_IMMEDIATELY) && ppResult == NULL) return WBEM_E_INVALID_PARAMETER;
// Create Finalizer.
// =================
_IWmiFinalizer *pFnz = 0; hRes = CreateSyncFinalizer(pCtx, &pFnz); if (FAILED(hRes)) return hRes; CReleaseMe _1(pFnz);
ULONG uTaskType = WMICORE_TASK_DELETE_INSTANCE; if (ppResult) uTaskType |= WMICORE_TASK_TYPE_SEMISYNC; else uTaskType |= WMICORE_TASK_TYPE_SYNC;
// Do the work elsewhere.
// ======================
hRes = _DeleteInstanceAsync(uTaskType, pFnz, 0, strObjectPath, lFlags & ~WBEM_RETURN_IMMEDIATELY, pCtx, NULL);
if (FAILED(hRes)) return hRes;
// Check for the two return paradigms.
// ===================================
if ((lFlags & WBEM_RETURN_IMMEDIATELY) == 0) { HRESULT hResTemp = pFnz->GetOperationResult(0,INFINITE, &hRes); if (FAILED(hResTemp)) return hResTemp; } if (ppResult) { hRes = pFnz->GetResultObject(0, IID_IWbemCallResult, (LPVOID *) ppResult); }
return hRes; }
//***************************************************************************
//
// CWbemNamespace::GetObject
//
// Calls GetObjectAsync and waits for completion
//
// Parameters and return values are described in help
//
//***************************************************************************
HRESULT CWbemNamespace::GetObject( READONLY const BSTR strObjectPath, long lFlags, IWbemContext* pCtx, NEWOBJECT IWbemClassObject** ppObj, NEWOBJECT IWbemCallResult** ppResult ) { HRESULT hRes = CheckNs(); if (FAILED(hRes)) return hRes; if (!Allowed(WBEM_ENABLE)) return WBEM_E_ACCESS_DENIED;
DEBUGTRACE((LOG_WBEMCORE, "CALL CWbemNamespace::GetObject\n" " BSTR ObjectPath = %S\n" " long lFlags = %d\n" " IWbemClassObject ** pObj = 0x%X\n", strObjectPath, lFlags, ppObj ));
if (ppObj) *ppObj = NULL;
if (lFlags & ~WBEM_FLAG_RETURN_IMMEDIATELY & ~WBEM_FLAG_USE_AMENDED_QUALIFIERS & ~WBEM_FLAG_DIRECT_READ ) return WBEM_E_INVALID_PARAMETER;
if ((lFlags & WBEM_RETURN_IMMEDIATELY) && ppResult == NULL) return WBEM_E_INVALID_PARAMETER;
try { if( ((lFlags & WBEM_FLAG_RETURN_IMMEDIATELY) == 0)&&(ppResult==NULL)) { //
// This is special case GetObject synchronous. We dont want to allow this unless,
// we're running setup.
//
AutoRevertSecTlsFlag RevSec ( (LPVOID) 1 ); if ( IsNtSetupRunning() ) { RevSec.SetSecTlsFlag ( (LPVOID) 0 ); }
HANDLE hCurrentToken; if(OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &hCurrentToken)) { //
// Got a thread token --- cannot fast-track because otherwise we
// will have a thread token on a thread executing internal code
//
CloseHandle(hCurrentToken); } else if (CWbemQueue::GetCurrentRequest() == NULL) { IWbemContext *pContext = pCtx ; if (pContext) pContext->AddRef () ; else { pContext = ConfigMgr::GetNewContext(); if ( pContext == NULL ) return WBEM_E_OUT_OF_MEMORY; }
CReleaseMe _1_pContext (pContext) ;
CSynchronousSink *pSyncSink = CSynchronousSink::Create(); if (pSyncSink == NULL) return WBEM_E_OUT_OF_MEMORY;
pSyncSink->AddRef(); CReleaseMe _2(pSyncSink);
hRes = Exec_GetObject(strObjectPath, lFlags, pContext, pSyncSink); //if (FAILED(hRes))
//{
// return hRes;
//}
// Extract the new object from the sink.
// ======================================
pSyncSink->Block();
IWbemClassObject* pErrorObj = NULL; pSyncSink->GetStatus(&hRes, NULL, &pErrorObj); CReleaseMe rm1(pErrorObj);
if(pErrorObj) { IErrorInfo* pErrorInfo = NULL; pErrorObj->QueryInterface(IID_IErrorInfo, (void**)&pErrorInfo); SetErrorInfo(0, pErrorInfo); pErrorInfo->Release(); }
if (SUCCEEDED(hRes)) { if(pSyncSink->GetObjects().GetSize() != 1) return WBEM_E_CRITICAL_ERROR;
// Only access the returned object if ppObj is non-NULL.
if ( NULL != ppObj ) { *ppObj = pSyncSink->GetObjects()[0]; (*ppObj)->AddRef(); } }
return hRes; } }
// Create Finalizer.
// =================
_IWmiFinalizer *pFnz = 0; hRes = CreateSyncFinalizer(pCtx, &pFnz); if (FAILED(hRes)) return hRes; CReleaseMe _1(pFnz);
ULONG uTaskType = WMICORE_TASK_GET_OBJECT; if (ppResult) uTaskType |= WMICORE_TASK_TYPE_SEMISYNC; else uTaskType |= WMICORE_TASK_TYPE_SYNC;
// Do the work elsewhere.
// ======================
hRes = _GetObjectAsync(uTaskType, pFnz, 0, strObjectPath, lFlags & ~WBEM_RETURN_IMMEDIATELY, pCtx, NULL);
if (FAILED(hRes)) { return hRes; }
// Check for the two return paradigms.
// ===================================
if ((lFlags & WBEM_RETURN_IMMEDIATELY) == 0) { HRESULT hResTemp = pFnz->GetOperationResult(0, INFINITE, &hRes); if (FAILED(hResTemp)) return hResTemp; if (FAILED(hRes)) return hRes; }
if (ppResult) { hRes = pFnz->GetResultObject(0, IID_IWbemCallResult, (LPVOID *) ppResult); if (FAILED(hRes)) { return hRes; } if (ppObj && ((lFlags & WBEM_RETURN_IMMEDIATELY) == 0)) hRes = (*ppResult)->GetResultObject(INFINITE, ppObj); } else if (ppObj && ((lFlags & WBEM_RETURN_IMMEDIATELY) == 0)) { hRes = pFnz->GetResultObject(0, IID_IWbemClassObject, (LPVOID *) ppObj); }
return hRes; } catch(...) // this interface goes to the Exec_[MethodName straight]
{ ExceptionCounter c; return WBEM_E_CRITICAL_ERROR; } }
//***************************************************************************
//
// CWbemNamespace::ExecMethod
//
//***************************************************************************
HRESULT CWbemNamespace::ExecMethod( const BSTR ObjectPath, const BSTR MethodName, long lFlags, IWbemContext *pCtx, IWbemClassObject *pInParams, IWbemClassObject **ppOutParams, IWbemCallResult **ppResult ) { HRESULT hRes = CheckNs(); if (FAILED(hRes)) return hRes;
DEBUGTRACE((LOG_WBEMCORE, "CALL CWbemNamespace::ExecMethod\n" " BSTR ObjectPath = %S\n" " BSTR MethodName = %S\n" " long lFlags = %d\n" " IWbemClassObject * pIn = 0x%X\n", ObjectPath, MethodName, lFlags, pInParams ));
// Parameter validation.
// =====================
if (ppOutParams) *ppOutParams = NULL;
if (lFlags & ~WBEM_FLAG_RETURN_IMMEDIATELY) return WBEM_E_INVALID_PARAMETER;
// Create Finalizer.
// =================
_IWmiFinalizer *pFnz = 0; hRes = CreateSyncFinalizer(pCtx, &pFnz); if (FAILED(hRes)) return hRes; CReleaseMe _1(pFnz);
ULONG uTaskType = WMICORE_TASK_EXEC_METHOD; if (ppResult) uTaskType |= WMICORE_TASK_TYPE_SEMISYNC; else uTaskType |= WMICORE_TASK_TYPE_SYNC;
// Do the work elsewhere.
// ======================
hRes = _ExecMethodAsync(uTaskType, pFnz, 0, ObjectPath, MethodName, lFlags & ~WBEM_RETURN_IMMEDIATELY, pCtx, pInParams, NULL);
if (FAILED(hRes)) return hRes;
// Check for the two return paradigms.
// ===================================
if ((lFlags & WBEM_RETURN_IMMEDIATELY) == 0) { HRESULT hResTemp = pFnz->GetOperationResult(0, INFINITE, &hRes); if (FAILED(hResTemp)) return hResTemp; if (FAILED(hRes)) return hRes; if (ppResult) { hRes = pFnz->GetResultObject(0, IID_IWbemCallResult, (LPVOID *) ppResult); if (FAILED(hRes)) return hRes; if (ppOutParams) { hRes = (*ppResult)->GetResultObject(INFINITE, ppOutParams); if (hRes == WBEM_E_NOT_FOUND) //If there was no object we still return success!
hRes = WBEM_S_NO_ERROR; } } else { hRes = pFnz->GetResultObject(0, IID_IWbemClassObject, (LPVOID *) ppOutParams); if (hRes == WBEM_E_NOT_FOUND) //If there was no object we still return success!
hRes = WBEM_S_NO_ERROR; } } else { //
// If we have a call result pointer we should try to use it
//
if ( ppResult ) { hRes = pFnz->GetResultObject(0, IID_IWbemCallResult, (LPVOID *) ppResult); if (hRes == WBEM_E_NOT_FOUND) //If there was no object we still return success!
hRes = WBEM_S_NO_ERROR; } else // semysync and nobody interested
{ pFnz->CancelTask(0); hRes = WBEM_S_NO_ERROR; }
}
return hRes; }
//***************************************************************************
//
// CWbemNamespace::CreateInstanceEnum
//
// Calls CreateInstanceEnumAsync and waits for completion
//
// Parameters and return values are described in help
//
//***************************************************************************
HRESULT CWbemNamespace::CreateInstanceEnum( const BSTR strClass, long lFlags, IWbemContext* pCtx, IEnumWbemClassObject** ppEnum ) { HRESULT hRes = CheckNs(); if (FAILED(hRes)) return hRes;
DEBUGTRACE((LOG_WBEMCORE, "CALL CWbemNamespace::CreateInstanceEnum\n" " long lFlags = 0x%X\n" " BSTR Class = %S\n" " IEnumWbemClassObject **pEnum = 0x%X\n", lFlags, strClass, ppEnum ));
// Validate parameters
// ===================
if (lFlags & ~WBEM_RETURN_IMMEDIATELY & ~WBEM_FLAG_FORWARD_ONLY & ~WBEM_FLAG_DEEP & ~WBEM_FLAG_SHALLOW & ~WBEM_FLAG_USE_AMENDED_QUALIFIERS & ~WBEM_FLAG_DIRECT_READ ) return WBEM_E_INVALID_PARAMETER;
if (ppEnum == NULL) return WBEM_E_INVALID_PARAMETER; *ppEnum = NULL;
// Create Finalizer.
// =================
_IWmiFinalizer *pFnz = 0; hRes = CreateSyncFinalizer(pCtx, &pFnz); if (FAILED(hRes)) return hRes; CReleaseMe _1(pFnz);
ULONG uTaskType = WMICORE_TASK_ENUM_INSTANCES; if (lFlags & WBEM_RETURN_IMMEDIATELY) uTaskType |= WMICORE_TASK_TYPE_SEMISYNC; else uTaskType |= WMICORE_TASK_TYPE_SYNC;
// Do the work.
// ============
hRes = _CreateInstanceEnumAsync(uTaskType, pFnz, 0, strClass, lFlags & ~WBEM_RETURN_IMMEDIATELY & ~WBEM_FLAG_FORWARD_ONLY, pCtx, NULL);
if (FAILED(hRes)) return hRes;
if ((lFlags & WBEM_RETURN_IMMEDIATELY) == 0) pFnz->GetOperationResult(0, INFINITE, &hRes);
if (SUCCEEDED(hRes)) { IEnumWbemClassObject* pEnum = NULL; HRESULT hResTemp = pFnz->GetResultObject(lFlags, IID_IEnumWbemClassObject, (LPVOID*)&pEnum); if (FAILED(hResTemp)) return hResTemp; CReleaseMe _2(pEnum);
*ppEnum = pEnum; pEnum->AddRef(); // counteract CReleaseMe
}
return hRes; }
//***************************************************************************
//
// CWbemNamespace::CreateClassEnum
//
// Invokes CreateClassEnumAsync and waits for completion. Actual work is
// performed in Exec_CreateClassEnum.
//
// Parameters and return values are described in help
//
//***************************************************************************
HRESULT CWbemNamespace::CreateClassEnum( const BSTR strParent, long lFlags, IWbemContext* pCtx, IEnumWbemClassObject **ppEnum ) { HRESULT hRes = CheckNs(); if (FAILED(hRes)) return hRes;
DEBUGTRACE((LOG_WBEMCORE, "CALL CWbemNamespace::CreateClassEnum\n" " BSTR Parent = %S\n" " long lFlags = 0x%X\n" " IEnumWbemClassObject = 0x%X\n", strParent, lFlags, ppEnum ));
// Validate parameters
// ===================
if (lFlags & ~WBEM_FLAG_DEEP & ~WBEM_FLAG_SHALLOW & ~WBEM_FLAG_USE_AMENDED_QUALIFIERS & ~WBEM_FLAG_RETURN_IMMEDIATELY & ~WBEM_FLAG_FORWARD_ONLY ) return WBEM_E_INVALID_PARAMETER;
if (ppEnum == NULL) return WBEM_E_INVALID_PARAMETER;
*ppEnum = NULL;
// Create Finalizer.
// =================
_IWmiFinalizer *pFnz = 0; hRes = CreateSyncFinalizer(pCtx, &pFnz); if (FAILED(hRes)) return hRes; CReleaseMe _1(pFnz);
ULONG uTaskType = WMICORE_TASK_ENUM_CLASSES; if (lFlags & WBEM_RETURN_IMMEDIATELY) uTaskType |= WMICORE_TASK_TYPE_SEMISYNC; else uTaskType |= WMICORE_TASK_TYPE_SYNC;
// Do the work.
// ============
hRes = _CreateClassEnumAsync(uTaskType, pFnz, 0, strParent, lFlags & ~WBEM_RETURN_IMMEDIATELY & ~WBEM_FLAG_FORWARD_ONLY, pCtx, NULL);
if (FAILED(hRes)) return hRes;
if ((lFlags & WBEM_RETURN_IMMEDIATELY) == 0) pFnz->GetOperationResult(0, INFINITE, &hRes);
if (SUCCEEDED(hRes)) { IEnumWbemClassObject* pEnum = NULL; HRESULT hResTemp = pFnz->GetResultObject(lFlags, IID_IEnumWbemClassObject, (LPVOID*)&pEnum); if (FAILED(hResTemp)) return hResTemp; CReleaseMe _2(pEnum);
*ppEnum = pEnum; pEnum->AddRef(); // Counteract CReleaseMe
} return hRes; }
//***************************************************************************
//
//***************************************************************************
HRESULT CWbemNamespace::ExecQuery( READONLY const BSTR strQueryFormat, READONLY const BSTR strQuery, long lFlags, IWbemContext* pCtx, NEWOBJECT IEnumWbemClassObject** ppEnum ) { HRESULT hRes = CheckNs(); if (FAILED(hRes)) return hRes;
DEBUGTRACE((LOG_WBEMCORE, "CALL CWbemNamespace::ExecQuery\n" " BSTR QueryFormat = %S\n" " BSTR Query = %S\n" " IEnumWbemClassObject **pEnum = 0x%X\n", strQueryFormat, strQuery, ppEnum ));
// Validate parameters
// ===================
if (lFlags & ~WBEM_FLAG_PROTOTYPE & ~WBEM_FLAG_ENSURE_LOCATABLE & ~WBEM_FLAG_USE_AMENDED_QUALIFIERS & ~WBEM_FLAG_KEEP_SHAPE & ~WBEM_RETURN_IMMEDIATELY & ~WBEM_FLAG_FORWARD_ONLY & ~WBEM_FLAG_DIRECT_READ ) return WBEM_E_INVALID_PARAMETER;
if (ppEnum == NULL) return WBEM_E_INVALID_PARAMETER;
try { *ppEnum = NULL;
// Create Finalizer.
_IWmiFinalizer *pFnz = 0; hRes = CreateSyncFinalizer(pCtx, &pFnz); if (FAILED(hRes)) return hRes; CReleaseMe _1(pFnz);
ULONG uTaskType = WMICORE_TASK_EXEC_QUERY; if (lFlags & WBEM_RETURN_IMMEDIATELY) uTaskType |= WMICORE_TASK_TYPE_SEMISYNC; else uTaskType |= WMICORE_TASK_TYPE_SYNC;
// Do the work.
// ============
hRes = _ExecQueryAsync(uTaskType, pFnz, 0, strQueryFormat, strQuery, lFlags & ~WBEM_RETURN_IMMEDIATELY & ~WBEM_FLAG_FORWARD_ONLY, pCtx, NULL);
if (FAILED(hRes)) return hRes;
if ((lFlags & WBEM_RETURN_IMMEDIATELY) == 0) pFnz->GetOperationResult(0, INFINITE, &hRes);
if (SUCCEEDED(hRes)) { IEnumWbemClassObject* pEnum = NULL; HRESULT hResTemp = pFnz->GetResultObject(lFlags, IID_IEnumWbemClassObject, (LPVOID*)&pEnum); if (FAILED(hResTemp)) return hResTemp; CReleaseMe _2(pEnum);
*ppEnum = pEnum; pEnum->AddRef(); // Counteract CReleaseMe
}
return hRes;
} catch(CX_MemoryException &) { return WBEM_E_OUT_OF_MEMORY; } catch(...) { ExceptionCounter c; return WBEM_E_CRITICAL_ERROR; } }
//***************************************************************************
//
// CWbemNamespace::QueryObjectSink
//
// Returns the pointer to the ESS event handler. Clients can use this pointer
// to supply events to WINMGMT. NOTE: this pointer will be NULL if ESS is
// disabled (see cfgmgr.h).
//
// Parameters and return values are described in help
//
//***************************************************************************
HRESULT CWbemNamespace::QueryObjectSink( long lFlags, IWbemObjectSink** ppHandler ) { HRESULT hRes = CheckNs(); if (FAILED(hRes)) return hRes; if (!Allowed(WBEM_FULL_WRITE_REP)) return WBEM_E_ACCESS_DENIED;
if (ppHandler == NULL) return WBEM_E_INVALID_PARAMETER;
*ppHandler = NULL;
if (lFlags != 0) return WBEM_E_INVALID_PARAMETER;
IWbemEventSubsystem_m4* pEss = ConfigMgr::GetEssSink(); if (pEss) { CReleaseMe rm_(pEss);
CWbemPtr<IWbemObjectSink> pEssSink; hRes = pEss->GetNamespaceSink(m_pThisNamespaceFull, &pEssSink);
if ( FAILED(hRes)) return hRes;
CWbemPtr<CSecureEssNamespaceSink> pSecureSink = new CSecureEssNamespaceSink(this,pEssSink);
if ( pSecureSink == NULL ) return WBEM_E_OUT_OF_MEMORY;
hRes = pSecureSink->QueryInterface( IID_IWbemObjectSink, (void**)ppHandler ); return hRes; } else { return WBEM_E_NOT_SUPPORTED; } }
//***************************************************************************
//
// CWbemNamespace::OpenNamespace
//
// Opens a child namespace of this one. Username, password, locale id,
// flags and error object parameters are ignored.
//
// Parameters:
//
// BSTR NsPath Relative path to the namespace
// BSTR User Reserved, must be NULL.
// BSTR Password Reserved, must be NULL.
// long lLocaleId Reserved, must be NULL.
// long lFlags Reserved, must be NULL.
// IWbemServices **pNewContext Destination for the new namespace pointer.
// Must be released by the caller.
// IWbemClassObject** ppErrorObj Reserved, must be NULL.
//
// RETURN VALUES:
//
// WBEM_S_NO_ERROR On success
// WBEM_E_INVALID_PARAMETER Invalid name.
//
//***************************************************************************
HRESULT CWbemNamespace::OpenNamespace( const BSTR NsPath, long lFlags, IWbemContext* pCtx, IWbemServices **ppNewNamespace, IWbemCallResult **ppResult ) { HRESULT hRes = CheckNs(); if (FAILED(hRes)) return hRes;
DEBUGTRACE((LOG_WBEMCORE, "CALL CWbemNamespace::OpenNamespace\n" " BSTR NsPath = %S\n" " long lFlags = %d\n" " IWbemContext* pCtx = 0x%X\n" " IWbemServices **pNewContext = 0x%X\n", NsPath, lFlags, pCtx, ppNewNamespace ));
// Parameter validation.
// =====================
try { if (NsPath == 0 || wcslen(NsPath) == 0 || // SEC:REVIEWED 2002-03-22 : OK
(ppNewNamespace == NULL && ppResult == NULL)) { return WBEM_E_INVALID_PARAMETER; } if (ppNewNamespace == NULL && (lFlags & WBEM_RETURN_IMMEDIATELY) == 0) { return WBEM_E_INVALID_PARAMETER; } if ((lFlags & WBEM_RETURN_IMMEDIATELY) && ppNewNamespace) return WBEM_E_INVALID_PARAMETER;
if(ppNewNamespace) *ppNewNamespace = NULL; if(ppResult) *ppResult = NULL;
if((lFlags & ~WBEM_RETURN_IMMEDIATELY & ~WBEM_FLAG_USE_AMENDED_QUALIFIERS & ~WBEM_FLAG_CONNECT_REPOSITORY_ONLY) != 0) return WBEM_E_INVALID_PARAMETER;
bool bWin9XLocalSecurity = false;
// If here, we found the object, so we open the
// corresponding namespace.
// ============================================
WString NewNs = m_pThisNamespace; NewNs += L"\\"; NewNs += NsPath;
CCallResult* pResult = new CCallResult; if(pResult == NULL) return WBEM_E_OUT_OF_MEMORY; CReleaseMe rmResult(pResult);
// Schedule a request and wait
// ===========================
bool bForClient = m_bForClient ? true : false;
wmilib::auto_ptr<CAsyncReq_OpenNamespace> pReq; pReq.reset( new CAsyncReq_OpenNamespace(this, NewNs, (bWin9XLocalSecurity) ? SecFlagWin9XLocal : lFlags & WBEM_FLAG_CONNECT_REPOSITORY_ONLY, (bWin9XLocalSecurity) ? m_dwPermission : 0, pCtx, pResult, bForClient));
if (NULL == pReq.get()) return WBEM_E_OUT_OF_MEMORY;
hRes = ConfigMgr::EnqueueRequest(pReq.get()); if (FAILED(hRes)) return hRes; pReq.release(); // ownership transferred to queue
if (ppResult) { *ppResult = pResult; pResult->AddRef(); }
if ((lFlags & WBEM_RETURN_IMMEDIATELY) == 0) { hRes = pResult->GetResultServices(INFINITE, ppNewNamespace); }
return hRes; } catch(...) { ExceptionCounter c; return WBEM_E_FAILED; } }
//***************************************************************************
//
//***************************************************************************
//
HRESULT CWbemNamespace::DeleteObject( IN const BSTR strObjectPath, IN long lFlags, IN IWbemContext __RPC_FAR *pCtx, /* [unique][in][out] */ IWbemCallResult __RPC_FAR *__RPC_FAR *ppCallResult ) {
HRESULT hRes; ULONGLONG uInf;
// Parse the path and determine if a class or instance.
IWbemPath *pPath = ConfigMgr::GetNewPath(); CReleaseMe _(pPath);
hRes = pPath->SetText(WBEMPATH_CREATE_ACCEPT_ALL, strObjectPath); if (FAILED(hRes)) return hRes;
hRes = pPath->GetInfo(0, &uInf); if (FAILED(hRes)) return hRes;
if (uInf & WBEMPATH_INFO_IS_CLASS_REF) return DeleteClass(strObjectPath, lFlags, pCtx, ppCallResult); else if (uInf & WBEMPATH_INFO_IS_INST_REF) return DeleteInstance(strObjectPath, lFlags, pCtx, ppCallResult); else return WBEM_E_INVALID_PARAMETER;
}
//***************************************************************************
//
//***************************************************************************
//
HRESULT CWbemNamespace::ExecSyncQuery( IN LPWSTR pszQuery, IN IWbemContext *pCtx, IN LONG lFlags, OUT CFlexArray &aDest ) { HRESULT hRes; CSynchronousSink* pSink = CSynchronousSink::Create(); if (NULL == pSink) return WBEM_E_OUT_OF_MEMORY; pSink->AddRef(); CReleaseMe _1(pSink);
hRes = CQueryEngine::ExecQuery(this, L"WQL", pszQuery, lFlags, pCtx, pSink); if (FAILED(hRes)) return hRes; pSink->Block(); pSink->GetStatus(&hRes, NULL, NULL); if (FAILED(hRes)) return hRes;
aDest.Bind(pSink->GetObjects().GetArray());
return WBEM_S_NO_ERROR; }
//***************************************************************************
//
// CWbemNamespace::MapAssocRefsToClasses
//
// Analyzes the association and determines which reference properties
// point to which endpoints. <pszAssocRef1> is the ref property
// which can point to instances of <pClsDef1> and <pszAssocRef2> is
// the property which can point to instances of <pClsDef2>.
//
//***************************************************************************
//
HRESULT CWbemNamespace::MapAssocRefsToClasses( IN IWbemClassObject *pAssocClass, IN IWbemClassObject *pClsDef1, IN IWbemClassObject *pClsDef2, wmilib::auto_buffer<WCHAR> & pszAssocRef1, wmilib::auto_buffer<WCHAR> & pszAssocRef2) { HRESULT hRes;
// Note 97: Not valid for ternary assoc types
// or derived types.
// ===========================================
// For each ref property, see if it can point to one of the endpoints.
// ===================================================================
pAssocClass->BeginEnumeration(WBEM_FLAG_REFS_ONLY);
while (1) { BSTR strPropName = 0; hRes = pAssocClass->Next(0,&strPropName,0,0,0); CSysFreeMe _1(strPropName);
if (hRes == WBEM_S_NO_MORE_DATA) break;
hRes = CAssocQuery::RoleTest(pClsDef1, pAssocClass, this, strPropName, ROLETEST_MODE_CIMREF_TYPE); if (SUCCEEDED(hRes)) { pszAssocRef1.reset(Macro_CloneLPWSTR(strPropName)); if (NULL == pszAssocRef1.get()) return WBEM_E_OUT_OF_MEMORY; continue; }
hRes = CAssocQuery::RoleTest(pClsDef2, pAssocClass, this, strPropName, ROLETEST_MODE_CIMREF_TYPE); if (SUCCEEDED(hRes)) { pszAssocRef2.reset(Macro_CloneLPWSTR(strPropName)); if (NULL == pszAssocRef2.get()) return WBEM_E_OUT_OF_MEMORY; continue; } } // Enum of ref properties
pAssocClass->EndEnumeration();
if (NULL == pszAssocRef1.get() ||NULL == pszAssocRef2.get()) { pszAssocRef1.reset(NULL); pszAssocRef2.reset(NULL); return WBEM_E_FAILED; }
return WBEM_S_NO_ERROR; }
//***************************************************************************
//
//***************************************************************************
//
HRESULT CWbemNamespace::BuildAssocTriads( IN IWbemClassObject *pAssocClass, // Assoc class
IN IWbemClassObject *pClsDef1, // Class for EP1
IN IWbemClassObject *pClsDef2, // Class for EP2
IN LPWSTR pszJoinProp1, // Matching prop in EP1
IN LPWSTR pszJoinProp2, // Matching prop in EP2
IN LPWSTR pszAssocRef1, // Prop which points to EP1
IN LPWSTR pszAssocRef2, // Prop which points to EP2
IN CFlexArray &aEp1, // EP1 instances
IN CFlexArray &aEp2, // EP2 instances
IN OUT CFlexArray &aTriads // OUT : Triad list
) { HRESULT hRes = WBEM_S_NO_ERROR;
if (pszJoinProp1 == 0 || pszJoinProp2 == 0 || pAssocClass == 0 || pszAssocRef1 == 0 || pszAssocRef2 == 0) return WBEM_E_INVALID_PARAMETER;
// Do the matching.
// ================
for (int i = 0; i < aEp1.Size(); i++) { IWbemClassObject *pObj1 = (IWbemClassObject *) aEp1[i]; CVARIANT v1; if (FAILED(hRes = pObj1->Get(pszJoinProp1, 0, &v1, 0, 0))) return hRes;
for (int i2 = 0; i2 < aEp2.Size(); i2++) { BOOL bMatch = FALSE;
IWbemClassObject *pObj2 = (IWbemClassObject *) aEp2[i2]; CVARIANT v2; pObj2->Get(pszJoinProp2, 0, &v2, 0, 0);
if (V_VT(&v1) == VT_I4 && V_VT(&v2) == VT_I4) { if (v1.GetLONG() == v2.GetLONG()) { bMatch = TRUE; } } else if (V_VT(&v1) == VT_BSTR && V_VT(&v2) == VT_BSTR) { if (wbem_wcsicmp(v1.GetStr(), v2.GetStr()) == 0) { bMatch = TRUE; } }
// If a match, spawn the association and bind it.
// ==============================================
if (bMatch) { IWbemClassObject *pAssocInst = 0; if (FAILED(hRes = pAssocClass->SpawnInstance(0, &pAssocInst))) return hRes; CReleaseMe rmAssoc(pAssocInst);
CVARIANT vPath1, vPath2;
if (FAILED(hRes = pObj1->Get(L"__RELPATH", 0, &vPath1, 0, 0))) return hRes; if (FAILED(hRes = pObj2->Get(L"__RELPATH", 0, &vPath2, 0, 0))) return hRes;
if (FAILED(hRes = pAssocInst->Put(pszAssocRef1, 0, &vPath1, 0))) return hRes; if (FAILED(hRes = pAssocInst->Put(pszAssocRef2, 0, &vPath2, 0))) return hRes;
wmilib::auto_ptr<SAssocTriad> pTriad( new SAssocTriad); if (NULL == pTriad.get()) return WBEM_E_OUT_OF_MEMORY;
pTriad->m_pEp1 = pObj1; pTriad->m_pEp1->AddRef(); pTriad->m_pEp2 = pObj2; pTriad->m_pEp2->AddRef(); pTriad->m_pAssoc = pAssocInst; pTriad->m_pAssoc->AddRef();
if (CFlexArray::no_error != aTriads.Add(pTriad.get())) return WBEM_E_OUT_OF_MEMORY; pTriad.release(); } } }
return hRes; }
//***************************************************************************
//
//***************************************************************************
//
HRESULT CWbemNamespace::ExtractEpInfoFromQuery( IN IWbemQuery *pQuery, wmilib::auto_buffer<WCHAR> & pszRetClass1, wmilib::auto_buffer<WCHAR> & pszRetProp1, wmilib::auto_buffer<WCHAR> & pszRetClass2, wmilib::auto_buffer<WCHAR> & pszRetProp2 ) { HRESULT hRes; SWQLNode *pRoot;
hRes = pQuery->GetAnalysis( WMIQ_ANALYSIS_RESERVED, 0, (LPVOID *) &pRoot );
if (FAILED(hRes)) return hRes;
// Move down the parse tree to find the JOIN clause.
// =================================================
if (!pRoot || pRoot->m_dwNodeType != TYPE_SWQLNode_QueryRoot) return WBEM_E_INVALID_QUERY; pRoot = pRoot->m_pLeft; if (!pRoot || pRoot->m_dwNodeType != TYPE_SWQLNode_Select) return WBEM_E_INVALID_QUERY; pRoot = pRoot->m_pLeft; if (!pRoot || pRoot->m_dwNodeType != TYPE_SWQLNode_TableRefs) return WBEM_E_INVALID_QUERY; pRoot = pRoot->m_pRight; if (!pRoot || pRoot->m_dwNodeType != TYPE_SWQLNode_FromClause) return WBEM_E_INVALID_QUERY; pRoot = pRoot->m_pLeft; if (!pRoot || pRoot->m_dwNodeType != TYPE_SWQLNode_Join) return WBEM_E_INVALID_QUERY;
// We are now at the JOIN node.
// ============================
SWQLNode_Join *pJoin = (SWQLNode_Join *) pRoot;
/* The parse tree is left-heavy and looks like this:
JN Join node / \ / \ JP OC JoinPair OnClause / \ / \ TR TR TableRef TableRef */
// First, get the first table & prop.
// ==================================
SWQLNode_JoinPair *pPair = (SWQLNode_JoinPair *) pJoin->m_pLeft; if (!pPair || pPair->m_dwNodeType != TYPE_SWQLNode_JoinPair) return WBEM_E_INVALID_QUERY;
SWQLNode_TableRef *pT1 = (SWQLNode_TableRef *) pPair->m_pLeft; SWQLNode_TableRef *pT2 = (SWQLNode_TableRef *) pPair->m_pRight;
if (!pT1 || !pT2) return WBEM_E_INVALID_QUERY;
SWQLNode_OnClause *pOC = (SWQLNode_OnClause *) pJoin->m_pRight; if (!pOC) return WBEM_E_INVALID_QUERY;
SWQLNode_RelExpr *pRE = (SWQLNode_RelExpr *) pOC->m_pLeft; if (!pRE) return WBEM_E_INVALID_QUERY;
if (pRE->m_dwExprType != WQL_TOK_TYPED_EXPR) return WBEM_E_INVALID_QUERY;
// We now have the table names available and the matching condition.
// ==================================================================
LPWSTR pszClass = pRE->m_pTypedExpr->m_pTableRef; LPWSTR pszProp = pRE->m_pTypedExpr->m_pColRef; LPWSTR pszClass2 = pRE->m_pTypedExpr->m_pJoinTableRef; LPWSTR pszProp2 = pRE->m_pTypedExpr->m_pJoinColRef;
if (wbem_wcsicmp(pT1->m_pTableName, pszClass) != 0) pszClass = pT1->m_pAlias;
if (wbem_wcsicmp(pT2->m_pTableName, pszClass2) != 0) pszClass2 = pT2->m_pAlias;
if (pszClass == 0 || pszProp == 0 || pszClass2 == 0 || pszProp2 == 0) return WBEM_E_INVALID_QUERY;
pszRetClass1.reset(Macro_CloneLPWSTR(pszClass)); if (NULL == pszRetClass1.get()) return WBEM_E_OUT_OF_MEMORY; pszRetProp1.reset(Macro_CloneLPWSTR(pszProp)); if (NULL == pszRetProp1.get()) return WBEM_E_OUT_OF_MEMORY; pszRetClass2.reset(Macro_CloneLPWSTR(pszClass2)); if (NULL == pszRetClass2.get()) return WBEM_E_OUT_OF_MEMORY; pszRetProp2.reset(Macro_CloneLPWSTR(pszProp2)); if (NULL ==pszRetProp2.get()) return WBEM_E_OUT_OF_MEMORY;
return WBEM_S_NO_ERROR; }
//***************************************************************************
//
// CWbemNamespace::BuildRuleBasedPathToInst
//
// Based on the incoming info, computes the path to the would-be other
// endpoint.
//
// <pEp> The known endpoint.
// <pszJoinProp1> The property in <pEp> which matches the property in the
// unknown EP.
// <pEp2> Class for the other endpoint.
// <pszJoinProp2> The property in the other class which matches the
// <pszJoinProp1> in the known endpoint class.
// <wsNewPath> The proposed path to the instance of class <pEp2>. Who
// knows whether or not we will find it, but we can try.
//
//***************************************************************************
//
HRESULT CWbemNamespace::BuildRuleBasedPathToInst( IWbemClassObject *pEp, LPWSTR pszJoinProp1, IWbemClassObject *pEp2, LPWSTR pszJoinProp2, OUT WString &wsNewPath ) { HRESULT hRes;
// Get the property from the <pEp> which is the cause of all the fuss.
// ===================================================================
_variant_t vProp; hRes = pEp->Get(pszJoinProp1, 0, &vProp, 0, 0); if (FAILED(hRes)) return hRes;
_variant_t vClass2; hRes = pEp2->Get(L"__CLASS", 0, &vClass2, 0, 0); if (FAILED(hRes)) return hRes; if (VT_BSTR != V_VT(&vClass2)) return WBEM_E_INVALID_PARAMETER;
wsNewPath = V_BSTR(&vClass2); wsNewPath += L"."; wsNewPath += pszJoinProp2; wsNewPath += L"=";
// Note 98: Doesn't work for compound keys!! Yuck.
// ===============================================
_variant_t vDest; hRes = VariantChangeType(&vDest, &vProp, 0, VT_BSTR); if (FAILED(hRes)) return hRes;
wsNewPath += V_BSTR(&vDest); return hRes; }
//***************************************************************************
//
// CWbemNamespace::ManufactureAssocs
//
// Manufactures the associations based on the rule in the <pszJoinQuery>
// which was extracted from the <rulebased> qualifier. Queries the two
// endpoint classes and joins the instances to produce the associations
//
// <pAssocClass> The association class definition which contains the rule.
// <pEp> Optional endpoint object. If not NULL, only objects
// which associate to this endpoint will be returned in
// the triad list, typically a single object.
// <pCtx> Call context
// <pszJoinQuery> The rule query text
// <aTriads> Receives the output, an array of SAssocTriad pointers.
// Caller must call SAssocTriad::ArrayCleanup.
//
//***************************************************************************
HRESULT CWbemNamespace::ManufactureAssocs( IN IWbemClassObject *pAssocClass, IN IWbemClassObject *pEp, // Optional
IN IWbemContext *pCtx, IN LPWSTR pszJoinQuery, OUT CFlexArray &aTriads ) { HRESULT hRes; WString q1, q2;
CFlexArray aEp1List; OnDelete<CFlexArray &,void(*)(CFlexArray &),EmptyObjectList> EmptyMe1(aEp1List); CFlexArray aEp2List; OnDelete<CFlexArray &,void(*)(CFlexArray &),EmptyObjectList> EmptyMe2(aEp2List); wmilib::auto_buffer<WCHAR> pClassName1; wmilib::auto_buffer<WCHAR> pClassName2; wmilib::auto_buffer<WCHAR> pszJoinProp1; wmilib::auto_buffer<WCHAR> pszJoinProp2; wmilib::auto_buffer<WCHAR> pszAssocRef1; wmilib::auto_buffer<WCHAR> pszAssocRef2; _IWmiQuery *pQuery = 0;
// Parse the query.
// ================
CCoreServices *pSvc = CCoreServices::CreateInstance(); if (NULL == pSvc) return WBEM_E_OUT_OF_MEMORY; CReleaseMe rmSvc(pSvc);
hRes = pSvc->CreateQueryParser(0, &pQuery); if (FAILED(hRes)) return hRes; CReleaseMe rmQuery(pQuery);
hRes = pQuery->Parse(L"SQL", pszJoinQuery, 0); if (FAILED(hRes)) return hRes;
// Extract the endpoint class names.
// ==================================
hRes = ExtractEpInfoFromQuery(pQuery, pClassName1,pszJoinProp1, pClassName2, pszJoinProp2); if (FAILED(hRes)) return hRes;
// Get the endpoint class defs.
// ============================
IWbemClassObject *pClsDef1 = 0; hRes = InternalGetClass(pClassName1.get(), &pClsDef1); if (FAILED(hRes)) return hRes; CReleaseMe rmCls1(pClsDef1);
IWbemClassObject *pClsDef2 = 0; hRes = InternalGetClass(pClassName2.get(), &pClsDef2); if (FAILED(hRes)) return hRes; CReleaseMe rmCls2(pClsDef2);
// Map which assoc ref properties point to which class.
// ====================================================
hRes = MapAssocRefsToClasses(pAssocClass, pClsDef1, pClsDef2, pszAssocRef1, pszAssocRef2); if (FAILED(hRes)) return hRes;
// If no specific endpoint, an enumeration is requested. We query the endpoint
// classes completely and match everything up.
// ============================================================================
IWbemClassObject *pEp2 = 0; CReleaseMeRef<IWbemClassObject *> rmRefEp2(pEp2);
if (pEp == 0) { // Build the queries.
// ===================
q1 = "select * from "; q1 += pClassName1.get(); q2 = "select * from "; q2 += pClassName2.get();
hRes = ExecSyncQuery(q1, pCtx, 0, aEp1List); if (FAILED(hRes)) return hRes;
hRes = ExecSyncQuery(q2, pCtx, 0, aEp2List); if (FAILED(hRes)) return hRes; } else { // Note 99: Oversimplified in that it doesn't do an enum; assumes a 1:1 mapping.
// Compute the path to the other endpoint based on the rule.
// =============================================================================
WString wsNewPath; hRes = BuildRuleBasedPathToInst(pEp, pszJoinProp1.get(), pClsDef2, pszJoinProp2.get(), wsNewPath); // throws
if (FAILED(hRes)) return hRes;
// Do a get object.
// ================
hRes = InternalGetInstance(wsNewPath, &pEp2); if (FAILED(hRes)) return hRes;
if (CFlexArray::no_error != aEp1List.Add(pEp)) return WBEM_E_OUT_OF_MEMORY; pEp->AddRef(); if (CFlexArray::no_error != aEp2List.Add(pEp2)) return WBEM_E_OUT_OF_MEMORY; pEp2->AddRef(); }
// Now, match up the results.
// For single-object type scenarios, the arrays simply have one element in them. Ho hum.
// =====================================================================================
OnDeleteIf<CFlexArray &,void(*)(CFlexArray &),EmptyObjectList> EmptyMeTriads(aTriads);
hRes = BuildAssocTriads( pAssocClass, pClsDef1, pClsDef2, pszJoinProp1.get(), pszJoinProp2.get(), pszAssocRef1.get(), pszAssocRef2.get(), aEp1List, aEp2List, aTriads // OUT
);
if (FAILED(hRes)) return hRes;
EmptyMeTriads.dismiss(); return hRes; }
//***************************************************************************
//
// CWbemNamespace::GetAceList
//
// Retrieves the ACEs associated with this namespace
//
// <ppAceList> Flexarray to hold ACE list
//
//***************************************************************************
HRESULT CWbemNamespace::GetAceList(CFlexAceArray** ppAceList) { HRESULT hRes=S_OK;
*ppAceList = new CFlexAceArray; if (ppAceList==NULL) hRes = WBEM_E_OUT_OF_MEMORY; else { // 1. Get security descriptor
CNtSecurityDescriptor& sd = GetSDRef();
// 2. Get the DACL
CNtAcl* pDacl; pDacl = sd.GetDacl(); if ( pDacl==NULL ) return WBEM_E_OUT_OF_MEMORY;
CDeleteMe<CNtAcl> dm(pDacl);
// 3. Loop through DACL
int iNumAces = pDacl->GetNumAces(); for ( int i=0; i<iNumAces; i++ ) { CNtAce* Ace; Ace = pDacl->GetAce(i); if ( Ace == NULL ) return WBEM_E_OUT_OF_MEMORY;
(*ppAceList)->Add (Ace); } } return hRes; }
//***************************************************************************
//
// CWbemNamespace::PutAceList
//
// Puts the ACEs associated with this namespace
//
// <ppAceList> Flexarray ACE list
//
//***************************************************************************
HRESULT CWbemNamespace::PutAceList(CFlexAceArray* pFlex) { SCODE sc = S_OK;
CNtAcl DestAcl;
int iNumAces = pFlex->Size(); for (int i=0; i<iNumAces; i++ ) { if ( DestAcl.AddAce ((CNtAce*) pFlex->GetAt(i)) == FALSE ) { return WBEM_E_INVALID_OBJECT; } } if ( m_sd.SetDacl (&DestAcl) == FALSE ) return WBEM_E_INVALID_OBJECT;
sc = StoreSDIntoNamespace(m_pSession, m_pNsHandle, m_sd); if ( !FAILED (sc) ) sc = RecursiveSDMerge(); return sc; }
//***************************************************************************
//
// CWbemNamespace::GetDynamicReferenceClasses
//
// Asks the provider subsystem for dynamic association classes.
//
//
//***************************************************************************
HRESULT CWbemNamespace::GetDynamicReferenceClasses( long lFlags, IWbemContext * pCtx, IWbemObjectSink* pSink ) { HRESULT hRes = WBEM_S_NO_ERROR;
_IWmiProviderAssociatorsHelper* pAssocHelp = NULL;
if ( m_pProvFact) { hRes = m_pProvFact->GetClassProvider( 0, // lFlags
pCtx, m_wszUserName, m_wsLocale, m_pThisNamespace, 0, IID__IWmiProviderAssociatorsHelper, (LPVOID *) &pAssocHelp );
CReleaseMe rm( pAssocHelp );
if ( SUCCEEDED( hRes ) ) { hRes = pAssocHelp->GetReferencesClasses( lFlags, pCtx, pSink ); }
if ( FAILED( hRes ) ) { pSink->SetStatus( 0L, hRes, 0L, 0L ); } } else { pSink->SetStatus( 0L, WBEM_S_NO_ERROR, 0L, 0L ); }
return hRes;
}
|