#include "PolicRange.h" #include #include #include #include #include #include "genlex.h" #include "objpath.h" #include "utility.h" /******************************\ **** POLICY PROVIDER HELPERS *** \******************************/ // returns addref'd pointer back to m_pWMIMgmt IWbemServices* CPolicyRange::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* CPolicyRange::GetADServices(void) { CInCritSec lock(&m_CS); IADsContainer *pADContainer = NULL; HRESULT hres; wchar_t *pADPath = NULL; if(NULL == pADPath) { if(NULL != m_pADMgmt) { m_pADMgmt->AddRef(); pADContainer = m_pADMgmt; } } else { wchar_t szDSPath[MAX_PATH]; // wcscpy(szDSPath,L"LDAP://"); // wcscat(szDSPath, pADPath); hres = ADsGetObject(pADPath, IID_IADsContainer, (void**) &pADContainer); if (FAILED(hres)) ERRORTRACE((LOG_ESS, "POLICMAN: failed 0x%08X\n", hres)); } return pADContainer; } // returns false if services pointer has already been set bool CPolicyRange::SetWMIServices(IWbemServices* pServices) { CInCritSec lock(&m_CS); bool bOldOneNull; if (bOldOneNull = (m_pWMIMgmt == NULL)) { m_pWMIMgmt = pServices; pServices->AddRef(); } return bOldOneNull; } // returns false if services pointer has already been set bool CPolicyRange::SetADServices(IADsContainer* pServices) { CInCritSec lock(&m_CS); bool bOldOneNull; if (bOldOneNull = (m_pADMgmt == NULL)) { m_pADMgmt = pServices; if(pServices) pServices->AddRef(); } return bOldOneNull; } CPolicyRange::~CPolicyRange() { // **** WMI services object if (NULL != m_pWMIMgmt) { m_pWMIMgmt->Release(); m_pWMIMgmt= NULL; } // **** AD services object if (NULL != m_pADMgmt) { m_pADMgmt->Release(); m_pADMgmt= NULL; } }; void* CPolicyRange::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* CPolicyRange::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* CPolicyRange::XProvider::GetPolicyTemplateInstance() { IWbemClassObject* pObj = NULL; IWbemClassObject* pClass = NULL; if (pClass = GetPolicyTemplateClass()) { CReleaseMe releaseClass(pClass); pClass->SpawnInstance(0, &pObj); } return pObj; } CPolicyRange::XProvider::~XProvider() { // I fixed it! - HMH ;-) // CInCritSec lock(&m_pObject->m_CS); if(NULL != m_pWMIPolicyClassObject) { m_pWMIPolicyClassObject->Release(); m_pWMIPolicyClassObject = NULL; } } /*************************\ *** IWbemProviderInit *** \*************************/ STDMETHODIMP CPolicyRange::XInit::Initialize( LPWSTR, LONG, LPWSTR, LPWSTR, IWbemServices* pServices, IWbemContext* pCtxt, IWbemProviderInitSink* pSink) { CComPtr pRootDSE; CComPtr pObject; HRESULT hres = WBEM_S_NO_ERROR, hres2 = WBEM_S_NO_ERROR; CComVariant v1; wchar_t szDSPath[MAX_PATH]; // **** 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",&v1); if(FAILED(hres)) { ERRORTRACE((LOG_ESS, "POLICMAN: (IADs::Get) could not get defaultNamingContext, 0x%08X\n", hres)); hres = WBEM_E_NOT_FOUND; } else { wcscpy(szDSPath,L"LDAP://CN=PolicyTemplate,CN=WMIPolicy,CN=System,"); wcscat(szDSPath, V_BSTR(&v1)); hres = ADsGetObject(szDSPath, IID_IADsContainer, (void**) &pObject); if (FAILED(hres)) { ERRORTRACE((LOG_ESS, "POLICMAN: (ADsGetObject) could not get AD object: %S, 0x%08X\n", szDSPath, hres)); hres = WBEM_E_NOT_FOUND; } m_pObject->SetADServices(pObject); } } } 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 *** \*******************/ //TODO: clean up bstrs & variants upon raising an exception (maybe theres a CVariantClearMe or some such?) HRESULT CPolicyRange::XProvider::DoResolve(IWbemServices* pPolicyNamespace, 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 pUnk; ParsedObjectPath *pParsedObjectPath = NULL; CComPtr pTargetPolicyObj, pMergedParam; CComVariant vRetVal, vMergedRange, vObj, vMergedParamValue, vMergedParamName, vTargetValue; long nIndex = -1; wchar_t *pswIndexStart = NULL; // **** parse object path CObjectPathParser ObjPath(e_ParserAcceptRelativeNamespace); if(ObjPath.NoError != ObjPath.Parse(strObjectPath, &pParsedObjectPath)) { ERRORTRACE((LOG_ESS, "POLICMAN: Parse error for object: %S\n", strObjectPath)); hres = WBEM_E_INVALID_QUERY; } else { // **** get input param obj hres = pInParams->Get(L"mergedRange", 0, &vMergedRange, NULL, NULL); if(FAILED(hres)) return hres; hres = V_UNKNOWN(&vMergedRange)->QueryInterface(IID_IWbemClassObject, (void **)&pMergedParam); if(FAILED(hres)) return hres; // **** get target policy object hres = pInParams->Get(L"obj", 0, &vObj, NULL, NULL); if(FAILED(hres)) return hres; hres = V_UNKNOWN(&vObj)->QueryInterface(IID_IWbemClassObject, (void **)&pTargetPolicyObj); if(FAILED(hres)) return hres; // **** get name for attribute in target policy object named in param obj hres = pMergedParam->Get(L"PropertyName", 0, &vMergedParamName, NULL, NULL); if(FAILED(hres)) return hres; // **** parse name to see if it is part of an array if(pswIndexStart = wcsstr(V_BSTR(&vMergedParamName), L"[")) { *pswIndexStart = L'\0'; nIndex = wcstol(pswIndexStart + 1, NULL, 10); } // **** check to see if vParamAttrName is an attribute in target object hres = pTargetPolicyObj->Get(V_BSTR(&vMergedParamName), 0, &vTargetValue, NULL, NULL); if(FAILED(hres)) { if(WBEM_E_NOT_FOUND == hres) { ERRORTRACE((LOG_ESS, "POLICMAN: Policy range setting %S not in target object\n", vMergedParamName.bstrVal)); } else return hres; } else { // **** get default value from param obj hres = pMergedParam->Get(L"Default", 0, &vMergedParamValue, NULL, NULL); if(FAILED(hres)) return hres; // **** set value if(nIndex < 0) { // **** check to see if attribute is already set if(vTargetValue.vt != VT_NULL) { ERRORTRACE((LOG_ESS, "POLICMAN: Attempt to set policy range setting %S more than once\n", vMergedParamName.bstrVal)); } else { hres = pTargetPolicyObj->Put(V_BSTR(&vMergedParamName), 0, &vMergedParamValue, 0); if(FAILED(hres)) { ERRORTRACE((LOG_ESS, "POLICMAN: Attempting to place attribute %S in target instance generated error 0x%x\n", vMergedParamName.bstrVal, hres)); return hres; } } } else { if((vTargetValue.vt & VT_ARRAY) || (vTargetValue.vt == VT_NULL)) { CComVariant vNewArray; // **** signed and unsigned integers if((vMergedParamValue.vt & VT_I4)) { SafeArray arrayMember(&vTargetValue); if(arrayMember.IndexMax() < nIndex) { arrayMember.ReDim(0, nIndex + 1); } arrayMember[nIndex] = vMergedParamValue.lVal; V_VT(&vNewArray) = (VT_ARRAY | VT_I4); V_ARRAY(&vNewArray) = arrayMember.Data(); } // **** real numbers else if((vMergedParamValue.vt & VT_R8)) { SafeArray arrayMember(&vTargetValue); if(arrayMember.IndexMax() < nIndex) { arrayMember.ReDim(0, nIndex + 1); } arrayMember[nIndex] = vMergedParamValue.dblVal; V_VT(&vNewArray) = (VT_ARRAY | VT_R8); V_ARRAY(&vNewArray) = arrayMember.Data(); } // **** strings else if((vMergedParamValue.vt & VT_BSTR)) { SafeArray arrayMember(&vTargetValue); if(arrayMember.IndexMax() < nIndex) { arrayMember.ReDim(0, nIndex + 1); } else if(NULL != arrayMember[nIndex]) { SysFreeString(arrayMember[nIndex]); } arrayMember[nIndex] = SysAllocString(vMergedParamValue.bstrVal); V_VT(&vNewArray) = (VT_ARRAY | VT_BSTR); V_ARRAY(&vNewArray) = arrayMember.Data(); } hres = pTargetPolicyObj->Put(V_BSTR(&vMergedParamName), 0, &vNewArray, 0); if(FAILED(hres)) return hres; } else return WBEM_E_TYPE_MISMATCH; } } // **** put target policy obj in output param obj hres = pTargetPolicyObj->QueryInterface(IID_IUnknown, (void **)&pUnk); if(FAILED(hres)) return hres; vObj = pUnk; hres = pOutParams->Put(L"obj", 0, &vObj, 0); if(FAILED(hres)) return hres; // **** put status in return value vRetVal = hres; hres = pOutParams->Put(L"ReturnValue", 0, &vRetVal, 0); if(FAILED(hres)) return hres; // **** send output back to client hres = pResponseHandler->Indicate(1, &pOutParams); if(FAILED(hres)) return hres; } ObjPath.Free(pParsedObjectPath); return hres; } HRESULT CPolicyRange::XProvider::DoSet() { HRESULT hr = WBEM_E_FAILED; return hr; } HRESULT CPolicyRange::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 pUnk; ParsedObjectPath *pParsedObjectPath = NULL; CComPtr pMergedParam; CComVariant v1; // **** parse object path CObjectPathParser ObjPath(e_ParserAcceptRelativeNamespace); if(ObjPath.NoError != ObjPath.Parse(strObjectPath, &pParsedObjectPath)) { ERRORTRACE((LOG_ESS, "POLICMAN: Parse error for object: %S\n", strObjectPath)); hres = WBEM_E_INVALID_QUERY; } else { int firstElement = -1, conflictObj = -1; CComPtr pArrayElement; CComVariant vRangeParamType; // **** get input array hres = pInParams->Get(L"ranges", 0, &v1, NULL, NULL); if(FAILED(hres)) return hres; SafeArray InputArray(&v1); firstElement = -1; while((++firstElement < InputArray.Size()) && (NULL == InputArray[firstElement])); if(firstElement >= InputArray.Size()) return WBEM_E_INVALID_PARAMETER; // **** get actual type of range parameter objects hres = InputArray[firstElement]->QueryInterface(IID_IWbemClassObject, (void **)&pArrayElement); if(FAILED(hres)) return hres; hres = pArrayElement->Get(L"__CLASS", 0, &vRangeParamType, NULL, NULL); if(FAILED(hres)) return hres; // **** perform merge if(-1 == conflictObj) { if(_wcsicmp(vRangeParamType.bstrVal, L"MSFT_SintRangeParam") == 0) hres = Range_Sint32_Merge(InputArray, pMergedParam, conflictObj); else if(_wcsicmp(vRangeParamType.bstrVal, L"MSFT_UintRangeParam") == 0) hres = Range_Uint32_Merge(InputArray, pMergedParam, conflictObj); else if(_wcsicmp(vRangeParamType.bstrVal, L"MSFT_RealRangeParam") == 0) hres = Range_Real_Merge(InputArray, pMergedParam, conflictObj); else if(_wcsicmp(vRangeParamType.bstrVal, L"MSFT_SintSetParam") == 0) hres = Set_Sint32_Merge(InputArray, pMergedParam, conflictObj); else if(_wcsicmp(vRangeParamType.bstrVal, L"MSFT_UintSetParam") == 0) hres = Set_Uint32_Merge(InputArray, pMergedParam, conflictObj); else if(_wcsicmp(vRangeParamType.bstrVal, L"MSFT_StringSetParam") == 0) hres = Set_String_Merge(InputArray, pMergedParam, conflictObj); else return WBEM_E_INVALID_PARAMETER; } // **** put merged range in output param obj if(NULL != pMergedParam.p) { hres = pMergedParam->QueryInterface(IID_IUnknown, (void **)&pUnk); if(FAILED(hres)) return hres; v1 = pUnk; hres = pOutParams->Put(L"mergedRange", 0, &v1, 0); if(FAILED(hres)) return hres; } // **** put put which policy object caused conflict v1 = conflictObj; hres = pOutParams->Put(L"conflict", 0, &v1, 0); if(FAILED(hres)) return hres; // **** put status in return value v1 = hres; hres = pOutParams->Put(L"ReturnValue", 0, &v1, 0); if(FAILED(hres)) return hres; // **** send output back to client hres = pResponseHandler->Indicate(1, &pOutParams); if(FAILED(hres)) return hres; } ObjPath.Free(pParsedObjectPath); return WBEM_S_NO_ERROR; } STDMETHODIMP CPolicyRange::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; 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_bstrClassRangeParam, 0, pCtx, &pClass, NULL); if(FAILED(hres)) return hres; 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"Resolve") == 0) hres = DoResolve(pNamespace, strObjectPath, 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; } } pResponseHandler->SetStatus(0, hres, NULL, NULL); hres = CoRevertToSelf(); } return hres; }