Leaked source code of windows server 2003
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.

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