Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1222 lines
34 KiB

  1. #include <unk.h>
  2. #include <wbemcli.h>
  3. #include <wbemprov.h>
  4. #include <atlbase.h>
  5. #include <sync.h>
  6. #include <activeds.h>
  7. #include <genlex.h>
  8. #include <objpath.h>
  9. #include <Utility.h>
  10. #include <ql.h>
  11. #include "PolicSOM.h"
  12. #ifdef TIME_TRIALS
  13. #include <StopWatch.h>
  14. #pragma message("!! Including time trial code !!")
  15. StopWatch EvaluateTimer(L"Somfilter Evaluation", L"C:\\Som.Evaluate.log");
  16. #endif
  17. /******************************\
  18. **** POLICY PROVIDER HELPERS ***
  19. \******************************/
  20. #define SOM_RDN L"CN=SOM,CN=WMIPolicy,CN=System"
  21. // returns addref'd pointer back to WinMgmt
  22. IWbemServices* CPolicySOM::GetWMIServices()
  23. {
  24. CInCritSec lock(&m_CS);
  25. if (m_pWMIMgmt)
  26. m_pWMIMgmt->AddRef();
  27. return m_pWMIMgmt;
  28. }
  29. // returns addref'd pointer back to m_pADMgmt
  30. IADsContainer *CPolicySOM::GetADServices(wchar_t *pDomain, HRESULT &hres)
  31. {
  32. CInCritSec lock(&m_CS);
  33. IADsContainer *pADsContainer = NULL;
  34. QString
  35. SomDN(SOM_RDN),
  36. DistDomainName,
  37. ObjPath(L"LDAP://");
  38. if(NULL == pDomain)
  39. {
  40. // **** if this is the 1st time through, get name of domain controller
  41. if(VT_BSTR != m_vDsLocalContext.vt)
  42. {
  43. CComPtr<IADs>
  44. pRootDSE;
  45. // **** get pointer to AD policy template table
  46. hres = ADsGetObject(L"LDAP://rootDSE", IID_IADs, (void**)&pRootDSE);
  47. if(FAILED(hres))
  48. {
  49. ERRORTRACE((LOG_ESS, "POLICMAN: (ADsGetObject) could not get object: LDAP://rootDSE, 0x%08X\n", hres));
  50. return NULL;
  51. }
  52. else
  53. {
  54. hres = pRootDSE->Get(L"defaultNamingContext",&m_vDsLocalContext);
  55. if(FAILED(hres))
  56. {
  57. ERRORTRACE((LOG_ESS, "POLICMAN: (IADs::Get) could not get defaultNamingContext, 0x%08X\n", hres));
  58. return NULL;
  59. }
  60. }
  61. }
  62. DistDomainName = m_vDsLocalContext.bstrVal;
  63. }
  64. else
  65. hres = DistNameFromDomainName(QString(pDomain), DistDomainName);
  66. ObjPath << SOM_RDN << L"," << DistDomainName;
  67. hres = ADsGetObject(ObjPath, IID_IADsContainer, (void**) &pADsContainer);
  68. if(NULL == pADsContainer)
  69. pADsContainer = CreateContainers(DistDomainName, SomDN);
  70. return pADsContainer;
  71. }
  72. // returns false if services pointer has already been set
  73. bool CPolicySOM::SetWMIServices(IWbemServices* pServices)
  74. {
  75. CInCritSec lock(&m_CS);
  76. bool bOldOneNull = FALSE;
  77. if (bOldOneNull = (m_pWMIMgmt == NULL))
  78. {
  79. m_pWMIMgmt = pServices;
  80. if(pServices) pServices->AddRef();
  81. }
  82. return bOldOneNull;
  83. }
  84. // returns false if services pointer has already been set
  85. bool CPolicySOM::SetADServices(IADsContainer* pServices, unsigned context)
  86. {
  87. CInCritSec lock(&m_CS);
  88. bool
  89. bOldOneNull = TRUE;
  90. switch(context)
  91. {
  92. case AD_LOCAL_CONTEXT :
  93. case AD_GLOBAL_CONTEXT :
  94. m_pADMgmt[context] = pServices;
  95. pServices->AddRef();
  96. bOldOneNull = (m_pADMgmt[context] == NULL);
  97. break;
  98. default : ;
  99. }
  100. return bOldOneNull;
  101. }
  102. CPolicySOM::~CPolicySOM()
  103. {
  104. // WMI services object
  105. if (m_pWMIMgmt)
  106. {
  107. m_pWMIMgmt->Release();
  108. m_pWMIMgmt= NULL;
  109. }
  110. // AD services object
  111. if (NULL != m_pADMgmt)
  112. {
  113. for(int i = 0; i < AD_MAX_CONTEXT; i++)
  114. {
  115. if(NULL != m_pADMgmt[i])
  116. {
  117. m_pADMgmt[i]->Release();
  118. m_pADMgmt[i] = NULL;
  119. }
  120. }
  121. }
  122. };
  123. void* CPolicySOM::GetInterface(REFIID riid)
  124. {
  125. if(riid == IID_IWbemServices)
  126. return &m_XProvider;
  127. else if(riid == IID_IWbemProviderInit)
  128. return &m_XInit;
  129. else return NULL;
  130. }
  131. /*********************************\
  132. *** Som Specific Implementation ***
  133. \*********************************/
  134. // returns addref'd pointer to class object
  135. IWbemClassObject* CPolicySOM::XProvider::GetSomClass()
  136. {
  137. CInCritSec lock(&m_pObject->m_CS);
  138. if (m_pSOMClassObject == NULL)
  139. {
  140. IWbemServices* pWinMgmt = NULL;
  141. if (pWinMgmt = m_pObject->GetWMIServices())
  142. {
  143. CReleaseMe relMgmt(pWinMgmt);
  144. pWinMgmt->GetObject(g_bstrClassSom, WBEM_FLAG_RETURN_WBEM_COMPLETE, NULL, &m_pSOMClassObject, NULL);
  145. }
  146. }
  147. if (m_pSOMClassObject)
  148. m_pSOMClassObject->AddRef();
  149. return m_pSOMClassObject;
  150. }
  151. // returns addref'd pointer to emply class instance
  152. IWbemClassObject* CPolicySOM::XProvider::GetSomInstance()
  153. {
  154. IWbemClassObject* pObj = NULL;
  155. IWbemClassObject* pClass = NULL;
  156. if (pClass = GetSomClass())
  157. {
  158. CReleaseMe releaseClass(pClass);
  159. pClass->SpawnInstance(0, &pObj);
  160. }
  161. return pObj;
  162. }
  163. CPolicySOM::XProvider::~XProvider()
  164. {
  165. if (m_pSOMClassObject)
  166. {
  167. m_pSOMClassObject->Release();
  168. m_pSOMClassObject= NULL;
  169. }
  170. if (m_pLocator)
  171. {
  172. m_pLocator->Release();
  173. m_pLocator = NULL;
  174. }
  175. }
  176. HRESULT CPolicySOM::XProvider::GetLocator(IWbemLocator*& pLocator)
  177. {
  178. HRESULT hr = WBEM_S_NO_ERROR;
  179. CInCritSec lock(&m_pObject->m_CS);
  180. if (!m_pLocator)
  181. hr = CoCreateInstance(CLSID_WbemAdministrativeLocator, NULL, CLSCTX_ALL, IID_IWbemLocator, (void**)&m_pLocator);
  182. if (m_pLocator)
  183. {
  184. m_pLocator->AddRef();
  185. pLocator = m_pLocator;
  186. }
  187. return hr;
  188. }
  189. // get namespace denoted by namespaceName
  190. // will release pNamespace if non-null on way in
  191. HRESULT CPolicySOM::XProvider::GetNewNamespace(BSTR namespaceName, IWbemServices*& pNamespace)
  192. {
  193. HRESULT hr = WBEM_E_FAILED;
  194. if (pNamespace)
  195. {
  196. pNamespace->Release();
  197. pNamespace = NULL;
  198. }
  199. IWbemLocator* pLocator = NULL;
  200. if (SUCCEEDED(hr = GetLocator(pLocator)))
  201. {
  202. CReleaseMe relLocator(pLocator);
  203. hr = pLocator->ConnectServer(namespaceName, NULL, NULL, NULL, 0, NULL, NULL, &pNamespace);
  204. }
  205. return hr;
  206. }
  207. // evaulate a single rule
  208. // pNamespace & namespaceName may be NULL on entry
  209. // may be different upon exit
  210. // this is a rudimentary caching mechanism,
  211. // assuming that most of the namespaces in the rules will be the same.
  212. HRESULT CPolicySOM::XProvider::EvaluateRule(IWbemServices*& pNamespace, BSTR& namespaceName, IWbemClassObject* pRule, bool& bResult)
  213. {
  214. VARIANT v;
  215. VariantInit(&v);
  216. // assume failure
  217. HRESULT hr = WBEM_E_FAILED;
  218. bResult = false;
  219. // check to see if we're still on the same namespace
  220. if (FAILED(hr = pRule->Get(L"TargetNamespace", 0, &v, NULL, NULL)))
  221. bResult = false;
  222. else
  223. {
  224. if ((pNamespace == NULL) || (_wcsicmp(namespaceName, v.bstrVal) != 0))
  225. if (SUCCEEDED(hr = GetNewNamespace(v.bstrVal, pNamespace)))
  226. {
  227. // keep copy of name
  228. if (namespaceName)
  229. {
  230. if (!SysReAllocString(&namespaceName, v.bstrVal))
  231. hr = WBEM_E_OUT_OF_MEMORY;
  232. }
  233. else
  234. if (NULL == (namespaceName = SysAllocString(v.bstrVal)))
  235. hr = WBEM_E_OUT_OF_MEMORY;
  236. }
  237. VariantClear(&v);
  238. }
  239. // if we're still on track...
  240. if (SUCCEEDED(hr) && SUCCEEDED(hr = pRule->Get(L"Query", 0, &v, NULL, NULL)))
  241. {
  242. #ifdef TIME_TRIALS
  243. EvaluateTimer.Start(StopWatch::AtomicTimer);
  244. #endif
  245. IEnumWbemClassObject *pEnumerator = NULL;
  246. if (SUCCEEDED(hr = pNamespace->ExecQuery(L"WQL", v.bstrVal, WBEM_FLAG_FORWARD_ONLY, NULL, &pEnumerator)))
  247. {
  248. #ifdef TIME_TRIALS
  249. EvaluateTimer.Start(StopWatch::ProviderTimer);
  250. #endif
  251. ULONG uReturned = 0;
  252. IWbemClassObject* pWhoCares = NULL;
  253. if (SUCCEEDED(hr = pEnumerator->Next(WBEM_INFINITE, 1, &pWhoCares, &uReturned)) && uReturned > 0)
  254. {
  255. // we don't care at all about the result set
  256. // just whether there is anything *in* the result set
  257. bResult = true;
  258. pWhoCares->Release();
  259. }
  260. pEnumerator->Release();
  261. }
  262. #ifdef TIME_TRIALS
  263. else
  264. EvaluateTimer.Start(StopWatch::ProviderTimer);
  265. #endif
  266. VariantClear(&v);
  267. }
  268. // s_false returned when no objects are returned from 'next'
  269. // THIS function has successfully determined that the query failed.
  270. if (hr == WBEM_S_FALSE)
  271. hr = WBEM_S_NO_ERROR;
  272. return hr;
  273. }
  274. // loop through all rules
  275. // grab namespace & try each query
  276. // TODO: Optimize by caching namespace pointers.
  277. HRESULT CPolicySOM::XProvider::Evaluate(IWbemClassObject* pObj, IWbemClassObject* pOutInstance)
  278. {
  279. HRESULT hr = WBEM_S_NO_ERROR;
  280. HRESULT hrEval = WBEM_S_NO_ERROR;
  281. // innocent until proven guilty
  282. bool bResult = true;
  283. VARIANT v;
  284. VariantInit(&v);
  285. if (SUCCEEDED(hr = pObj->Get(L"Rules", 0, &v, NULL, NULL)))
  286. {
  287. SafeArray<IUnknown*, VT_UNKNOWN> rules(&v);
  288. long nRules = rules.Size();
  289. // first run optimization: we'll hold onto each namespace as it comes in
  290. // in hopes that the NEXT one will be in the same namespace
  291. // in practice - it probably will be
  292. IWbemServices* pNamespace = NULL;
  293. BSTR namespaceName = NULL;
  294. // with each rule:
  295. // get namespace name
  296. // if different than the one we're currently playing with
  297. // get namespace
  298. // issue query
  299. // count results
  300. for(UINT i = 0; (i < nRules) && bResult && SUCCEEDED(hrEval); i++)
  301. {
  302. if (rules[i])
  303. {
  304. IWbemClassObject* pRule = NULL;
  305. if (SUCCEEDED(rules[i]->QueryInterface(IID_IWbemClassObject, (void**)&pRule)))
  306. {
  307. hrEval = EvaluateRule(pNamespace, namespaceName, pRule, bResult);
  308. pRule->Release();
  309. pRule = NULL;
  310. }
  311. else
  312. {
  313. bResult = FALSE;
  314. hrEval = hr = WBEM_E_INVALID_PARAMETER;
  315. }
  316. }
  317. }
  318. // clean up after yourself
  319. VariantClear(&v);
  320. if (pNamespace)
  321. pNamespace->Release();
  322. if (namespaceName)
  323. SysFreeString(namespaceName);
  324. }
  325. // we done - tell somebody about it!
  326. if (SUCCEEDED(hr))
  327. {
  328. HRESULT hrDebug;
  329. VARIANT v;
  330. VariantInit(&v);
  331. v.vt = VT_I4;
  332. if (SUCCEEDED(hrEval))
  333. v.lVal = bResult ? S_OK : S_FALSE;
  334. else
  335. v.lVal = hrEval;
  336. hrDebug = pOutInstance->Put(L"ReturnValue", 0, &v, NULL);
  337. }
  338. return hr;
  339. }
  340. // loop through each of the references in input obj
  341. // call evaluate for each,
  342. // TODO: Optimize w/ ExecMethodASYNC
  343. HRESULT CPolicySOM::XProvider::BatchEvaluate(IWbemClassObject* pObj, IWbemClassObject* pOutInstance, IWbemServices* pPolicyNamespace)
  344. {
  345. HRESULT hr = WBEM_S_NO_ERROR;
  346. if (pObj == NULL)
  347. return WBEM_E_INVALID_PARAMETER;
  348. VARIANT vFilters;
  349. VariantInit(&vFilters);
  350. BSTR methodName = SysAllocString(L"Evaluate");
  351. CSysFreeMe freeEvil(methodName);
  352. SAFEARRAY* pResults = NULL;
  353. if (SUCCEEDED(hr = pObj->Get(L"filters", 0, &vFilters, NULL, NULL)))
  354. {
  355. if ((vFilters.parray == NULL) ||
  356. (vFilters.parray->cDims != 1) ||
  357. (vFilters.parray->rgsabound[0].cElements == 0))
  358. hr = WBEM_E_INVALID_PARAMETER;
  359. else
  360. {
  361. long index, lUbound = 0;
  362. SafeArrayGetUBound(vFilters.parray, 1, &lUbound);
  363. SAFEARRAYBOUND bounds = {lUbound +1, 0};
  364. pResults = SafeArrayCreate(VT_I4, 1, &bounds);
  365. if (!pResults)
  366. return WBEM_E_OUT_OF_MEMORY;
  367. for (index = 0; (index <= lUbound) && SUCCEEDED(hr); index++)
  368. {
  369. BSTR path = NULL;
  370. if (SUCCEEDED(hr = SafeArrayGetElement(vFilters.parray, &index, &path)))
  371. {
  372. IWbemClassObject* pGazotta = NULL;
  373. if (SUCCEEDED(hr = pPolicyNamespace->ExecMethod(path, methodName, 0, NULL, NULL, &pGazotta, NULL)))
  374. {
  375. CReleaseMe relGazotta(pGazotta);
  376. VARIANT v;
  377. VariantInit(&v);
  378. hr = pGazotta->Get(L"ReturnValue", 0, &v, NULL, NULL);
  379. hr = SafeArrayPutElement(pResults, &index, &v.lVal);
  380. }
  381. }
  382. SysFreeString(path);
  383. }
  384. }
  385. }
  386. if (SUCCEEDED(hr))
  387. {
  388. VARIANT v;
  389. VariantInit(&v);
  390. v.vt = VT_I4 | VT_ARRAY;
  391. v.parray = pResults;
  392. hr = pOutInstance->Put(L"Results", 0, &v, NULL);
  393. // no clear - array is deleted separately.
  394. VariantInit(&v);
  395. v.vt = VT_I4;
  396. v.lVal = hr;
  397. hr = pOutInstance->Put(L"ReturnValue", 0, &v, NULL);
  398. }
  399. if (pResults)
  400. SafeArrayDestroy(pResults);
  401. VariantClear(&vFilters);
  402. return hr;
  403. }
  404. /*************************\
  405. *** IWbemProviderInit ***
  406. \*************************/
  407. STDMETHODIMP CPolicySOM::XInit::Initialize(
  408. LPWSTR, LONG, LPWSTR, LPWSTR, IWbemServices* pServices, IWbemContext* pCtxt,
  409. IWbemProviderInitSink* pSink)
  410. {
  411. HRESULT
  412. hres = WBEM_S_NO_ERROR,
  413. hres2 = WBEM_S_NO_ERROR;
  414. // **** impersonate client for security
  415. hres = CoImpersonateClient();
  416. if(FAILED(hres))
  417. {
  418. ERRORTRACE((LOG_ESS, "POLICMAN: (CoImpersonateClient) could not assume client permissions, 0x%08X\n", hres));
  419. return WBEM_S_ACCESS_DENIED;
  420. }
  421. else
  422. {
  423. // **** save WMI name space pointer
  424. m_pObject->SetWMIServices(pServices);
  425. }
  426. hres2 = pSink->SetStatus(hres, 0);
  427. if(FAILED(hres2))
  428. {
  429. ERRORTRACE((LOG_ESS, "POLICMAN: could not set return status\n"));
  430. if(SUCCEEDED(hres)) hres = hres2;
  431. }
  432. return hres;
  433. }
  434. /*******************\
  435. *** IWbemServices ***
  436. \*******************/
  437. STDMETHODIMP CPolicySOM::XProvider::GetObjectAsync(
  438. /* [in] */ const BSTR ObjectPath,
  439. /* [in] */ long lFlags,
  440. /* [in] */ IWbemContext __RPC_FAR *pCtx,
  441. /* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler)
  442. {
  443. HRESULT
  444. hres = WBEM_S_NO_ERROR,
  445. hres2 = WBEM_S_NO_ERROR;
  446. CComPtr<IWbemServices>
  447. pNamespace;
  448. CComPtr<IADsContainer>
  449. pADsContainer;
  450. CComPtr<IDispatch>
  451. pDisp;
  452. CComPtr<IWbemClassObject>
  453. pObj;
  454. CComPtr<IDirectoryObject>
  455. pDirObj;
  456. VARIANT
  457. *pvkeyID = NULL,
  458. *pvDomain = NULL;
  459. // **** impersonate client for security
  460. hres = CoImpersonateClient();
  461. if (FAILED(hres))
  462. {
  463. ERRORTRACE((LOG_ESS, "POLICMAN: (CoImpersonateClient) could not assume callers permissions, 0x%08X\n",hres));
  464. hres = WBEM_E_ACCESS_DENIED;
  465. }
  466. else
  467. {
  468. // **** Check arguments
  469. if(ObjectPath == NULL || pResponseHandler == NULL)
  470. {
  471. ERRORTRACE((LOG_ESS, "POLICMAN: object path and/or return object are NULL\n"));
  472. hres = WBEM_E_INVALID_PARAMETER;
  473. }
  474. else
  475. {
  476. // **** parse object path
  477. CObjectPathParser
  478. ObjPath(e_ParserAcceptRelativeNamespace);
  479. ParsedObjectPath
  480. *pParsedObjectPath = NULL;
  481. if((ObjPath.NoError != ObjPath.Parse(ObjectPath, &pParsedObjectPath)) ||
  482. (0 != _wcsicmp(g_bstrClassSom, pParsedObjectPath->m_pClass)) ||
  483. (2 != pParsedObjectPath->m_dwNumKeys))
  484. {
  485. ERRORTRACE((LOG_ESS, "POLICMAN: Parse error for object: %S\n", ObjectPath));
  486. hres = WBEM_E_INVALID_QUERY;
  487. }
  488. else
  489. {
  490. int x;
  491. for(x = 0; x < pParsedObjectPath->m_dwNumKeys; x++)
  492. {
  493. if(0 == _wcsicmp((*(pParsedObjectPath->m_paKeys + x))->m_pName, g_bstrDomain))
  494. pvDomain = &((*(pParsedObjectPath->m_paKeys + x))->m_vValue);
  495. else if(0 == _wcsicmp((*(pParsedObjectPath->m_paKeys + x))->m_pName, g_bstrID))
  496. pvkeyID = &((*(pParsedObjectPath->m_paKeys + x))->m_vValue);
  497. }
  498. pNamespace.Attach(m_pObject->GetWMIServices());
  499. pADsContainer.Attach(m_pObject->GetADServices(pvDomain->bstrVal, hres));
  500. if((FAILED(hres)) || (pNamespace == NULL) || (pADsContainer == NULL))
  501. {
  502. ERRORTRACE((LOG_ESS, "POLICMAN: WMI and/or AD services not initialized\n"));
  503. hres = ADSIToWMIErrorCodes(hres);
  504. }
  505. else
  506. {
  507. try
  508. {
  509. // **** Get pointer to instance in AD
  510. hres = pADsContainer->GetObject(g_bstrADClassSom, QString(L"CN=") << V_BSTR(pvkeyID), &pDisp);
  511. if(FAILED(hres))
  512. hres = ADSIToWMIErrorCodes(hres);
  513. else
  514. {
  515. hres = pDisp->QueryInterface(IID_IDirectoryObject, (void **)&pDirObj);
  516. if(SUCCEEDED(hres))
  517. {
  518. // **** Get the instance and send it back
  519. hres = Som_ADToCIM(&pObj, pDirObj, pNamespace);
  520. if(FAILED(hres)) hres = ADSIToWMIErrorCodes(hres);
  521. if(pObj == NULL) hres = WBEM_E_FAILED;
  522. // **** Set object
  523. pResponseHandler->Indicate(1, &pObj);
  524. }
  525. }
  526. }
  527. catch(long hret)
  528. {
  529. hres = ADSIToWMIErrorCodes(hret);
  530. ERRORTRACE((LOG_ESS, "POLICMAN: Translation of Policy object from AD to WMI generated HRESULT 0x%08X\n", hres));
  531. }
  532. catch(wchar_t *swErrString)
  533. {
  534. ERRORTRACE((LOG_ESS, "POLICMAN: Caught Exception: %S\n", swErrString));
  535. hres = WBEM_E_FAILED;
  536. }
  537. catch(...)
  538. {
  539. ERRORTRACE((LOG_ESS, "POLICMAN: Caught UNKNOWN Exception\n"));
  540. hres = WBEM_E_FAILED;
  541. }
  542. }
  543. }
  544. ObjPath.Free(pParsedObjectPath);
  545. hres2 = pResponseHandler->SetStatus(0,hres, NULL, NULL);
  546. if(FAILED(hres2))
  547. {
  548. ERRORTRACE((LOG_ESS, "POLICMAN: could not set return status\n"));
  549. if(SUCCEEDED(hres)) hres = hres2;
  550. }
  551. }
  552. CoRevertToSelf();
  553. }
  554. return hres;
  555. }
  556. STDMETHODIMP CPolicySOM::XProvider::CreateInstanceEnumAsync(
  557. /* [in] */ const BSTR Class,
  558. /* [in] */ long lFlags,
  559. /* [in] */ IWbemContext __RPC_FAR *pCtx,
  560. /* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler)
  561. {
  562. return WBEM_E_NOT_SUPPORTED;
  563. }
  564. // validate that the rules contained in pInst are proper syntax
  565. // if they are not, an error object is created & an error returned
  566. HRESULT CPolicySOM::XProvider::ValidateRules(IWbemClassObject* pInst, IWbemClassObject*& pErrorObject)
  567. {
  568. // init the toys we'll be playing with
  569. HRESULT hr = WBEM_S_NO_ERROR;
  570. bool bBadQuery = false;
  571. VARIANT vRules;
  572. VariantInit(&vRules);
  573. SAFEARRAY* pResults = NULL;
  574. if (FAILED(pInst->Get(L"Rules", 0, &vRules, NULL, NULL))
  575. || (vRules.vt != (VT_UNKNOWN | VT_ARRAY)))
  576. hr = WBEM_E_INVALID_PARAMETER;
  577. else
  578. {
  579. // good to go, we'll create the array to keep logic simple
  580. long index, lUbound = 0;
  581. SafeArrayGetUBound(vRules.parray, 1, &lUbound);
  582. SAFEARRAYBOUND bounds = {lUbound +1, 0};
  583. pResults = SafeArrayCreate(VT_I4, 1, &bounds);
  584. if (!pResults)
  585. hr = WBEM_E_OUT_OF_MEMORY;
  586. else
  587. for (index = 0; (index <= lUbound) && SUCCEEDED(hr); index++)
  588. {
  589. // get the MSFT_Rule out of the MSFT_SomFilter
  590. IWbemClassObject* pRule = NULL;
  591. if (SUCCEEDED(hr = SafeArrayGetElement(vRules.parray, &index, &pRule)))
  592. {
  593. HRESULT hrParse = 0;
  594. VARIANT vQueryLanguage;
  595. VariantInit(&vQueryLanguage);
  596. if (SUCCEEDED(hr = pRule->Get(L"QueryLanguage", 0, &vQueryLanguage, NULL, NULL))
  597. && (vQueryLanguage.vt == VT_BSTR) && (vQueryLanguage.bstrVal != NULL))
  598. {
  599. if (0 != _wcsicmp(vQueryLanguage.bstrVal, L"WQL"))
  600. {
  601. hrParse = WBEM_E_INVALID_QUERY_TYPE;
  602. bBadQuery = true;
  603. }
  604. else
  605. {
  606. VARIANT vQuery;
  607. VariantInit(&vQuery);
  608. // get the query out of the MSFT_Rule.
  609. if (SUCCEEDED(hr = pRule->Get(L"Query", 0, &vQuery, NULL, NULL))
  610. && (vQuery.vt == VT_BSTR) && (vQuery.bstrVal != NULL))
  611. {
  612. CTextLexSource src(vQuery.bstrVal);
  613. QL1_Parser parser(&src);
  614. QL_LEVEL_1_RPN_EXPRESSION *pExp = NULL;
  615. // if it parses, we good, else we bad.
  616. if(parser.Parse(&pExp))
  617. {
  618. hrParse = WBEM_E_INVALID_QUERY;
  619. bBadQuery = true;
  620. }
  621. if (pExp)
  622. delete pExp;
  623. }
  624. else
  625. hrParse = WBEM_E_INVALID_PARAMETER;
  626. VariantClear(&vQuery);
  627. }
  628. }
  629. else
  630. hrParse = WBEM_E_INVALID_PARAMETER;
  631. SafeArrayPutElement(pResults, &index, (void*)&hrParse);
  632. pRule->Release();
  633. VariantClear(&vQueryLanguage);
  634. }
  635. }
  636. }
  637. // if we found a bad query, we create an error object to hold the info
  638. if (bBadQuery)
  639. {
  640. IWbemServices* pSvc = m_pObject->GetWMIServices();
  641. IWbemClassObject* pErrorClass = NULL;
  642. BSTR name = SysAllocString(L"SomFilterPutStatus");
  643. if (pSvc &&
  644. name &&
  645. SUCCEEDED(hr = pSvc->GetObject(name, 0, NULL, &pErrorClass, NULL)) &&
  646. SUCCEEDED(hr = pErrorClass->SpawnInstance(0, &pErrorObject)))
  647. {
  648. hr = WBEM_E_INVALID_PARAMETER;
  649. HRESULT hrDebug;
  650. // variant to hold array - don't clear it, the array is destroyed elsewhere
  651. VARIANT vResultArray;
  652. VariantInit(&vResultArray);
  653. vResultArray.vt = VT_I4 | VT_ARRAY;
  654. vResultArray.parray = pResults;
  655. hrDebug = pErrorObject->Put(L"RuleValidationResults", 0, &vResultArray, NULL);
  656. // other interesting error vals.
  657. VARIANT vTemp;
  658. vTemp.vt = VT_BSTR;
  659. vTemp.bstrVal = SysAllocString(L"PutInstance");
  660. hrDebug = pErrorObject->Put(L"Operation",0,&vTemp,NULL);
  661. SysFreeString(vTemp.bstrVal);
  662. vTemp.bstrVal = SysAllocString(L"PolicSOM");
  663. hrDebug = pErrorObject->Put(L"ProviderName",0,&vTemp,NULL);
  664. SysFreeString(vTemp.bstrVal);
  665. vTemp.vt = VT_I4;
  666. vTemp.lVal = WBEM_E_INVALID_QUERY;
  667. hrDebug = pErrorObject->Put(L"StatusCode",0,&vTemp,NULL);
  668. //BSTR debuggy = NULL;
  669. //pErrorObject->GetObjectText(0, &debuggy);
  670. }
  671. if (pSvc)
  672. pSvc->Release();
  673. if (name)
  674. SysFreeString(name);
  675. if (pErrorClass)
  676. pErrorClass->Release();
  677. }
  678. // cleanup
  679. VariantClear(&vRules);
  680. if (pResults)
  681. SafeArrayDestroy(pResults);
  682. return hr;
  683. }
  684. STDMETHODIMP CPolicySOM::XProvider::PutInstanceAsync(
  685. /* [in] */ IWbemClassObject __RPC_FAR *pInst,
  686. /* [in] */ long lFlags,
  687. /* [in] */ IWbemContext __RPC_FAR *pCtx,
  688. /* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler)
  689. {
  690. HRESULT
  691. hres = WBEM_S_NO_ERROR,
  692. hres2 = WBEM_S_NO_ERROR;
  693. CComPtr<IADsContainer>
  694. pADsContainer;
  695. CComPtr<IDirectoryObject>
  696. pDirObj;
  697. CComVariant
  698. v1, vRelPath;
  699. ADsStruct<ADS_OBJECT_INFO>
  700. pInfo;
  701. // **** impersonate client
  702. hres = CoImpersonateClient();
  703. if(FAILED(hres))
  704. {
  705. ERRORTRACE((LOG_ESS, "POLICMAN: (CoImpersonateClient) could not assume callers permissions, 0x%08X\n",hres));
  706. hres = WBEM_E_ACCESS_DENIED;
  707. }
  708. else
  709. {
  710. // **** check arguments
  711. if((NULL == pInst) || (NULL == pResponseHandler))
  712. {
  713. ERRORTRACE((LOG_ESS, "POLICMAN: (CoImpersonateClient) could not assume callers permissions, 0x%08X\n",hres));
  714. hres = WBEM_E_ACCESS_DENIED;
  715. }
  716. else
  717. {
  718. IWbemClassObject* pErrorObject = NULL;
  719. if SUCCEEDED(hres = ValidateRules(pInst, pErrorObject))
  720. {
  721. // **** put policy obj into AD
  722. try
  723. {
  724. EnsureID(pInst, NULL);
  725. // **** aquire AD path in which to place object
  726. hres = pInst->Get(g_bstrDomain, 0, &v1, NULL, NULL);
  727. if(FAILED(hres)) return hres;
  728. if(VT_BSTR == v1.vt)
  729. pADsContainer.Attach(m_pObject->GetADServices(v1.bstrVal, hres));
  730. else
  731. pADsContainer.Attach(m_pObject->GetADServices(NULL, hres));
  732. if((FAILED(hres)) || (pADsContainer == NULL))
  733. {
  734. ERRORTRACE((LOG_ESS, "POLICMAN: Could not find or connect to domain: %S\n", V_BSTR(&v1)));
  735. return ADSIToWMIErrorCodes(hres);
  736. }
  737. hres = pADsContainer->QueryInterface(IID_IDirectoryObject, (void **)&pDirObj);
  738. if(FAILED(hres)) return ADSIToWMIErrorCodes(hres);
  739. // **** copy policy obj into AD
  740. hres = Som_CIMToAD(pInst, pDirObj, lFlags);
  741. if(FAILED(hres))
  742. {
  743. if(0x800700a == hres)
  744. ERRORTRACE((LOG_ESS, "POLICMAN: Active Directory Schema for MSFT_SomFilter is invalid/missing\n"));
  745. return ADSIToWMIErrorCodes(hres);
  746. }
  747. }
  748. catch(long hret)
  749. {
  750. hres = ADSIToWMIErrorCodes(hret);
  751. ERRORTRACE((LOG_ESS, "POLICMAN: Translation of Policy object from WMI to AD generated HRESULT 0x%08X\n", hres));
  752. }
  753. catch(wchar_t *swErrString)
  754. {
  755. ERRORTRACE((LOG_ESS, "POLICMAN: Caught Exception: %S\n", swErrString));
  756. hres = WBEM_E_FAILED;
  757. }
  758. catch(...)
  759. {
  760. ERRORTRACE((LOG_ESS, "POLICMAN: Caught unknown Exception\n"));
  761. hres = WBEM_E_FAILED;
  762. }
  763. }
  764. if(FAILED(hres) && pErrorObject)
  765. {
  766. if(FAILED(pResponseHandler->SetStatus(0,hres, NULL, pErrorObject)))
  767. ERRORTRACE((LOG_ESS, "POLICMAN: could not set return status\n"));
  768. }
  769. else
  770. {
  771. // **** indicate return status
  772. pInst->Get(L"__RELPATH", 0, &vRelPath, NULL, NULL);
  773. if(FAILED(pResponseHandler->SetStatus(0,hres, vRelPath.bstrVal, NULL)))
  774. ERRORTRACE((LOG_ESS, "POLICMAN: could not set return status\n"));
  775. }
  776. if (pErrorObject)
  777. pErrorObject->Release();
  778. }
  779. CoRevertToSelf();
  780. }
  781. return hres;
  782. }
  783. STDMETHODIMP CPolicySOM::XProvider::DeleteInstanceAsync(
  784. /* [in] */ const BSTR ObjectPath,
  785. /* [in] */ long lFlags,
  786. /* [in] */ IWbemContext __RPC_FAR *pCtx,
  787. /* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler)
  788. {
  789. HRESULT
  790. hres = WBEM_S_NO_ERROR,
  791. hres2 = WBEM_S_NO_ERROR;
  792. CComPtr<IADsContainer>
  793. pADsContainer;
  794. CComPtr<IDispatch>
  795. pDisp;
  796. CComPtr<IADsDeleteOps>
  797. pDelObj;
  798. VARIANT
  799. *pvDomain = NULL,
  800. *pvkeyID = NULL;
  801. ParsedObjectPath
  802. *pParsedObjectPath = NULL;
  803. // **** impersonate client
  804. hres = CoImpersonateClient();
  805. if(FAILED(hres))
  806. {
  807. ERRORTRACE((LOG_ESS, "POLICMAN: (CoImpersonateClient) could not assume callers permissions, 0x%08X\n",hres));
  808. hres = WBEM_E_ACCESS_DENIED;
  809. }
  810. else
  811. {
  812. // **** Check arguments
  813. if(ObjectPath == NULL || pResponseHandler == NULL)
  814. {
  815. ERRORTRACE((LOG_ESS, "POLICMAN: object handle and/or return status object are NULL\n"));
  816. hres = WBEM_E_INVALID_PARAMETER;
  817. }
  818. else
  819. {
  820. // **** parse object path
  821. CObjectPathParser
  822. ObjPath(e_ParserAcceptRelativeNamespace);
  823. if((ObjPath.NoError != ObjPath.Parse(ObjectPath, &pParsedObjectPath)) ||
  824. (0 != _wcsicmp(g_bstrClassSom, pParsedObjectPath->m_pClass)) ||
  825. (2 != pParsedObjectPath->m_dwNumKeys))
  826. {
  827. ERRORTRACE((LOG_ESS, "POLICMAN: Parse error for object: %S\n", ObjectPath));
  828. hres = WBEM_E_INVALID_QUERY;
  829. }
  830. else
  831. {
  832. int x;
  833. for(x = 0; x < pParsedObjectPath->m_dwNumKeys; x++)
  834. {
  835. if(0 == _wcsicmp((*(pParsedObjectPath->m_paKeys + x))->m_pName, g_bstrDomain))
  836. pvDomain = &((*(pParsedObjectPath->m_paKeys + x))->m_vValue);
  837. else if(0 == _wcsicmp((*(pParsedObjectPath->m_paKeys + x))->m_pName, g_bstrID))
  838. pvkeyID = &((*(pParsedObjectPath->m_paKeys + x))->m_vValue);
  839. }
  840. pADsContainer.Attach(m_pObject->GetADServices(pvDomain->bstrVal, hres));
  841. if((FAILED(hres)) || (pADsContainer == NULL))
  842. {
  843. ERRORTRACE((LOG_ESS, "POLICMAN: Could not find domain: %S\n", V_BSTR(pvDomain)));
  844. hres = ADSIToWMIErrorCodes(hres);
  845. }
  846. else
  847. {
  848. // **** get pointer to instance in AD
  849. hres = pADsContainer->GetObject(g_bstrADClassSom, QString(L"CN=") << V_BSTR(pvkeyID), &pDisp);
  850. if(FAILED(hres))
  851. {
  852. hres = ADSIToWMIErrorCodes(hres);
  853. ERRORTRACE((LOG_ESS, "POLICMAN: (IADsContainer::GetObject) could not get object in AD %S, 0x%08X\n", V_BSTR(pvkeyID), hres));
  854. }
  855. else
  856. {
  857. hres = pDisp->QueryInterface(IID_IADsDeleteOps, (void **)&pDelObj);
  858. if(FAILED(hres))
  859. {
  860. ERRORTRACE((LOG_ESS, "POLICMAN: (IDispatch::QueryInterface) could not get IID_IADsDeleteOps interface on object\n"));
  861. }
  862. else
  863. {
  864. // **** delete the instance and all its children in AD
  865. hres = pDelObj->DeleteObject(0);
  866. if(FAILED(hres))
  867. {
  868. ERRORTRACE((LOG_ESS, "POLICMAN: (IADsDeleteOps::DeleteObject) could not delete object (0x%08X)\n", hres));
  869. hres = WBEM_E_ACCESS_DENIED;
  870. }
  871. }
  872. }
  873. }
  874. }
  875. ObjPath.Free(pParsedObjectPath);
  876. hres2 = pResponseHandler->SetStatus(0,hres, NULL, NULL);
  877. if(FAILED(hres2))
  878. {
  879. ERRORTRACE((LOG_ESS, "POLICMAN: could not set return status\n"));
  880. if(SUCCEEDED(hres)) hres = hres2;
  881. }
  882. }
  883. CoRevertToSelf();
  884. }
  885. return hres;
  886. }
  887. STDMETHODIMP CPolicySOM::XProvider::ExecQueryAsync(
  888. /* [in] */ const BSTR QueryLanguage,
  889. /* [in] */ const BSTR Query,
  890. /* [in] */ long lFlags,
  891. /* [in] */ IWbemContext __RPC_FAR *pCtx,
  892. /* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler)
  893. {
  894. HRESULT
  895. hres = WBEM_E_FAILED;
  896. CComPtr<IWbemServices>
  897. pNameSpace;
  898. hres = CoImpersonateClient();
  899. if(FAILED(hres))
  900. {
  901. ERRORTRACE((LOG_ESS, "POLICMAN: (CoImpersonateClient) could not assume callers permissions, 0x%08X\n",hres));
  902. hres = WBEM_E_ACCESS_DENIED;
  903. }
  904. else
  905. {
  906. pNameSpace.Attach(m_pObject->GetWMIServices());
  907. hres = ExecuteWQLQuery(SOM_RDN,
  908. Query,
  909. pResponseHandler,
  910. pNameSpace,
  911. g_bstrADClassSom,
  912. Som_ADToCIM);
  913. if(pResponseHandler != NULL)
  914. pResponseHandler->SetStatus(0, hres, 0, 0);
  915. }
  916. CoRevertToSelf();
  917. return hres;
  918. }
  919. STDMETHODIMP CPolicySOM::XProvider::ExecMethodAsync(
  920. /* [in] */ const BSTR strObjectPath,
  921. /* [in] */ const BSTR strMethodName,
  922. /* [in] */ long lFlags,
  923. /* [in] */ IWbemContext __RPC_FAR *pCtx,
  924. /* [in] */ IWbemClassObject __RPC_FAR *pInParams,
  925. /* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler)
  926. {
  927. HRESULT hr = WBEM_E_FAILED;
  928. #ifdef TIME_TRIALS
  929. EvaluateTimer.Start(StopWatch::ProviderTimer);
  930. #endif
  931. enum WhichMethod {Eval, BatchEval};
  932. WhichMethod whichMethod;
  933. // check for valid method name
  934. if (_wcsicmp(strMethodName, L"Evaluate") == 0)
  935. whichMethod = Eval;
  936. else if (_wcsicmp(strMethodName, L"BatchEvaluate") == 0)
  937. whichMethod = BatchEval;
  938. else
  939. return WBEM_E_INVALID_METHOD;
  940. // **** impersonate client for security
  941. hr = CoImpersonateClient();
  942. if (FAILED(hr))
  943. return hr;
  944. // retrieve target object
  945. CComPtr<IWbemServices>
  946. pService;
  947. pService.Attach(m_pObject->GetWMIServices());
  948. if (pService == NULL)
  949. hr = WBEM_E_FAILED;
  950. else
  951. {
  952. IWbemClassObject* pObj = NULL;
  953. #ifdef TIME_TRIALS
  954. EvaluateTimer.Start(StopWatch::WinMgmtTimer);
  955. #endif
  956. if (SUCCEEDED(hr = pService->GetObject(strObjectPath, WBEM_FLAG_RETURN_WBEM_COMPLETE, pCtx, &pObj, NULL)))
  957. {
  958. #ifdef TIME_TRIALS
  959. EvaluateTimer.Start(StopWatch::ProviderTimer);
  960. #endif
  961. CReleaseMe releaseObj(pObj);
  962. // retreive class & output param object
  963. IWbemClassObject* pOurClass;
  964. if (NULL == (pOurClass = GetSomClass()))
  965. hr = WBEM_E_FAILED;
  966. else
  967. {
  968. CReleaseMe releaseClass(pOurClass);
  969. IWbemClassObject* pOutClass = NULL;
  970. if (SUCCEEDED(hr = pOurClass->GetMethod(strMethodName, 0, NULL, &pOutClass)))
  971. {
  972. CReleaseMe releaseOut(pOutClass);
  973. IWbemClassObject* pOutInstance = NULL;
  974. if (SUCCEEDED(pOutClass->SpawnInstance(0, &pOutInstance)))
  975. {
  976. CReleaseMe releaseInnerOut(pOutInstance);
  977. if (whichMethod == Eval)
  978. hr = Evaluate(pObj, pOutInstance);
  979. else if (whichMethod == BatchEval)
  980. hr = BatchEvaluate(pInParams, pOutInstance, pService);
  981. else
  982. hr = WBEM_E_INVALID_METHOD;
  983. if (SUCCEEDED(hr))
  984. hr = pResponseHandler->Indicate(1, &pOutInstance);
  985. }
  986. }
  987. }
  988. }
  989. else hr = WBEM_E_NOT_FOUND;
  990. }
  991. #ifdef TIME_TRIALS
  992. EvaluateTimer.Stop();
  993. EvaluateTimer.LogResults();
  994. EvaluateTimer.Reset(); // for next time!
  995. #endif
  996. // difficult call - do we put this before or after we take the timestamp?
  997. pResponseHandler->SetStatus(0,hr,NULL, NULL);
  998. CoRevertToSelf();
  999. return hr;
  1000. }