|
|
#include <unk.h>
#include <wbemcli.h>
#include <wbemprov.h>
#include <atlbase.h>
#include <sync.h>
#include <activeds.h>
#include <genlex.h>
#include <objpath.h>
#include <Utility.h>
#include <ql.h>
#include "PolicSOM.h"
#ifdef TIME_TRIALS
#include <StopWatch.h>
#pragma message("!! Including time trial code !!")
StopWatch EvaluateTimer(L"Somfilter Evaluation", L"C:\\Som.Evaluate.log"); #endif
/******************************\
**** POLICY PROVIDER HELPERS *** \******************************/
#define SOM_RDN L"CN=SOM,CN=WMIPolicy,CN=System"
// returns addref'd pointer back to WinMgmt
IWbemServices* CPolicySOM::GetWMIServices() { CInCritSec lock(&m_CS);
if (m_pWMIMgmt) m_pWMIMgmt->AddRef();
return m_pWMIMgmt; }
// returns addref'd pointer back to m_pADMgmt
IADsContainer *CPolicySOM::GetADServices(wchar_t *pDomain, HRESULT &hres) { CInCritSec lock(&m_CS); IADsContainer *pADsContainer = NULL;
QString SomDN(SOM_RDN), DistDomainName, ObjPath(L"LDAP://");
if(NULL == pDomain) { // **** if this is the 1st time through, get name of domain controller
if(VT_BSTR != m_vDsLocalContext.vt) { CComPtr<IADs> pRootDSE;
// **** get pointer to AD policy template table
hres = ADsGetObject(L"LDAP://rootDSE", IID_IADs, (void**)&pRootDSE); if(FAILED(hres)) { ERRORTRACE((LOG_ESS, "POLICMAN: (ADsGetObject) could not get object: LDAP://rootDSE, 0x%08X\n", hres)); return NULL; } else { hres = pRootDSE->Get(L"defaultNamingContext",&m_vDsLocalContext);
if(FAILED(hres)) { ERRORTRACE((LOG_ESS, "POLICMAN: (IADs::Get) could not get defaultNamingContext, 0x%08X\n", hres)); return NULL; } } }
DistDomainName = m_vDsLocalContext.bstrVal; } else hres = DistNameFromDomainName(QString(pDomain), DistDomainName);
ObjPath << SOM_RDN << L"," << DistDomainName;
hres = ADsGetObject(ObjPath, IID_IADsContainer, (void**) &pADsContainer);
if(NULL == pADsContainer) pADsContainer = CreateContainers(DistDomainName, SomDN);
return pADsContainer; }
// returns false if services pointer has already been set
bool CPolicySOM::SetWMIServices(IWbemServices* pServices) { CInCritSec lock(&m_CS); bool bOldOneNull = FALSE;
if (bOldOneNull = (m_pWMIMgmt == NULL)) { m_pWMIMgmt = pServices; if(pServices) pServices->AddRef(); }
return bOldOneNull; }
// returns false if services pointer has already been set
bool CPolicySOM::SetADServices(IADsContainer* pServices, unsigned context) { CInCritSec lock(&m_CS); bool bOldOneNull = TRUE;
switch(context) { case AD_LOCAL_CONTEXT : case AD_GLOBAL_CONTEXT : m_pADMgmt[context] = pServices; pServices->AddRef(); bOldOneNull = (m_pADMgmt[context] == NULL); break;
default : ; }
return bOldOneNull; }
CPolicySOM::~CPolicySOM() { // WMI services object
if (m_pWMIMgmt) { m_pWMIMgmt->Release(); m_pWMIMgmt= NULL; }
// AD services object
if (NULL != m_pADMgmt) { for(int i = 0; i < AD_MAX_CONTEXT; i++) { if(NULL != m_pADMgmt[i]) { m_pADMgmt[i]->Release(); m_pADMgmt[i] = NULL; } } } };
void* CPolicySOM::GetInterface(REFIID riid) { if(riid == IID_IWbemServices) return &m_XProvider; else if(riid == IID_IWbemProviderInit) return &m_XInit; else return NULL; } /*********************************\
*** Som Specific Implementation *** \*********************************/
// returns addref'd pointer to class object
IWbemClassObject* CPolicySOM::XProvider::GetSomClass() { CInCritSec lock(&m_pObject->m_CS);
if (m_pSOMClassObject == NULL) { IWbemServices* pWinMgmt = NULL;
if (pWinMgmt = m_pObject->GetWMIServices()) { CReleaseMe relMgmt(pWinMgmt); pWinMgmt->GetObject(g_bstrClassSom, WBEM_FLAG_RETURN_WBEM_COMPLETE, NULL, &m_pSOMClassObject, NULL); } }
if (m_pSOMClassObject) m_pSOMClassObject->AddRef();
return m_pSOMClassObject; }
// returns addref'd pointer to emply class instance
IWbemClassObject* CPolicySOM::XProvider::GetSomInstance() { IWbemClassObject* pObj = NULL; IWbemClassObject* pClass = NULL;
if (pClass = GetSomClass()) { CReleaseMe releaseClass(pClass); pClass->SpawnInstance(0, &pObj); }
return pObj; }
CPolicySOM::XProvider::~XProvider() { if (m_pSOMClassObject) { m_pSOMClassObject->Release(); m_pSOMClassObject= NULL; }
if (m_pLocator) { m_pLocator->Release(); m_pLocator = NULL; }
}
HRESULT CPolicySOM::XProvider::GetLocator(IWbemLocator*& pLocator) { HRESULT hr = WBEM_S_NO_ERROR; CInCritSec lock(&m_pObject->m_CS);
if (!m_pLocator) hr = CoCreateInstance(CLSID_WbemAdministrativeLocator, NULL, CLSCTX_ALL, IID_IWbemLocator, (void**)&m_pLocator); if (m_pLocator) { m_pLocator->AddRef(); pLocator = m_pLocator; }
return hr; }
// get namespace denoted by namespaceName
// will release pNamespace if non-null on way in
HRESULT CPolicySOM::XProvider::GetNewNamespace(BSTR namespaceName, IWbemServices*& pNamespace) { HRESULT hr = WBEM_E_FAILED; if (pNamespace) { pNamespace->Release(); pNamespace = NULL; }
IWbemLocator* pLocator = NULL; if (SUCCEEDED(hr = GetLocator(pLocator))) { CReleaseMe relLocator(pLocator); hr = pLocator->ConnectServer(namespaceName, NULL, NULL, NULL, 0, NULL, NULL, &pNamespace); }
return hr; }
// evaulate a single rule
// pNamespace & namespaceName may be NULL on entry
// may be different upon exit
// this is a rudimentary caching mechanism,
// assuming that most of the namespaces in the rules will be the same.
HRESULT CPolicySOM::XProvider::EvaluateRule(IWbemServices*& pNamespace, BSTR& namespaceName, IWbemClassObject* pRule, bool& bResult) { VARIANT v; VariantInit(&v);
// assume failure
HRESULT hr = WBEM_E_FAILED; bResult = false;
// check to see if we're still on the same namespace
if (FAILED(hr = pRule->Get(L"TargetNamespace", 0, &v, NULL, NULL))) bResult = false; else { if ((pNamespace == NULL) || (_wcsicmp(namespaceName, v.bstrVal) != 0)) if (SUCCEEDED(hr = GetNewNamespace(v.bstrVal, pNamespace))) { // keep copy of name
if (namespaceName) { if (!SysReAllocString(&namespaceName, v.bstrVal)) hr = WBEM_E_OUT_OF_MEMORY; } else if (NULL == (namespaceName = SysAllocString(v.bstrVal))) hr = WBEM_E_OUT_OF_MEMORY; } VariantClear(&v); }
// if we're still on track...
if (SUCCEEDED(hr) && SUCCEEDED(hr = pRule->Get(L"Query", 0, &v, NULL, NULL))) {
#ifdef TIME_TRIALS
EvaluateTimer.Start(StopWatch::AtomicTimer); #endif
IEnumWbemClassObject *pEnumerator = NULL; if (SUCCEEDED(hr = pNamespace->ExecQuery(L"WQL", v.bstrVal, WBEM_FLAG_FORWARD_ONLY, NULL, &pEnumerator))) {
#ifdef TIME_TRIALS
EvaluateTimer.Start(StopWatch::ProviderTimer); #endif
ULONG uReturned = 0; IWbemClassObject* pWhoCares = NULL;
if (SUCCEEDED(hr = pEnumerator->Next(WBEM_INFINITE, 1, &pWhoCares, &uReturned)) && uReturned > 0) { // we don't care at all about the result set
// just whether there is anything *in* the result set
bResult = true; pWhoCares->Release(); } pEnumerator->Release(); } #ifdef TIME_TRIALS
else EvaluateTimer.Start(StopWatch::ProviderTimer); #endif
VariantClear(&v); }
// s_false returned when no objects are returned from 'next'
// THIS function has successfully determined that the query failed.
if (hr == WBEM_S_FALSE) hr = WBEM_S_NO_ERROR;
return hr; }
// loop through all rules
// grab namespace & try each query
// TODO: Optimize by caching namespace pointers.
HRESULT CPolicySOM::XProvider::Evaluate(IWbemClassObject* pObj, IWbemClassObject* pOutInstance) { HRESULT hr = WBEM_S_NO_ERROR; HRESULT hrEval = WBEM_S_NO_ERROR; // innocent until proven guilty
bool bResult = true;
VARIANT v; VariantInit(&v);
if (SUCCEEDED(hr = pObj->Get(L"Rules", 0, &v, NULL, NULL))) { SafeArray<IUnknown*, VT_UNKNOWN> rules(&v); long nRules = rules.Size();
// first run optimization: we'll hold onto each namespace as it comes in
// in hopes that the NEXT one will be in the same namespace
// in practice - it probably will be
IWbemServices* pNamespace = NULL; BSTR namespaceName = NULL;
// with each rule:
// get namespace name
// if different than the one we're currently playing with
// get namespace
// issue query
// count results
for(UINT i = 0; (i < nRules) && bResult && SUCCEEDED(hrEval); i++) {
if (rules[i]) { IWbemClassObject* pRule = NULL;
if (SUCCEEDED(rules[i]->QueryInterface(IID_IWbemClassObject, (void**)&pRule))) { hrEval = EvaluateRule(pNamespace, namespaceName, pRule, bResult); pRule->Release(); pRule = NULL; } else { bResult = FALSE; hrEval = hr = WBEM_E_INVALID_PARAMETER; } } }
// clean up after yourself
VariantClear(&v); if (pNamespace) pNamespace->Release(); if (namespaceName) SysFreeString(namespaceName); }
// we done - tell somebody about it!
if (SUCCEEDED(hr)) { HRESULT hrDebug; VARIANT v; VariantInit(&v); v.vt = VT_I4;
if (SUCCEEDED(hrEval)) v.lVal = bResult ? S_OK : S_FALSE; else v.lVal = hrEval; hrDebug = pOutInstance->Put(L"ReturnValue", 0, &v, NULL); }
return hr; }
// loop through each of the references in input obj
// call evaluate for each,
// TODO: Optimize w/ ExecMethodASYNC
HRESULT CPolicySOM::XProvider::BatchEvaluate(IWbemClassObject* pObj, IWbemClassObject* pOutInstance, IWbemServices* pPolicyNamespace) { HRESULT hr = WBEM_S_NO_ERROR; if (pObj == NULL) return WBEM_E_INVALID_PARAMETER;
VARIANT vFilters; VariantInit(&vFilters);
BSTR methodName = SysAllocString(L"Evaluate"); CSysFreeMe freeEvil(methodName);
SAFEARRAY* pResults = NULL;
if (SUCCEEDED(hr = pObj->Get(L"filters", 0, &vFilters, NULL, NULL))) { if ((vFilters.parray == NULL) || (vFilters.parray->cDims != 1) || (vFilters.parray->rgsabound[0].cElements == 0)) hr = WBEM_E_INVALID_PARAMETER; else { long index, lUbound = 0; SafeArrayGetUBound(vFilters.parray, 1, &lUbound);
SAFEARRAYBOUND bounds = {lUbound +1, 0};
pResults = SafeArrayCreate(VT_I4, 1, &bounds); if (!pResults) return WBEM_E_OUT_OF_MEMORY;
for (index = 0; (index <= lUbound) && SUCCEEDED(hr); index++) { BSTR path = NULL;
if (SUCCEEDED(hr = SafeArrayGetElement(vFilters.parray, &index, &path))) { IWbemClassObject* pGazotta = NULL; if (SUCCEEDED(hr = pPolicyNamespace->ExecMethod(path, methodName, 0, NULL, NULL, &pGazotta, NULL))) { CReleaseMe relGazotta(pGazotta); VARIANT v; VariantInit(&v);
hr = pGazotta->Get(L"ReturnValue", 0, &v, NULL, NULL); hr = SafeArrayPutElement(pResults, &index, &v.lVal); } }
SysFreeString(path); } } }
if (SUCCEEDED(hr)) { VARIANT v; VariantInit(&v); v.vt = VT_I4 | VT_ARRAY; v.parray = pResults; hr = pOutInstance->Put(L"Results", 0, &v, NULL);
// no clear - array is deleted separately.
VariantInit(&v); v.vt = VT_I4; v.lVal = hr; hr = pOutInstance->Put(L"ReturnValue", 0, &v, NULL);
}
if (pResults) SafeArrayDestroy(pResults);
VariantClear(&vFilters); return hr; }
/*************************\
*** IWbemProviderInit *** \*************************/
STDMETHODIMP CPolicySOM::XInit::Initialize( LPWSTR, LONG, LPWSTR, LPWSTR, IWbemServices* pServices, IWbemContext* pCtxt, IWbemProviderInitSink* pSink) { HRESULT hres = WBEM_S_NO_ERROR, hres2 = WBEM_S_NO_ERROR;
// **** impersonate client for security
hres = CoImpersonateClient(); if(FAILED(hres)) { ERRORTRACE((LOG_ESS, "POLICMAN: (CoImpersonateClient) could not assume client permissions, 0x%08X\n", hres)); return WBEM_S_ACCESS_DENIED; } else { // **** save WMI name space pointer
m_pObject->SetWMIServices(pServices); }
hres2 = pSink->SetStatus(hres, 0); if(FAILED(hres2)) { ERRORTRACE((LOG_ESS, "POLICMAN: could not set return status\n")); if(SUCCEEDED(hres)) hres = hres2; }
return hres; }
/*******************\
*** IWbemServices *** \*******************/
STDMETHODIMP CPolicySOM::XProvider::GetObjectAsync( /* [in] */ const BSTR ObjectPath, /* [in] */ long lFlags, /* [in] */ IWbemContext __RPC_FAR *pCtx, /* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler) { HRESULT hres = WBEM_S_NO_ERROR, hres2 = WBEM_S_NO_ERROR;
CComPtr<IWbemServices> pNamespace;
CComPtr<IADsContainer> pADsContainer;
CComPtr<IDispatch> pDisp;
CComPtr<IWbemClassObject> pObj;
CComPtr<IDirectoryObject> pDirObj;
VARIANT *pvkeyID = NULL, *pvDomain = NULL;
// **** impersonate client for security
hres = CoImpersonateClient(); if (FAILED(hres)) { ERRORTRACE((LOG_ESS, "POLICMAN: (CoImpersonateClient) could not assume callers permissions, 0x%08X\n",hres)); hres = WBEM_E_ACCESS_DENIED; } else { // **** Check arguments
if(ObjectPath == NULL || pResponseHandler == NULL) { ERRORTRACE((LOG_ESS, "POLICMAN: object path and/or return object are NULL\n")); hres = WBEM_E_INVALID_PARAMETER; } else { // **** parse object path
CObjectPathParser ObjPath(e_ParserAcceptRelativeNamespace);
ParsedObjectPath *pParsedObjectPath = NULL;
if((ObjPath.NoError != ObjPath.Parse(ObjectPath, &pParsedObjectPath)) || (0 != _wcsicmp(g_bstrClassSom, pParsedObjectPath->m_pClass)) || (2 != pParsedObjectPath->m_dwNumKeys)) { ERRORTRACE((LOG_ESS, "POLICMAN: Parse error for object: %S\n", ObjectPath)); hres = WBEM_E_INVALID_QUERY; } else { int x;
for(x = 0; x < pParsedObjectPath->m_dwNumKeys; x++) { if(0 == _wcsicmp((*(pParsedObjectPath->m_paKeys + x))->m_pName, g_bstrDomain)) pvDomain = &((*(pParsedObjectPath->m_paKeys + x))->m_vValue); else if(0 == _wcsicmp((*(pParsedObjectPath->m_paKeys + x))->m_pName, g_bstrID)) pvkeyID = &((*(pParsedObjectPath->m_paKeys + x))->m_vValue); }
pNamespace.Attach(m_pObject->GetWMIServices()); pADsContainer.Attach(m_pObject->GetADServices(pvDomain->bstrVal, hres));
if((FAILED(hres)) || (pNamespace == NULL) || (pADsContainer == NULL)) { ERRORTRACE((LOG_ESS, "POLICMAN: WMI and/or AD services not initialized\n")); hres = ADSIToWMIErrorCodes(hres); } else { try { // **** Get pointer to instance in AD
hres = pADsContainer->GetObject(g_bstrADClassSom, QString(L"CN=") << V_BSTR(pvkeyID), &pDisp); if(FAILED(hres)) hres = ADSIToWMIErrorCodes(hres); else { hres = pDisp->QueryInterface(IID_IDirectoryObject, (void **)&pDirObj); if(SUCCEEDED(hres)) { // **** Get the instance and send it back
hres = Som_ADToCIM(&pObj, pDirObj, pNamespace); if(FAILED(hres)) hres = ADSIToWMIErrorCodes(hres); if(pObj == NULL) hres = WBEM_E_FAILED;
// **** Set object
pResponseHandler->Indicate(1, &pObj); } } } catch(long hret) { hres = ADSIToWMIErrorCodes(hret); ERRORTRACE((LOG_ESS, "POLICMAN: Translation of Policy object from AD to WMI generated HRESULT 0x%08X\n", hres)); } catch(wchar_t *swErrString) { ERRORTRACE((LOG_ESS, "POLICMAN: Caught Exception: %S\n", swErrString)); hres = WBEM_E_FAILED; } catch(...) { ERRORTRACE((LOG_ESS, "POLICMAN: Caught UNKNOWN Exception\n")); hres = WBEM_E_FAILED; } } }
ObjPath.Free(pParsedObjectPath); hres2 = pResponseHandler->SetStatus(0,hres, NULL, NULL); if(FAILED(hres2)) { ERRORTRACE((LOG_ESS, "POLICMAN: could not set return status\n")); if(SUCCEEDED(hres)) hres = hres2; } }
CoRevertToSelf(); }
return hres; }
STDMETHODIMP CPolicySOM::XProvider::CreateInstanceEnumAsync( /* [in] */ const BSTR Class, /* [in] */ long lFlags, /* [in] */ IWbemContext __RPC_FAR *pCtx, /* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler) { return WBEM_E_NOT_SUPPORTED; }
// validate that the rules contained in pInst are proper syntax
// if they are not, an error object is created & an error returned
HRESULT CPolicySOM::XProvider::ValidateRules(IWbemClassObject* pInst, IWbemClassObject*& pErrorObject) { // init the toys we'll be playing with
HRESULT hr = WBEM_S_NO_ERROR; bool bBadQuery = false;
VARIANT vRules; VariantInit(&vRules);
SAFEARRAY* pResults = NULL;
if (FAILED(pInst->Get(L"Rules", 0, &vRules, NULL, NULL)) || (vRules.vt != (VT_UNKNOWN | VT_ARRAY))) hr = WBEM_E_INVALID_PARAMETER; else { // good to go, we'll create the array to keep logic simple
long index, lUbound = 0; SafeArrayGetUBound(vRules.parray, 1, &lUbound); SAFEARRAYBOUND bounds = {lUbound +1, 0}; pResults = SafeArrayCreate(VT_I4, 1, &bounds);
if (!pResults) hr = WBEM_E_OUT_OF_MEMORY; else for (index = 0; (index <= lUbound) && SUCCEEDED(hr); index++) { // get the MSFT_Rule out of the MSFT_SomFilter
IWbemClassObject* pRule = NULL; if (SUCCEEDED(hr = SafeArrayGetElement(vRules.parray, &index, &pRule))) { HRESULT hrParse = 0; VARIANT vQueryLanguage; VariantInit(&vQueryLanguage); if (SUCCEEDED(hr = pRule->Get(L"QueryLanguage", 0, &vQueryLanguage, NULL, NULL)) && (vQueryLanguage.vt == VT_BSTR) && (vQueryLanguage.bstrVal != NULL)) { if (0 != _wcsicmp(vQueryLanguage.bstrVal, L"WQL")) { hrParse = WBEM_E_INVALID_QUERY_TYPE; bBadQuery = true; } else { VARIANT vQuery; VariantInit(&vQuery);
// get the query out of the MSFT_Rule.
if (SUCCEEDED(hr = pRule->Get(L"Query", 0, &vQuery, NULL, NULL)) && (vQuery.vt == VT_BSTR) && (vQuery.bstrVal != NULL)) { CTextLexSource src(vQuery.bstrVal); QL1_Parser parser(&src); QL_LEVEL_1_RPN_EXPRESSION *pExp = NULL; // if it parses, we good, else we bad.
if(parser.Parse(&pExp)) { hrParse = WBEM_E_INVALID_QUERY; bBadQuery = true; }
if (pExp) delete pExp; } else hrParse = WBEM_E_INVALID_PARAMETER;
VariantClear(&vQuery); } } else hrParse = WBEM_E_INVALID_PARAMETER;
SafeArrayPutElement(pResults, &index, (void*)&hrParse); pRule->Release();
VariantClear(&vQueryLanguage); } } } // if we found a bad query, we create an error object to hold the info
if (bBadQuery) { IWbemServices* pSvc = m_pObject->GetWMIServices(); IWbemClassObject* pErrorClass = NULL; BSTR name = SysAllocString(L"SomFilterPutStatus");
if (pSvc && name && SUCCEEDED(hr = pSvc->GetObject(name, 0, NULL, &pErrorClass, NULL)) && SUCCEEDED(hr = pErrorClass->SpawnInstance(0, &pErrorObject))) { hr = WBEM_E_INVALID_PARAMETER; HRESULT hrDebug;
// variant to hold array - don't clear it, the array is destroyed elsewhere
VARIANT vResultArray; VariantInit(&vResultArray); vResultArray.vt = VT_I4 | VT_ARRAY; vResultArray.parray = pResults;
hrDebug = pErrorObject->Put(L"RuleValidationResults", 0, &vResultArray, NULL);
// other interesting error vals.
VARIANT vTemp; vTemp.vt = VT_BSTR; vTemp.bstrVal = SysAllocString(L"PutInstance"); hrDebug = pErrorObject->Put(L"Operation",0,&vTemp,NULL); SysFreeString(vTemp.bstrVal); vTemp.bstrVal = SysAllocString(L"PolicSOM"); hrDebug = pErrorObject->Put(L"ProviderName",0,&vTemp,NULL); SysFreeString(vTemp.bstrVal);
vTemp.vt = VT_I4; vTemp.lVal = WBEM_E_INVALID_QUERY; hrDebug = pErrorObject->Put(L"StatusCode",0,&vTemp,NULL);
//BSTR debuggy = NULL;
//pErrorObject->GetObjectText(0, &debuggy);
}
if (pSvc) pSvc->Release(); if (name) SysFreeString(name); if (pErrorClass) pErrorClass->Release(); }
// cleanup
VariantClear(&vRules); if (pResults) SafeArrayDestroy(pResults);
return hr; }
STDMETHODIMP CPolicySOM::XProvider::PutInstanceAsync( /* [in] */ IWbemClassObject __RPC_FAR *pInst, /* [in] */ long lFlags, /* [in] */ IWbemContext __RPC_FAR *pCtx, /* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler) { HRESULT hres = WBEM_S_NO_ERROR, hres2 = WBEM_S_NO_ERROR; CComPtr<IADsContainer> pADsContainer; CComPtr<IDirectoryObject> pDirObj; CComVariant v1, vRelPath; ADsStruct<ADS_OBJECT_INFO> pInfo; // **** impersonate client
hres = CoImpersonateClient(); if(FAILED(hres)) { ERRORTRACE((LOG_ESS, "POLICMAN: (CoImpersonateClient) could not assume callers permissions, 0x%08X\n",hres)); hres = WBEM_E_ACCESS_DENIED; } else { // **** check arguments
if((NULL == pInst) || (NULL == pResponseHandler)) { ERRORTRACE((LOG_ESS, "POLICMAN: (CoImpersonateClient) could not assume callers permissions, 0x%08X\n",hres)); hres = WBEM_E_ACCESS_DENIED; } else { IWbemClassObject* pErrorObject = NULL; if SUCCEEDED(hres = ValidateRules(pInst, pErrorObject)) { // **** put policy obj into AD
try { EnsureID(pInst, NULL); // **** aquire AD path in which to place object
hres = pInst->Get(g_bstrDomain, 0, &v1, NULL, NULL); if(FAILED(hres)) return hres; if(VT_BSTR == v1.vt) pADsContainer.Attach(m_pObject->GetADServices(v1.bstrVal, hres)); else pADsContainer.Attach(m_pObject->GetADServices(NULL, hres)); if((FAILED(hres)) || (pADsContainer == NULL)) { ERRORTRACE((LOG_ESS, "POLICMAN: Could not find or connect to domain: %S\n", V_BSTR(&v1))); return ADSIToWMIErrorCodes(hres); } hres = pADsContainer->QueryInterface(IID_IDirectoryObject, (void **)&pDirObj); if(FAILED(hres)) return ADSIToWMIErrorCodes(hres); // **** copy policy obj into AD
hres = Som_CIMToAD(pInst, pDirObj, lFlags); if(FAILED(hres)) { if(0x800700a == hres) ERRORTRACE((LOG_ESS, "POLICMAN: Active Directory Schema for MSFT_SomFilter is invalid/missing\n"));
return ADSIToWMIErrorCodes(hres); } } catch(long hret) { hres = ADSIToWMIErrorCodes(hret); ERRORTRACE((LOG_ESS, "POLICMAN: Translation of Policy object from WMI to AD generated HRESULT 0x%08X\n", hres)); } catch(wchar_t *swErrString) { ERRORTRACE((LOG_ESS, "POLICMAN: Caught Exception: %S\n", swErrString)); hres = WBEM_E_FAILED; } catch(...) { ERRORTRACE((LOG_ESS, "POLICMAN: Caught unknown Exception\n")); hres = WBEM_E_FAILED; } } if(FAILED(hres) && pErrorObject) { if(FAILED(pResponseHandler->SetStatus(0,hres, NULL, pErrorObject))) ERRORTRACE((LOG_ESS, "POLICMAN: could not set return status\n")); } else { // **** indicate return status
pInst->Get(L"__RELPATH", 0, &vRelPath, NULL, NULL); if(FAILED(pResponseHandler->SetStatus(0,hres, vRelPath.bstrVal, NULL))) ERRORTRACE((LOG_ESS, "POLICMAN: could not set return status\n")); } if (pErrorObject) pErrorObject->Release(); } CoRevertToSelf(); } return hres; }
STDMETHODIMP CPolicySOM::XProvider::DeleteInstanceAsync( /* [in] */ const BSTR ObjectPath, /* [in] */ long lFlags, /* [in] */ IWbemContext __RPC_FAR *pCtx, /* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler) { HRESULT hres = WBEM_S_NO_ERROR, hres2 = WBEM_S_NO_ERROR;
CComPtr<IADsContainer> pADsContainer;
CComPtr<IDispatch> pDisp;
CComPtr<IADsDeleteOps> pDelObj;
VARIANT *pvDomain = NULL, *pvkeyID = NULL;
ParsedObjectPath *pParsedObjectPath = NULL;
// **** impersonate client
hres = CoImpersonateClient(); if(FAILED(hres)) { ERRORTRACE((LOG_ESS, "POLICMAN: (CoImpersonateClient) could not assume callers permissions, 0x%08X\n",hres)); hres = WBEM_E_ACCESS_DENIED; } else { // **** Check arguments
if(ObjectPath == NULL || pResponseHandler == NULL) { ERRORTRACE((LOG_ESS, "POLICMAN: object handle and/or return status object are NULL\n")); hres = WBEM_E_INVALID_PARAMETER; } else { // **** parse object path
CObjectPathParser ObjPath(e_ParserAcceptRelativeNamespace);
if((ObjPath.NoError != ObjPath.Parse(ObjectPath, &pParsedObjectPath)) || (0 != _wcsicmp(g_bstrClassSom, pParsedObjectPath->m_pClass)) || (2 != pParsedObjectPath->m_dwNumKeys)) { ERRORTRACE((LOG_ESS, "POLICMAN: Parse error for object: %S\n", ObjectPath)); hres = WBEM_E_INVALID_QUERY; } else { int x;
for(x = 0; x < pParsedObjectPath->m_dwNumKeys; x++) { if(0 == _wcsicmp((*(pParsedObjectPath->m_paKeys + x))->m_pName, g_bstrDomain)) pvDomain = &((*(pParsedObjectPath->m_paKeys + x))->m_vValue); else if(0 == _wcsicmp((*(pParsedObjectPath->m_paKeys + x))->m_pName, g_bstrID)) pvkeyID = &((*(pParsedObjectPath->m_paKeys + x))->m_vValue); }
pADsContainer.Attach(m_pObject->GetADServices(pvDomain->bstrVal, hres)); if((FAILED(hres)) || (pADsContainer == NULL)) { ERRORTRACE((LOG_ESS, "POLICMAN: Could not find domain: %S\n", V_BSTR(pvDomain))); hres = ADSIToWMIErrorCodes(hres); } else { // **** get pointer to instance in AD
hres = pADsContainer->GetObject(g_bstrADClassSom, QString(L"CN=") << V_BSTR(pvkeyID), &pDisp); if(FAILED(hres)) { hres = ADSIToWMIErrorCodes(hres); ERRORTRACE((LOG_ESS, "POLICMAN: (IADsContainer::GetObject) could not get object in AD %S, 0x%08X\n", V_BSTR(pvkeyID), hres)); } else { hres = pDisp->QueryInterface(IID_IADsDeleteOps, (void **)&pDelObj); if(FAILED(hres)) { ERRORTRACE((LOG_ESS, "POLICMAN: (IDispatch::QueryInterface) could not get IID_IADsDeleteOps interface on object\n")); } else { // **** delete the instance and all its children in AD
hres = pDelObj->DeleteObject(0); if(FAILED(hres)) { ERRORTRACE((LOG_ESS, "POLICMAN: (IADsDeleteOps::DeleteObject) could not delete object (0x%08X)\n", hres)); hres = WBEM_E_ACCESS_DENIED; } } } } }
ObjPath.Free(pParsedObjectPath); hres2 = pResponseHandler->SetStatus(0,hres, NULL, NULL); if(FAILED(hres2)) { ERRORTRACE((LOG_ESS, "POLICMAN: could not set return status\n")); if(SUCCEEDED(hres)) hres = hres2; } }
CoRevertToSelf(); }
return hres; }
STDMETHODIMP CPolicySOM::XProvider::ExecQueryAsync( /* [in] */ const BSTR QueryLanguage, /* [in] */ const BSTR Query, /* [in] */ long lFlags, /* [in] */ IWbemContext __RPC_FAR *pCtx, /* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler) { HRESULT hres = WBEM_E_FAILED;
CComPtr<IWbemServices> pNameSpace;
hres = CoImpersonateClient(); if(FAILED(hres)) { ERRORTRACE((LOG_ESS, "POLICMAN: (CoImpersonateClient) could not assume callers permissions, 0x%08X\n",hres)); hres = WBEM_E_ACCESS_DENIED; } else { pNameSpace.Attach(m_pObject->GetWMIServices()); hres = ExecuteWQLQuery(SOM_RDN, Query, pResponseHandler, pNameSpace, g_bstrADClassSom, Som_ADToCIM);
if(pResponseHandler != NULL) pResponseHandler->SetStatus(0, hres, 0, 0); }
CoRevertToSelf();
return hres; }
STDMETHODIMP CPolicySOM::XProvider::ExecMethodAsync( /* [in] */ const BSTR strObjectPath, /* [in] */ const BSTR strMethodName, /* [in] */ long lFlags, /* [in] */ IWbemContext __RPC_FAR *pCtx, /* [in] */ IWbemClassObject __RPC_FAR *pInParams, /* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler) { HRESULT hr = WBEM_E_FAILED;
#ifdef TIME_TRIALS
EvaluateTimer.Start(StopWatch::ProviderTimer); #endif
enum WhichMethod {Eval, BatchEval}; WhichMethod whichMethod;
// check for valid method name
if (_wcsicmp(strMethodName, L"Evaluate") == 0) whichMethod = Eval; else if (_wcsicmp(strMethodName, L"BatchEvaluate") == 0) whichMethod = BatchEval; else return WBEM_E_INVALID_METHOD; // **** impersonate client for security
hr = CoImpersonateClient(); if (FAILED(hr)) return hr; // retrieve target object
CComPtr<IWbemServices> pService;
pService.Attach(m_pObject->GetWMIServices()); if (pService == NULL) hr = WBEM_E_FAILED; else { IWbemClassObject* pObj = NULL;
#ifdef TIME_TRIALS
EvaluateTimer.Start(StopWatch::WinMgmtTimer); #endif
if (SUCCEEDED(hr = pService->GetObject(strObjectPath, WBEM_FLAG_RETURN_WBEM_COMPLETE, pCtx, &pObj, NULL))) {
#ifdef TIME_TRIALS
EvaluateTimer.Start(StopWatch::ProviderTimer); #endif
CReleaseMe releaseObj(pObj);
// retreive class & output param object
IWbemClassObject* pOurClass; if (NULL == (pOurClass = GetSomClass())) hr = WBEM_E_FAILED; else { CReleaseMe releaseClass(pOurClass);
IWbemClassObject* pOutClass = NULL; if (SUCCEEDED(hr = pOurClass->GetMethod(strMethodName, 0, NULL, &pOutClass))) { CReleaseMe releaseOut(pOutClass); IWbemClassObject* pOutInstance = NULL; if (SUCCEEDED(pOutClass->SpawnInstance(0, &pOutInstance))) { CReleaseMe releaseInnerOut(pOutInstance);
if (whichMethod == Eval) hr = Evaluate(pObj, pOutInstance); else if (whichMethod == BatchEval) hr = BatchEvaluate(pInParams, pOutInstance, pService); else hr = WBEM_E_INVALID_METHOD;
if (SUCCEEDED(hr)) hr = pResponseHandler->Indicate(1, &pOutInstance);
} } } } else hr = WBEM_E_NOT_FOUND; }
#ifdef TIME_TRIALS
EvaluateTimer.Stop(); EvaluateTimer.LogResults(); EvaluateTimer.Reset(); // for next time!
#endif
// difficult call - do we put this before or after we take the timestamp?
pResponseHandler->SetStatus(0,hr,NULL, NULL); CoRevertToSelf();
return hr; }
|