1467 lines
42 KiB
C++
1467 lines
42 KiB
C++
|
#include <unk.h>
|
||
|
#include <wbemcli.h>
|
||
|
#include <wbemprov.h>
|
||
|
#include <atlbase.h>
|
||
|
#include <sync.h>
|
||
|
#include <ql.h>
|
||
|
#include "activeds.h"
|
||
|
#include "genlex.h"
|
||
|
#include "objpath.h"
|
||
|
#include "Utility.h"
|
||
|
|
||
|
#include "polictempl.h"
|
||
|
|
||
|
/******************************\
|
||
|
**** POLICY PROVIDER HELPERS ***
|
||
|
\******************************/
|
||
|
|
||
|
#define TEMPLATE_RDN L"CN=PolicyTemplate,CN=WMIPolicy,CN=System"
|
||
|
|
||
|
// returns addref'd pointer back to m_pWMIMgmt
|
||
|
IWbemServices* CPolicyTemplate::GetWMIServices(void)
|
||
|
{
|
||
|
CInCritSec lock(&m_CS);
|
||
|
|
||
|
if (NULL != m_pWMIMgmt)
|
||
|
m_pWMIMgmt->AddRef();
|
||
|
|
||
|
return m_pWMIMgmt;
|
||
|
}
|
||
|
|
||
|
// returns addref'd pointer back to m_pADMgmt
|
||
|
IADsContainer *CPolicyTemplate::GetADServices(wchar_t *pDomain)
|
||
|
{
|
||
|
DEBUGTRACE((LOG_ESS, "POLICMAN: [PolicyTemplate] GetADServices (%S)\n", pDomain));
|
||
|
|
||
|
CInCritSec lock(&m_CS);
|
||
|
IADsContainer *pADsContainer = NULL;
|
||
|
HRESULT hres;
|
||
|
|
||
|
QString
|
||
|
DistDomainName;
|
||
|
|
||
|
if(NULL == pDomain)
|
||
|
DistDomainName = m_vDsLocalContext.bstrVal;
|
||
|
else
|
||
|
hres = DistNameFromDomainName(QString(pDomain), DistDomainName);
|
||
|
|
||
|
hres = ADsGetObject(QString(L"LDAP://") << TEMPLATE_RDN << L"," << DistDomainName,
|
||
|
IID_IADsContainer,
|
||
|
(void**) &pADsContainer);
|
||
|
|
||
|
if(NULL == pADsContainer)
|
||
|
pADsContainer = CreateContainers(DistDomainName, QString(TEMPLATE_RDN));
|
||
|
|
||
|
return pADsContainer;
|
||
|
}
|
||
|
|
||
|
// returns false if services pointer has already been set
|
||
|
bool CPolicyTemplate::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 CPolicyTemplate::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;
|
||
|
}
|
||
|
|
||
|
CPolicyTemplate::~CPolicyTemplate()
|
||
|
{
|
||
|
// **** WMI services object
|
||
|
|
||
|
if (NULL != 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* CPolicyTemplate::GetInterface(REFIID riid)
|
||
|
{
|
||
|
if(riid == IID_IWbemServices)
|
||
|
return &m_XProvider;
|
||
|
else if(riid == IID_IWbemProviderInit)
|
||
|
return &m_XInit;
|
||
|
else return NULL;
|
||
|
}
|
||
|
|
||
|
/*********************************************\
|
||
|
*** Policy Template Specific Implementation ***
|
||
|
\*********************************************/
|
||
|
|
||
|
// returns addref'd pointer to class object
|
||
|
IWbemClassObject* CPolicyTemplate::XProvider::GetPolicyTemplateClass()
|
||
|
{
|
||
|
CInCritSec lock(&m_pObject->m_CS);
|
||
|
|
||
|
if(NULL == m_pWMIPolicyClassObject)
|
||
|
{
|
||
|
IWbemServices* pWinMgmt = NULL;
|
||
|
|
||
|
if(pWinMgmt = m_pObject->GetWMIServices())
|
||
|
{
|
||
|
CReleaseMe relMgmt(pWinMgmt);
|
||
|
pWinMgmt->GetObject(g_bstrClassMergeablePolicy,
|
||
|
WBEM_FLAG_RETURN_WBEM_COMPLETE,
|
||
|
NULL,
|
||
|
&m_pWMIPolicyClassObject,
|
||
|
NULL);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (m_pWMIPolicyClassObject)
|
||
|
m_pWMIPolicyClassObject->AddRef();
|
||
|
|
||
|
return m_pWMIPolicyClassObject;
|
||
|
}
|
||
|
|
||
|
// returns addref'd pointer to emply class instance
|
||
|
IWbemClassObject* CPolicyTemplate::XProvider::GetPolicyTemplateInstance()
|
||
|
{
|
||
|
IWbemClassObject* pObj = NULL;
|
||
|
IWbemClassObject* pClass = NULL;
|
||
|
|
||
|
if (pClass = GetPolicyTemplateClass())
|
||
|
{
|
||
|
CReleaseMe releaseClass(pClass);
|
||
|
pClass->SpawnInstance(0, &pObj);
|
||
|
}
|
||
|
|
||
|
return pObj;
|
||
|
}
|
||
|
|
||
|
|
||
|
CPolicyTemplate::XProvider::~XProvider()
|
||
|
{
|
||
|
// I fixed it! - HMH ;-)
|
||
|
// CInCritSec lock(&m_pObject->m_CS);
|
||
|
|
||
|
if(NULL != m_pWMIPolicyClassObject)
|
||
|
{
|
||
|
m_pWMIPolicyClassObject->Release();
|
||
|
m_pWMIPolicyClassObject = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*************************\
|
||
|
*** IWbemProviderInit ***
|
||
|
\*************************/
|
||
|
|
||
|
STDMETHODIMP CPolicyTemplate::XInit::Initialize(
|
||
|
LPWSTR, LONG, LPWSTR, LPWSTR, IWbemServices* pServices, IWbemContext* pCtxt,
|
||
|
IWbemProviderInitSink* pSink)
|
||
|
{
|
||
|
DEBUGTRACE((LOG_ESS, "POLICMAN: [PolicyTemplate] IWbemProviderInit::Initialize\n"));
|
||
|
|
||
|
CComPtr<IADs>
|
||
|
pRootDSE;
|
||
|
|
||
|
CComPtr<IADsContainer>
|
||
|
pObject;
|
||
|
|
||
|
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));
|
||
|
hres = WBEM_S_ACCESS_DENIED;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// **** safe WMI name space pointer
|
||
|
|
||
|
m_pObject->SetWMIServices(pServices);
|
||
|
|
||
|
// **** 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));
|
||
|
hres = WBEM_E_NOT_FOUND;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hres = pRootDSE->Get(L"defaultNamingContext",&m_pObject->m_vDsLocalContext);
|
||
|
if(FAILED(hres))
|
||
|
{
|
||
|
ERRORTRACE((LOG_ESS, "POLICMAN: (IADs::Get) could not get defaultNamingContext, 0x%08X\n", hres));
|
||
|
hres = WBEM_E_NOT_FOUND;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
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 CPolicyTemplate::XProvider::GetObjectAsync(
|
||
|
/* [in] */ const BSTR ObjectPath,
|
||
|
/* [in] */ long lFlags,
|
||
|
/* [in] */ IWbemContext __RPC_FAR *pCtx,
|
||
|
/* [in] */ IWbemObjectSink __RPC_FAR *pResponse)
|
||
|
{
|
||
|
DEBUGTRACE((LOG_ESS, "POLICMAN: [PolicyTemplate] IWbemServices::GetObjectAsync(%S, 0x%x, 0x%x, 0x%x)\n", ObjectPath, lFlags, pCtx, pResponse));
|
||
|
|
||
|
HRESULT
|
||
|
hres = WBEM_S_NO_ERROR,
|
||
|
hres2 = WBEM_S_NO_ERROR;
|
||
|
|
||
|
VARIANT
|
||
|
*pvDomain = NULL,
|
||
|
*pvkeyID = NULL;
|
||
|
|
||
|
CComPtr<IDispatch>
|
||
|
pDisp;
|
||
|
|
||
|
CComPtr<IWbemClassObject>
|
||
|
pObj;
|
||
|
|
||
|
CComPtr<IDirectoryObject>
|
||
|
pDirObj;
|
||
|
|
||
|
CComPtr<IWbemServices>
|
||
|
pNamespace;
|
||
|
|
||
|
CComPtr<IADsContainer>
|
||
|
pADsContainer;
|
||
|
|
||
|
// **** 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
|
||
|
{
|
||
|
pNamespace = m_pObject->GetWMIServices();
|
||
|
|
||
|
if(pNamespace == NULL)
|
||
|
{
|
||
|
ERRORTRACE((LOG_ESS, "POLICMAN: WMI services not initialized\n"));
|
||
|
hres = WBEM_E_NOT_FOUND;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// **** Check arguments
|
||
|
|
||
|
if(ObjectPath == NULL || pResponse == 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_bstrClassMergeablePolicy, pParsedObjectPath->m_pClass)) &&
|
||
|
(0 != _wcsicmp(g_bstrClassSimplePolicy, 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;
|
||
|
|
||
|
// **** only grab ID key for now
|
||
|
|
||
|
for(x = 0; x < pParsedObjectPath->m_dwNumKeys; x++)
|
||
|
{
|
||
|
if(0 == _wcsicmp((*(pParsedObjectPath->m_paKeys + x))->m_pName, g_bstrID))
|
||
|
pvkeyID = &((*(pParsedObjectPath->m_paKeys + x))->m_vValue);
|
||
|
else if(0 == _wcsicmp((*(pParsedObjectPath->m_paKeys + x))->m_pName, g_bstrDomain))
|
||
|
pvDomain = &((*(pParsedObjectPath->m_paKeys + x))->m_vValue);
|
||
|
}
|
||
|
|
||
|
try
|
||
|
{
|
||
|
pADsContainer = m_pObject->GetADServices(pvDomain->bstrVal);
|
||
|
if(pADsContainer == NULL)
|
||
|
{
|
||
|
ERRORTRACE((LOG_ESS, "POLICMAN: Could not find domain: %S\n", V_BSTR(pvDomain)));
|
||
|
return WBEM_E_ACCESS_DENIED;
|
||
|
}
|
||
|
|
||
|
// **** Get pointer to instance in AD
|
||
|
|
||
|
hres = pADsContainer->GetObject(NULL, QString(L"CN=") << V_BSTR(pvkeyID), &pDisp);
|
||
|
if(FAILED(hres)) return ADSIToWMIErrorCodes(hres);
|
||
|
|
||
|
hres = pDisp->QueryInterface(IID_IDirectoryObject, (void **)&pDirObj);
|
||
|
if(FAILED(hres)) return hres;
|
||
|
|
||
|
// **** HACK **** do quick check to see if object is of correct type
|
||
|
|
||
|
{
|
||
|
CComVariant
|
||
|
vObjType;
|
||
|
|
||
|
CComQIPtr<IADs, &IID_IADs>
|
||
|
pADsObj = pDirObj;
|
||
|
|
||
|
hres2 = pADsObj->Get(g_bstrADNormalizedClass, &vObjType);
|
||
|
if(FAILED(hres2)) return hres2;
|
||
|
|
||
|
if(_wcsicmp(vObjType.bstrVal, pParsedObjectPath->m_pClass))
|
||
|
return WBEM_E_NOT_FOUND;
|
||
|
}
|
||
|
|
||
|
// **** Get the instance and send it back
|
||
|
|
||
|
hres = Policy_ADToCIM(&pObj, pDirObj, pNamespace);
|
||
|
if(pObj == NULL) return WBEM_E_FAILED;
|
||
|
|
||
|
// **** Set object
|
||
|
|
||
|
pResponse->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 = pResponse->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 CPolicyTemplate::XProvider::CreateInstanceEnumAsync(/* [in] */ const BSTR Class,
|
||
|
/* [in] */ long lFlags,
|
||
|
/* [in] */ IWbemContext __RPC_FAR *pCtx,
|
||
|
/* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler)
|
||
|
{
|
||
|
return WBEM_E_NOT_SUPPORTED;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CPolicyTemplate::XProvider::PutInstanceAsync(
|
||
|
/* [in] */ IWbemClassObject __RPC_FAR *pInst,
|
||
|
/* [in] */ long lFlags,
|
||
|
/* [in] */ IWbemContext __RPC_FAR *pCtx,
|
||
|
/* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler)
|
||
|
{
|
||
|
DEBUGTRACE((LOG_ESS, "POLICMAN: [PolicyTemplate] IWbemServices::PutInstanceAsync(0x%x, 0x%x, 0x%x, 0x%x)\n", pInst, lFlags, pCtx, pResponseHandler));
|
||
|
|
||
|
HRESULT
|
||
|
hres = WBEM_S_NO_ERROR,
|
||
|
hres2 = WBEM_S_NO_ERROR;
|
||
|
|
||
|
CComPtr<IADsContainer>
|
||
|
pADsContainer;
|
||
|
|
||
|
CComPtr<IDirectoryObject>
|
||
|
pDirObj;
|
||
|
|
||
|
CComVariant
|
||
|
v1, vRelPath;
|
||
|
|
||
|
// **** 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: object handle and/or return status object are NULL\n"));
|
||
|
hres = WBEM_E_INVALID_PARAMETER;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// **** 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 = m_pObject->GetADServices(v1.bstrVal);
|
||
|
else
|
||
|
pADsContainer = m_pObject->GetADServices(NULL);
|
||
|
|
||
|
if(pADsContainer == NULL)
|
||
|
{
|
||
|
ERRORTRACE((LOG_ESS, "POLICMAN: Could not find or connect to domain: %S\n", V_BSTR(&v1)));
|
||
|
return WBEM_E_ACCESS_DENIED;
|
||
|
}
|
||
|
|
||
|
hres = pADsContainer->QueryInterface(IID_IDirectoryObject, (void **)&pDirObj);
|
||
|
if(FAILED(hres)) return hres;
|
||
|
|
||
|
// **** copy policy obj into AD
|
||
|
|
||
|
hres = Policy_CIMToAD(lFlags, pInst, pDirObj);
|
||
|
if(FAILED(hres)) 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;
|
||
|
}
|
||
|
|
||
|
// **** send it back as we may have added keys
|
||
|
if (SUCCEEDED(hres))
|
||
|
pResponseHandler->Indicate(1, &pInst);
|
||
|
|
||
|
// **** indicate return status
|
||
|
|
||
|
pInst->Get(L"__RELPATH", 0, &vRelPath, NULL, NULL);
|
||
|
if(FAILED(pResponseHandler->SetStatus(0, hres, V_BSTR(&vRelPath), NULL)))
|
||
|
{
|
||
|
ERRORTRACE((LOG_ESS, "POLICMAN: could not set return status\n"));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CoRevertToSelf();
|
||
|
}
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CPolicyTemplate::XProvider::DeleteInstanceAsync(
|
||
|
/* [in] */ const BSTR ObjectPath,
|
||
|
/* [in] */ long lFlags,
|
||
|
/* [in] */ IWbemContext __RPC_FAR *pCtx,
|
||
|
/* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler)
|
||
|
{
|
||
|
DEBUGTRACE((LOG_ESS, "POLICMAN: [PolicyTemplate] IWbemServices::DeleteInstanceAsync(%S, 0x%x, 0x%x, 0x%x)\n", ObjectPath, lFlags, pCtx, 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 WMI object path
|
||
|
|
||
|
CObjectPathParser
|
||
|
ObjPath(e_ParserAcceptRelativeNamespace);
|
||
|
|
||
|
if((ObjPath.NoError != ObjPath.Parse(ObjectPath, &pParsedObjectPath)) ||
|
||
|
((0 != _wcsicmp(g_bstrClassMergeablePolicy, pParsedObjectPath->m_pClass)) &&
|
||
|
(0 != _wcsicmp(g_bstrClassSimplePolicy, 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;
|
||
|
|
||
|
// **** only grab ID key for now
|
||
|
|
||
|
for(x = 0; x < pParsedObjectPath->m_dwNumKeys; x++)
|
||
|
{
|
||
|
if(0 == _wcsicmp((*(pParsedObjectPath->m_paKeys + x))->m_pName, g_bstrID))
|
||
|
pvkeyID = &((*(pParsedObjectPath->m_paKeys + x))->m_vValue);
|
||
|
else if(0 == _wcsicmp((*(pParsedObjectPath->m_paKeys + x))->m_pName, g_bstrDomain))
|
||
|
pvDomain = &((*(pParsedObjectPath->m_paKeys + x))->m_vValue);
|
||
|
}
|
||
|
|
||
|
pADsContainer = m_pObject->GetADServices(pvDomain->bstrVal);
|
||
|
if(pADsContainer == NULL)
|
||
|
{
|
||
|
ERRORTRACE((LOG_ESS, "POLICMAN: Could not find domain: %S\n", V_BSTR(pvDomain)));;
|
||
|
hres = WBEM_E_ACCESS_DENIED;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// **** Get pointer to instance in AD
|
||
|
|
||
|
BSTR pADClassName;
|
||
|
if(0 == _wcsicmp(g_bstrClassMergeablePolicy, pParsedObjectPath->m_pClass))
|
||
|
pADClassName = g_bstrADClassMergeablePolicy;
|
||
|
else if(0 == _wcsicmp(g_bstrClassSimplePolicy, pParsedObjectPath->m_pClass))
|
||
|
pADClassName = g_bstrADClassSimplePolicy;
|
||
|
|
||
|
hres = pADsContainer->GetObject(NULL, 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))
|
||
|
{
|
||
|
hres = ADSIToWMIErrorCodes(hres);
|
||
|
ERRORTRACE((LOG_ESS, "POLICMAN: (IADsDeleteOps::DeleteObject) could not delete object\n"));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ObjPath.Free(pParsedObjectPath);
|
||
|
}
|
||
|
|
||
|
// **** Set Status
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
HRESULT GetADContainerInDomain(wchar_t *wcsDomain, wchar_t *wcsPath, IDirectorySearch **pObj);
|
||
|
|
||
|
STDMETHODIMP CPolicyTemplate::XProvider::ExecQueryAsync(
|
||
|
/* [in] */ const BSTR QueryLanguage,
|
||
|
/* [in] */ const BSTR Query,
|
||
|
/* [in] */ long lFlags,
|
||
|
/* [in] */ IWbemContext __RPC_FAR *pCtx,
|
||
|
/* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler)
|
||
|
{
|
||
|
DEBUGTRACE((LOG_ESS, "POLICMAN: [PolicyTemplate] IWbemServices::ExecQueryAsync(%S, %S, 0x%x, 0x%x, 0x%x)\n", QueryLanguage, Query, lFlags, pCtx, pResponseHandler));
|
||
|
|
||
|
HRESULT
|
||
|
hres = WBEM_E_FAILED;
|
||
|
|
||
|
CComPtr<IWbemServices>
|
||
|
pNameSpace = m_pObject->GetWMIServices();
|
||
|
|
||
|
QL_LEVEL_1_TOKEN
|
||
|
*pToken = NULL;
|
||
|
|
||
|
CComPtr<IDirectorySearch>
|
||
|
pDirectorySearch;
|
||
|
|
||
|
QString
|
||
|
LDAPQuery;
|
||
|
|
||
|
wchar_t
|
||
|
objPath[1024];
|
||
|
|
||
|
ADS_SEARCH_HANDLE
|
||
|
searchHandle;
|
||
|
|
||
|
ADS_SEARCH_COLUMN
|
||
|
searchColumn;
|
||
|
|
||
|
wchar_t
|
||
|
*pszDistName[] = { L"distinguishedName" };
|
||
|
|
||
|
// **** parse WQL expression
|
||
|
|
||
|
CTextLexSource
|
||
|
src(Query);
|
||
|
|
||
|
QL1_Parser
|
||
|
parser(&src);
|
||
|
|
||
|
QL_LEVEL_1_RPN_EXPRESSION
|
||
|
*pExp = NULL;
|
||
|
|
||
|
AutoDelete<QL_LEVEL_1_RPN_EXPRESSION>
|
||
|
AutoExp(&pExp);
|
||
|
|
||
|
int
|
||
|
nRes;
|
||
|
|
||
|
if(nRes = parser.Parse(&pExp))
|
||
|
return WBEM_E_INVALID_QUERY;
|
||
|
|
||
|
// **** find domain attribute
|
||
|
|
||
|
for(int iToken = 0; (iToken < pExp->nNumTokens) && (NULL == pToken); iToken++)
|
||
|
{
|
||
|
pToken = &pExp->pArrayOfTokens[iToken];
|
||
|
|
||
|
if(_wcsicmp(g_bstrDomain, pToken->PropertyName.GetStringAt(pToken->PropertyName.GetNumElements() - 1)))
|
||
|
pToken = NULL;
|
||
|
}
|
||
|
|
||
|
if(NULL == pToken)
|
||
|
{
|
||
|
if(pResponseHandler != NULL)
|
||
|
hres = pResponseHandler->SetStatus(0, WBEMESS_E_REGISTRATION_TOO_BROAD, 0, 0);
|
||
|
|
||
|
return WBEMESS_E_REGISTRATION_TOO_BROAD;
|
||
|
}
|
||
|
|
||
|
if((QL_LEVEL_1_TOKEN::OP_EXPRESSION != pToken->nTokenType) ||
|
||
|
(QL_LEVEL_1_TOKEN::OP_EQUAL != pToken->nOperator) ||
|
||
|
(TRUE == pToken->m_bPropComp) ||
|
||
|
(VT_BSTR != pToken->vConstValue.vt))
|
||
|
return WBEM_E_INVALID_QUERY;
|
||
|
|
||
|
// **** connect to LDAP location
|
||
|
|
||
|
hres = GetADContainerInDomain(pToken->vConstValue.bstrVal, TEMPLATE_RDN, &pDirectorySearch);
|
||
|
if(FAILED(hres) || (pDirectorySearch == NULL))
|
||
|
return WBEM_E_ACCESS_DENIED;
|
||
|
|
||
|
// **** build LDAP query to execute on container pADs
|
||
|
|
||
|
if(0 == _wcsicmp(g_bstrClassMergeablePolicy, pExp->bsClassName))
|
||
|
LDAPQuery << L"(|(objectCategory=msWMI-MergeablePolicyTemplate)(&(objectCategory=msWMI-SimplePolicyTemplate)(msWMI-NormalizedClass=msWMI-MergeablePolicyTemplate)))";
|
||
|
else
|
||
|
LDAPQuery << L"(&(objectCategory=msWMI-SimplePolicyTemplate)(|(msWMI-NormalizedClass=msWMI-SimplePolicyTemplate)(msWMI-NormalizedClass=MSFT_MergeablePolicyTemplate)))";
|
||
|
|
||
|
// **** set search preferences
|
||
|
|
||
|
ADS_SEARCHPREF_INFO
|
||
|
SearchPreferences[1];
|
||
|
|
||
|
SearchPreferences[0].dwSearchPref = ADS_SEARCHPREF_PAGESIZE;
|
||
|
SearchPreferences[0].vValue.dwType = ADSTYPE_INTEGER;
|
||
|
SearchPreferences[0].vValue.Integer = 1000;
|
||
|
|
||
|
hres = pDirectorySearch->SetSearchPreference(SearchPreferences, 1);
|
||
|
|
||
|
if(FAILED(hres))
|
||
|
{
|
||
|
ERRORTRACE((LOG_ESS, "POLICMAN: Could not set search preferences, returned error: 0x%08X\n", (LPWSTR)LDAPQuery, hres));
|
||
|
return WBEM_E_FAILED;
|
||
|
}
|
||
|
|
||
|
// **** execute query
|
||
|
|
||
|
hres = pDirectorySearch->ExecuteSearch(LDAPQuery, pszDistName, 1, &searchHandle);
|
||
|
|
||
|
if(FAILED(hres))
|
||
|
{
|
||
|
ERRORTRACE((LOG_ESS, "POLICMAN: Could execute query: (%s) returned error: 0x%08X\n", (LPWSTR)LDAPQuery, hres));
|
||
|
return WBEM_E_FAILED;
|
||
|
}
|
||
|
|
||
|
// **** build result list
|
||
|
|
||
|
try
|
||
|
{
|
||
|
while(SUCCEEDED(hres = pDirectorySearch->GetNextRow(searchHandle)) && (S_ADS_NOMORE_ROWS != hres))
|
||
|
{
|
||
|
CComPtr<IDirectoryObject>
|
||
|
pDirectoryObject;
|
||
|
|
||
|
CComPtr<IWbemClassObject>
|
||
|
pWbemClassObject;
|
||
|
|
||
|
// **** get path to object
|
||
|
|
||
|
hres = pDirectorySearch->GetColumn(searchHandle, pszDistName[0], &searchColumn);
|
||
|
if(FAILED(hres)) return ADSIToWMIErrorCodes(hres);
|
||
|
|
||
|
// **** get pointer to object
|
||
|
|
||
|
wcscpy(objPath, L"LDAP://");
|
||
|
wcscat(objPath, searchColumn.pADsValues->CaseIgnoreString);
|
||
|
pDirectorySearch->FreeColumn(&searchColumn);
|
||
|
|
||
|
|
||
|
hres = ADsGetObject(objPath, IID_IDirectoryObject, (void **)&pDirectoryObject);
|
||
|
if(FAILED(hres)) return ADSIToWMIErrorCodes(hres);
|
||
|
|
||
|
hres = Policy_ADToCIM(&pWbemClassObject, pDirectoryObject, pNameSpace);
|
||
|
if(FAILED(hres)) return ADSIToWMIErrorCodes(hres);
|
||
|
if(pWbemClassObject == NULL) return WBEM_E_FAILED;
|
||
|
|
||
|
hres = pResponseHandler->Indicate(1, &pWbemClassObject);
|
||
|
}
|
||
|
}
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
hres = pDirectorySearch->CloseSearchHandle(searchHandle);
|
||
|
|
||
|
if(pResponseHandler != NULL)
|
||
|
hres = pResponseHandler->SetStatus(0, hres, 0, 0);
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
//TODO: clean up bstrs & variants upon raising an exception (maybe theres a CVariantClearMe or some such?)
|
||
|
HRESULT CPolicyTemplate::XProvider::ResolveMergeable(IWbemClassObject* pResolveMe,
|
||
|
IWbemClassObject* pClassDef,
|
||
|
IWbemServices* pPolicyNamespace,
|
||
|
IWbemContext __RPC_FAR* pCtx,
|
||
|
IWbemClassObject __RPC_FAR* pOutParams,
|
||
|
IWbemObjectSink __RPC_FAR* pResponseHandler)
|
||
|
{
|
||
|
HRESULT hr = WBEM_E_FAILED;
|
||
|
DEBUGTRACE((LOG_ESS, "POLICMAN: CPolicyTemplate::ResolveMergeable\n"));
|
||
|
|
||
|
// instanciate instance of target class (pClassDef)
|
||
|
// loop through all range params & place each in out obj
|
||
|
|
||
|
CComVariant
|
||
|
vTable,
|
||
|
vGazinta;
|
||
|
|
||
|
CComPtr<IWbemClassObject>
|
||
|
pTargetInstance,
|
||
|
pRangeParamClass, // class object for range param & in & out params to RangeParam::Resolve
|
||
|
pResolveParamClass,
|
||
|
pResolveParamIn,
|
||
|
pResolveParamOut;
|
||
|
|
||
|
if (SUCCEEDED(hr = pClassDef->SpawnInstance(0, &pTargetInstance)) &&
|
||
|
|
||
|
// **** get MSFT_RangeParam::Resolve() input parameter object
|
||
|
|
||
|
SUCCEEDED(hr = pPolicyNamespace->GetObject(L"MSFT_RangeParam", 0, pCtx, &pRangeParamClass, NULL)) &&
|
||
|
SUCCEEDED(hr = pRangeParamClass->GetMethod(L"Resolve", 0, &pResolveParamClass, NULL)) &&
|
||
|
SUCCEEDED(hr = pResolveParamClass->SpawnInstance(0, &pResolveParamIn))
|
||
|
)
|
||
|
{
|
||
|
// **** set keys from object path
|
||
|
|
||
|
CComVariant
|
||
|
vTargetPath;
|
||
|
|
||
|
if(SUCCEEDED(hr = pResolveMe->Get(g_bstrTargetPath, 0, &vTargetPath, NULL, NULL)))
|
||
|
{
|
||
|
CObjectPathParser
|
||
|
ObjPath(e_ParserAcceptRelativeNamespace);
|
||
|
|
||
|
ParsedObjectPath
|
||
|
*pParsedObjectPath = NULL;
|
||
|
|
||
|
if(ObjPath.NoError != ObjPath.Parse(vTargetPath.bstrVal, &pParsedObjectPath))
|
||
|
{
|
||
|
ERRORTRACE((LOG_ESS, "POLICMAN: Parse error for object: %S\n", vTargetPath.bstrVal));
|
||
|
return WBEM_E_INVALID_OBJECT_PATH;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for(int x = 0; x < pParsedObjectPath->m_dwNumKeys; x++)
|
||
|
{
|
||
|
if((NULL != (*(pParsedObjectPath->m_paKeys + x))->m_pName) &&
|
||
|
((*(pParsedObjectPath->m_paKeys + x))->m_vValue.vt != VT_NULL))
|
||
|
{
|
||
|
CComVariant
|
||
|
vCurVal;
|
||
|
|
||
|
hr = pTargetInstance->Get((*(pParsedObjectPath->m_paKeys + x))->m_pName, 0, &vCurVal, NULL, NULL);
|
||
|
if(FAILED(hr))
|
||
|
{
|
||
|
if(WBEM_E_NOT_FOUND == hr)
|
||
|
ERRORTRACE((LOG_ESS, "POLICMAN: Policy key setting %S not in target object\n", (*(pParsedObjectPath->m_paKeys + x))->m_pName));
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
if(vCurVal.vt != VT_NULL)
|
||
|
{
|
||
|
ERRORTRACE((LOG_ESS, "POLICMAN: Attempt to set policy key setting %S more than once\n", (*(pParsedObjectPath->m_paKeys + x))->m_pName));
|
||
|
return WBEM_E_FAILED;
|
||
|
}
|
||
|
|
||
|
hr = pTargetInstance->Put((*(pParsedObjectPath->m_paKeys + x))->m_pName, 0,
|
||
|
&((*(pParsedObjectPath->m_paKeys + x))->m_vValue), NULL);
|
||
|
if(FAILED(hr)) return hr;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// get the array of settings we're setting
|
||
|
|
||
|
pResolveMe->Get(L"RangeSettings", 0, &vTable, NULL, NULL);
|
||
|
|
||
|
SafeArray<IUnknown*, VT_UNKNOWN>
|
||
|
settings(&vTable);
|
||
|
|
||
|
vGazinta = pTargetInstance;
|
||
|
|
||
|
for (int i = 0; i < settings.Size(); i++)
|
||
|
{
|
||
|
CComVariant
|
||
|
vSetting,
|
||
|
vName;
|
||
|
|
||
|
CComPtr<IWbemClassObject>
|
||
|
pResolveParamOut,
|
||
|
pRange;
|
||
|
|
||
|
// **** an in/out param in WMI winds up being copied from the in to the out
|
||
|
// **** so we need to put the new one in every time through the loop
|
||
|
|
||
|
vSetting = settings[i];
|
||
|
|
||
|
hr = pResolveParamIn->Put(L"obj", 0, &vGazinta, NULL);
|
||
|
if(FAILED(hr)) return hr;
|
||
|
|
||
|
hr = pResolveParamIn->Put(L"mergedRange", 0, &vSetting, NULL);
|
||
|
if(FAILED(hr)) return hr;
|
||
|
|
||
|
hr = vSetting.punkVal->QueryInterface(IID_IWbemClassObject, (void**)&pRange);
|
||
|
if(FAILED(hr)) return hr;
|
||
|
|
||
|
hr = pRange->Get(L"__CLASS", 0, &vName, NULL, NULL);
|
||
|
if(FAILED(hr)) return hr;
|
||
|
|
||
|
hr = pPolicyNamespace->ExecMethod(vName.bstrVal, L"Resolve", 0, pCtx, pResolveParamIn, &pResolveParamOut, NULL);
|
||
|
if(FAILED(hr)) return hr;
|
||
|
|
||
|
hr = pResolveParamOut->Get(L"obj",0, &vGazinta, NULL, NULL);
|
||
|
if(FAILED(hr)) return hr;
|
||
|
}
|
||
|
|
||
|
// <whew> at this point, our new, improved & merge-ified object is held inside the vGazinta variant
|
||
|
pOutParams->Put(L"obj", 0, &vGazinta, NULL);
|
||
|
hr = WBEM_S_NO_ERROR;
|
||
|
pResponseHandler->Indicate(1, &pOutParams);
|
||
|
}
|
||
|
else
|
||
|
ERRORTRACE((LOG_ESS, "POLICMAN: Failed to create target instance to resolve, 0x%08X\n", hr));
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// extract out class instance from PolicyTemplate in param
|
||
|
HRESULT CPolicyTemplate::XProvider::DoResolve(IWbemServices* pPolicyNamespace,
|
||
|
IWbemContext __RPC_FAR *pCtx,
|
||
|
IWbemClassObject __RPC_FAR *pInParams,
|
||
|
IWbemClassObject __RPC_FAR *pOutParams,
|
||
|
IWbemObjectSink __RPC_FAR *pResponseHandler)
|
||
|
{
|
||
|
HRESULT
|
||
|
hr = WBEM_E_FAILED;
|
||
|
|
||
|
DEBUGTRACE((LOG_ESS, "POLICMAN: CPolicyTemplate::DoResolve\n"));
|
||
|
|
||
|
CComVariant
|
||
|
vTemplate, vClass, vObj, vClassDef;
|
||
|
|
||
|
CComPtr<IWbemClassObject>
|
||
|
pResolveMe, pClassDef;
|
||
|
|
||
|
if(SUCCEEDED(hr = pInParams->Get(L"template", 0, &vTemplate, NULL, NULL)) &&
|
||
|
SUCCEEDED(hr = pInParams->Get(L"classObject", 0, &vClassDef, NULL, NULL)))
|
||
|
{
|
||
|
// **** the instance from which we'll pull our object
|
||
|
|
||
|
if(SUCCEEDED(hr = vTemplate.punkVal->QueryInterface(IID_IWbemClassObject, (void**)&pResolveMe)) &&
|
||
|
SUCCEEDED(hr = vClassDef.punkVal->QueryInterface(IID_IWbemClassObject, (void**)&pClassDef)))
|
||
|
{
|
||
|
// **** find out what, exactly we are.
|
||
|
// **** we're either a simple policy template, a mergeable policy template
|
||
|
// **** or we're derived from one of those.
|
||
|
|
||
|
pResolveMe->Get(L"__CLASS", 0, &vClass, NULL, NULL);
|
||
|
|
||
|
// **** simple case first
|
||
|
|
||
|
if((_wcsicmp(L"MSFT_SimplePolicyTemplate", vClass.bstrVal) == 0) ||
|
||
|
(pResolveMe->InheritsFrom(L"MSFT_SimplePolicyTemplate") == WBEM_S_NO_ERROR))
|
||
|
{
|
||
|
// **** this one's easy - what's in the input goes into the output
|
||
|
|
||
|
if (SUCCEEDED(hr = pResolveMe->Get(L"TargetObject", 0, &vObj, NULL, NULL)))
|
||
|
{
|
||
|
hr = pOutParams->Put(L"obj", 0, &vObj, NULL);
|
||
|
|
||
|
pResponseHandler->Indicate(1, &pOutParams);
|
||
|
}
|
||
|
}
|
||
|
else if((_wcsicmp(L"MSFT_MergeablePolicyTemplate", vClass.bstrVal) == 0) ||
|
||
|
(pResolveMe->InheritsFrom(L"MSFT_MergeablePolicyTemplate") == WBEM_S_NO_ERROR))
|
||
|
{
|
||
|
hr = ResolveMergeable(pResolveMe, pClassDef, pPolicyNamespace, pCtx, pOutParams, pResponseHandler);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ERRORTRACE((LOG_ESS, "POLICMAN: Invalid class passed to Resolve\n"));
|
||
|
|
||
|
hr = WBEM_E_INVALID_PARAMETER;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
DEBUGTRACE((LOG_ESS, "POLICMAN: CPolicyTemplate::DoResolve returning 0x%08X\n", hr));
|
||
|
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT CPolicyTemplate::XProvider::DoSet(IWbemClassObject* pInParams,
|
||
|
IWbemClassObject* pOutParams,
|
||
|
IWbemClassObject* pClass,
|
||
|
IWbemObjectSink* pResponseHandler,
|
||
|
IWbemServices* pPolicyNamespace)
|
||
|
{
|
||
|
HRESULT
|
||
|
hr = WBEM_S_NO_ERROR;
|
||
|
|
||
|
CComVariant
|
||
|
v;
|
||
|
|
||
|
CComPtr<IWbemClassObject>
|
||
|
pTemplate,
|
||
|
pObj;
|
||
|
|
||
|
if(SUCCEEDED(pInParams->Get(L"base",0,&v,NULL,NULL)) &&
|
||
|
(v.vt == VT_UNKNOWN) &&
|
||
|
(v.punkVal != NULL))
|
||
|
{
|
||
|
if (SUCCEEDED(hr = v.punkVal->QueryInterface(IID_IWbemClassObject, (void**)&pObj)))
|
||
|
{
|
||
|
if (SUCCEEDED(hr = pClass->SpawnInstance(0, &pTemplate)))
|
||
|
{
|
||
|
if (SUCCEEDED(pObj->Get(L"__CLASS", 0, &v, NULL, NULL)))
|
||
|
pTemplate->Put(L"TargetClass", 0, &v, NULL);
|
||
|
VariantClear(&v);
|
||
|
|
||
|
if (SUCCEEDED(pObj->Get(L"__NAMESPACE", 0, &v, NULL, NULL)))
|
||
|
pTemplate->Put(L"TargetNamespace", 0, &v, NULL);
|
||
|
VariantClear(&v);
|
||
|
|
||
|
if (SUCCEEDED(pObj->Get(L"__RELPATH", 0, &v, NULL, NULL)))
|
||
|
pTemplate->Put(L"TargetPath", 0, &v, NULL);
|
||
|
VariantClear(&v);
|
||
|
|
||
|
// loop through properties, any that are not NULL
|
||
|
// get set into the template object as range params
|
||
|
pObj->BeginEnumeration(WBEM_FLAG_NONSYSTEM_ONLY);
|
||
|
|
||
|
BSTR propName = NULL;
|
||
|
|
||
|
while (SUCCEEDED(hr = pObj->Next(0, &propName, &v, NULL, NULL)) && (hr != WBEM_S_NO_MORE_DATA))
|
||
|
{
|
||
|
CSysFreeMe freeProp(propName);
|
||
|
|
||
|
// TODO: tighten up error checking here!
|
||
|
if (v.vt != VT_NULL)
|
||
|
pObj->Put(propName, 0, &v, NULL);
|
||
|
|
||
|
VariantClear(&v);
|
||
|
}
|
||
|
|
||
|
pObj->EndEnumeration();
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
v = (IUnknown*)pTemplate;
|
||
|
|
||
|
if (SUCCEEDED(hr = pOutParams->Put(L"PolicyObj", 0, &v, NULL)))
|
||
|
pResponseHandler->Indicate(1, &pOutParams);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
VariantClear(&v);
|
||
|
|
||
|
}
|
||
|
else
|
||
|
hr = WBEM_E_INVALID_PARAMETER;
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// get safearray out of variant
|
||
|
// if safearray doesn't exist, create it & stuff it into the variant
|
||
|
// in either case, the array you get back is a pointer to the array in the variant
|
||
|
HRESULT CPolicyTemplate::XProvider::GetArray(VARIANT& vArray, SAFEARRAY*& pArray)
|
||
|
{
|
||
|
HRESULT hr = WBEM_S_NO_ERROR;
|
||
|
|
||
|
if ((vArray.vt == (VT_UNKNOWN | VT_ARRAY))
|
||
|
&&
|
||
|
(vArray.parray != NULL))
|
||
|
pArray = vArray.parray;
|
||
|
else
|
||
|
{
|
||
|
VariantClear(&vArray);
|
||
|
vArray.vt = (VT_UNKNOWN | VT_ARRAY);
|
||
|
|
||
|
SAFEARRAYBOUND bounds = {0,0};
|
||
|
vArray.parray = pArray = SafeArrayCreate(VT_UNKNOWN, 1, &bounds);
|
||
|
|
||
|
if (!pArray)
|
||
|
hr = WBEM_E_OUT_OF_MEMORY;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// walk through array - if param of same name exists, replace, else add
|
||
|
// assumptions: pRange is instance of a MSFT_RangeParam & pArray is an array of range params.
|
||
|
HRESULT CPolicyTemplate::XProvider::SetSettingInOurArray(const WCHAR* pName, IWbemClassObject* pRange, SAFEARRAY* pArray)
|
||
|
{
|
||
|
HRESULT hr = WBEM_S_NO_ERROR;
|
||
|
|
||
|
long bound;
|
||
|
SafeArrayGetUBound(pArray, 1, &bound);
|
||
|
|
||
|
// walk through array looking for our goodie
|
||
|
bool bFound = false;
|
||
|
for (long i = 0; (i < bound) && !bFound; i++)
|
||
|
{
|
||
|
// get pointer
|
||
|
IWbemClassObject* pOldRange = NULL;
|
||
|
SafeArrayGetElement(pArray, &i, &pOldRange);
|
||
|
CReleaseMe relOldRange(pOldRange);
|
||
|
|
||
|
// get name
|
||
|
VARIANT vName;
|
||
|
VariantInit(&vName);
|
||
|
pOldRange->Get(L"PropertyName", 0, &vName, NULL, NULL);
|
||
|
|
||
|
// compare name; if same: do game
|
||
|
if ((vName.bstrVal != NULL)
|
||
|
&&
|
||
|
(_wcsicmp(vName.bstrVal, pName) == 0))
|
||
|
{
|
||
|
hr = SafeArrayPutElement(pArray, &i, pRange);
|
||
|
bFound = true;
|
||
|
}
|
||
|
|
||
|
VariantClear(&vName);
|
||
|
}
|
||
|
|
||
|
// okay, wasn't there, grow the array & set it at end
|
||
|
if (!bFound)
|
||
|
{
|
||
|
SAFEARRAYBOUND b = {bound + 2, 0};
|
||
|
if (SUCCEEDED(hr = SafeArrayRedim(pArray, &b)))
|
||
|
{
|
||
|
bound++;
|
||
|
hr = SafeArrayPutElement(pArray, &bound, pRange);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// in the inparams there should be a rangeparam
|
||
|
// we'll walk through our array of range params, delete any that have the same name
|
||
|
// and stuff this new one in!
|
||
|
HRESULT CPolicyTemplate::XProvider::DoSetRange(IWbemClassObject* pInParams,
|
||
|
IWbemClassObject* pOutParams,
|
||
|
IWbemObjectSink* pResponseHandler)
|
||
|
{
|
||
|
HRESULT hr = WBEM_E_FAILED;
|
||
|
DEBUGTRACE((LOG_ESS, "POLICMAN: CPolicyTemplate::DoSetRange\n"));
|
||
|
|
||
|
IWbemClassObject* pRange = NULL;
|
||
|
IWbemClassObject* pThis = NULL;
|
||
|
|
||
|
VARIANT vRange;
|
||
|
VARIANT vThis;
|
||
|
|
||
|
VariantInit(&vRange);
|
||
|
VariantInit(&vThis);
|
||
|
|
||
|
if (SUCCEEDED(hr = pInParams->Get(L"rangeSetting", 0, &vRange, NULL, NULL))
|
||
|
&&
|
||
|
(vRange.vt == VT_UNKNOWN)
|
||
|
&&
|
||
|
(vRange.punkVal != NULL)
|
||
|
&&
|
||
|
SUCCEEDED(hr = pInParams->Get(L"PolicyObj", 0, &vThis, NULL, NULL))
|
||
|
&&
|
||
|
(vThis.vt == VT_UNKNOWN)
|
||
|
&&
|
||
|
(vThis.punkVal != NULL)
|
||
|
)
|
||
|
{
|
||
|
if (SUCCEEDED(hr = vThis.punkVal->QueryInterface(IID_IWbemClassObject, (void**)&pThis)))
|
||
|
{
|
||
|
CReleaseMe relThis(pThis);
|
||
|
|
||
|
hr = vRange.punkVal->QueryInterface(IID_IWbemClassObject, (void**)&pRange);
|
||
|
CReleaseMe relRange(pRange);
|
||
|
|
||
|
VARIANT vName;
|
||
|
VariantInit(&vName);
|
||
|
|
||
|
if (SUCCEEDED(pRange->Get(L"PropertyName", 0, &vName, NULL, NULL))
|
||
|
&&
|
||
|
(vName.vt == VT_BSTR)
|
||
|
&&
|
||
|
(vName.bstrVal != NULL)
|
||
|
&&
|
||
|
(wcslen(vName.bstrVal) != 0)
|
||
|
)
|
||
|
{
|
||
|
VARIANT vArray;
|
||
|
VariantInit(&vArray);
|
||
|
|
||
|
SAFEARRAY* pArray = NULL;
|
||
|
|
||
|
// get current state of range settings
|
||
|
if (SUCCEEDED(hr = pThis->Get(L"RangeSettings", 0, &vArray, NULL, NULL))
|
||
|
&&
|
||
|
SUCCEEDED(hr = GetArray(vArray, pArray)))
|
||
|
{
|
||
|
// walk through pArray
|
||
|
if (SUCCEEDED(hr = SetSettingInOurArray(vName.bstrVal, pRange, pArray)))
|
||
|
{
|
||
|
hr = pThis->Put(L"RangeSettings", 0, &vArray, NULL);
|
||
|
hr = pOutParams->Put(L"PolicyObj", 0, &vThis, NULL);
|
||
|
|
||
|
pResponseHandler->Indicate(1, &pOutParams);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
VariantClear(&vArray);
|
||
|
VariantClear(&vName);
|
||
|
}
|
||
|
else
|
||
|
hr = WBEM_E_INVALID_PARAMETER;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
DEBUGTRACE((LOG_ESS, "POLICMAN: failed to retrieve input parameters 0x%08X\n", hr));
|
||
|
hr = WBEM_E_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
VariantClear(&vThis);
|
||
|
VariantClear(&vRange);
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
HRESULT CPolicyTemplate::XProvider::DoMerge(IWbemServices* pNamespace,
|
||
|
const BSTR strObjectPath,
|
||
|
IWbemContext __RPC_FAR *pCtx,
|
||
|
IWbemClassObject __RPC_FAR *pInParams,
|
||
|
IWbemClassObject __RPC_FAR *pOutParams,
|
||
|
IWbemObjectSink __RPC_FAR *pResponseHandler)
|
||
|
{
|
||
|
HRESULT
|
||
|
hres = WBEM_E_FAILED;
|
||
|
|
||
|
CComPtr<IUnknown>
|
||
|
pUnk;
|
||
|
|
||
|
CComPtr<IWbemClassObject>
|
||
|
pOutResult;
|
||
|
|
||
|
ParsedObjectPath
|
||
|
*pParsedObjectPath = NULL;
|
||
|
|
||
|
CComVariant
|
||
|
v1;
|
||
|
|
||
|
// **** parse object path
|
||
|
|
||
|
CObjectPathParser
|
||
|
ObjPath(e_ParserAcceptRelativeNamespace);
|
||
|
|
||
|
if((ObjPath.NoError != ObjPath.Parse(strObjectPath, &pParsedObjectPath)) ||
|
||
|
(0 != _wcsicmp(pParsedObjectPath->m_pClass, g_bstrClassMergeablePolicy)))
|
||
|
{
|
||
|
ERRORTRACE((LOG_ESS, "POLICMAN: Parse error for object: %S\n", strObjectPath));
|
||
|
hres = WBEM_E_INVALID_QUERY;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// **** get input array
|
||
|
|
||
|
hres = pInParams->Get(L"templateList", 0, &v1, NULL, NULL);
|
||
|
if(FAILED(hres)) return hres;
|
||
|
|
||
|
// **** perform merge
|
||
|
|
||
|
SafeArray<IUnknown*, VT_UNKNOWN>
|
||
|
InputArray(&v1);
|
||
|
|
||
|
hres = Policy_Merge(InputArray, pOutResult, pNamespace);
|
||
|
if(FAILED(hres)) return hres;
|
||
|
if(pOutResult == NULL) return WBEM_E_FAILED;
|
||
|
|
||
|
// **** insert output of merge
|
||
|
|
||
|
hres = pOutResult->QueryInterface(IID_IUnknown, (void **)&pUnk);
|
||
|
if(FAILED(hres)) return hres;
|
||
|
|
||
|
v1 = pUnk;
|
||
|
hres = pOutParams->Put(L"mergedTemplate", 0, &v1, 0);
|
||
|
if(FAILED(hres)) return hres;
|
||
|
|
||
|
// **** put status in return value
|
||
|
|
||
|
v1 = hres;
|
||
|
hres = pOutParams->Put(L"ReturnValue", 0, &v1, 0);
|
||
|
|
||
|
// **** send output back to client
|
||
|
|
||
|
hres = pResponseHandler->Indicate(1, &pOutParams);
|
||
|
if(FAILED(hres)) return hres;
|
||
|
}
|
||
|
|
||
|
ObjPath.Free(pParsedObjectPath);
|
||
|
|
||
|
return hres;
|
||
|
};
|
||
|
|
||
|
STDMETHODIMP CPolicyTemplate::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
|
||
|
hres = WBEM_S_NO_ERROR,
|
||
|
hres2 = WBEM_S_NO_ERROR;
|
||
|
|
||
|
IWbemServices* pNamespace = m_pObject->GetWMIServices();
|
||
|
CReleaseMe RelpNamespace(pNamespace);
|
||
|
|
||
|
// **** impersonate client
|
||
|
hres = CoImpersonateClient();
|
||
|
if(FAILED(hres))
|
||
|
{
|
||
|
ERRORTRACE((LOG_ESS, "POLICMAN: (CoImpersonateClient) could not assume client permissions, 0x%08X\n", hres));
|
||
|
hres = WBEM_S_ACCESS_DENIED;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if((NULL == strObjectPath) ||
|
||
|
(NULL == strMethodName) ||
|
||
|
(NULL == pInParams) ||
|
||
|
(NULL == pResponseHandler))
|
||
|
{
|
||
|
ERRORTRACE((LOG_ESS, "POLICMAN: object handle and/or return status objects are NULL\n"));
|
||
|
hres = WBEM_E_INVALID_PARAMETER;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
// **** get policy template class definition
|
||
|
IWbemClassObject* pClass = NULL;
|
||
|
hres = pNamespace->GetObject(g_bstrClassMergeablePolicy, 0, pCtx, &pClass, NULL);
|
||
|
if(FAILED(hres)) return WBEM_E_NOT_FOUND;
|
||
|
CReleaseMe relClass(pClass);
|
||
|
|
||
|
// **** get output object
|
||
|
IWbemClassObject* pOutClass = NULL;
|
||
|
IWbemClassObject* pOutParamsObj = NULL;
|
||
|
|
||
|
CReleaseMe relOutClass(pOutClass);
|
||
|
CReleaseMe relOutObj(pOutParamsObj);
|
||
|
|
||
|
hres = pClass->GetMethod(strMethodName, 0, NULL, &pOutClass);
|
||
|
if(FAILED(hres)) return hres;
|
||
|
|
||
|
hres = pOutClass->SpawnInstance(0, &pOutParamsObj);
|
||
|
if(FAILED(hres)) return hres;
|
||
|
|
||
|
// figure out which method we're here to service
|
||
|
if (_wcsicmp(strMethodName, L"Merge") == 0)
|
||
|
hres = DoMerge(pNamespace, strObjectPath, pCtx, pInParams, pOutParamsObj, pResponseHandler);
|
||
|
else if (_wcsicmp(strMethodName, L"SetRange") == 0)
|
||
|
hres = DoSetRange(pInParams, pOutParamsObj, pResponseHandler);
|
||
|
else if (_wcsicmp(strMethodName, L"Set") == 0)
|
||
|
hres = DoSet(pInParams, pOutParamsObj, pClass, pResponseHandler, pNamespace);
|
||
|
else if (_wcsicmp(strMethodName, L"Resolve") == 0)
|
||
|
hres = DoResolve(pNamespace, pCtx, pInParams, pOutParamsObj, pResponseHandler);
|
||
|
else
|
||
|
hres = WBEM_E_INVALID_PARAMETER;
|
||
|
|
||
|
}
|
||
|
catch(long hret)
|
||
|
{
|
||
|
ERRORTRACE((LOG_ESS, "POLICMAN: caught exception with HRESULT 0x%08X\n", hret));
|
||
|
hres = hret;
|
||
|
}
|
||
|
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;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|