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.

692 lines
18 KiB

  1. #include "PolicRange.h"
  2. #include <stdio.h>
  3. #include <windows.h>
  4. #include <ArrTempl.h>
  5. #include <wbemutil.h>
  6. #include <GenUtils.h>
  7. #include "genlex.h"
  8. #include "objpath.h"
  9. #include "utility.h"
  10. /******************************\
  11. **** POLICY PROVIDER HELPERS ***
  12. \******************************/
  13. // returns addref'd pointer back to m_pWMIMgmt
  14. IWbemServices* CPolicyRange::GetWMIServices(void)
  15. {
  16. CInCritSec lock(&m_CS);
  17. if (NULL != m_pWMIMgmt)
  18. m_pWMIMgmt->AddRef();
  19. return m_pWMIMgmt;
  20. }
  21. // returns addref'd pointer back to m_pADMgmt
  22. IADsContainer* CPolicyRange::GetADServices(void)
  23. {
  24. CInCritSec lock(&m_CS);
  25. IADsContainer *pADContainer = NULL;
  26. HRESULT hres;
  27. wchar_t *pADPath = NULL;
  28. if(NULL == pADPath)
  29. {
  30. if(NULL != m_pADMgmt)
  31. {
  32. m_pADMgmt->AddRef();
  33. pADContainer = m_pADMgmt;
  34. }
  35. }
  36. else
  37. {
  38. wchar_t
  39. szDSPath[MAX_PATH];
  40. // wcscpy(szDSPath,L"LDAP://");
  41. // wcscat(szDSPath, pADPath);
  42. hres = ADsGetObject(pADPath, IID_IADsContainer, (void**) &pADContainer);
  43. if (FAILED(hres))
  44. ERRORTRACE((LOG_ESS, "POLICMAN: failed 0x%08X\n", hres));
  45. }
  46. return pADContainer;
  47. }
  48. // returns false if services pointer has already been set
  49. bool CPolicyRange::SetWMIServices(IWbemServices* pServices)
  50. {
  51. CInCritSec lock(&m_CS);
  52. bool bOldOneNull;
  53. if (bOldOneNull = (m_pWMIMgmt == NULL))
  54. {
  55. m_pWMIMgmt = pServices;
  56. pServices->AddRef();
  57. }
  58. return bOldOneNull;
  59. }
  60. // returns false if services pointer has already been set
  61. bool CPolicyRange::SetADServices(IADsContainer* pServices)
  62. {
  63. CInCritSec lock(&m_CS);
  64. bool bOldOneNull;
  65. if (bOldOneNull = (m_pADMgmt == NULL))
  66. {
  67. m_pADMgmt = pServices;
  68. if(pServices) pServices->AddRef();
  69. }
  70. return bOldOneNull;
  71. }
  72. CPolicyRange::~CPolicyRange()
  73. {
  74. // **** WMI services object
  75. if (NULL != m_pWMIMgmt)
  76. {
  77. m_pWMIMgmt->Release();
  78. m_pWMIMgmt= NULL;
  79. }
  80. // **** AD services object
  81. if (NULL != m_pADMgmt)
  82. {
  83. m_pADMgmt->Release();
  84. m_pADMgmt= NULL;
  85. }
  86. };
  87. void* CPolicyRange::GetInterface(REFIID riid)
  88. {
  89. if(riid == IID_IWbemServices)
  90. return &m_XProvider;
  91. else if(riid == IID_IWbemProviderInit)
  92. return &m_XInit;
  93. else return NULL;
  94. }
  95. /*********************************************\
  96. *** Policy Template Specific Implementation ***
  97. \*********************************************/
  98. // returns addref'd pointer to class object
  99. IWbemClassObject* CPolicyRange::XProvider::GetPolicyTemplateClass()
  100. {
  101. CInCritSec lock(&m_pObject->m_CS);
  102. if(NULL == m_pWMIPolicyClassObject)
  103. {
  104. IWbemServices* pWinMgmt = NULL;
  105. if(pWinMgmt = m_pObject->GetWMIServices())
  106. {
  107. CReleaseMe relMgmt(pWinMgmt);
  108. pWinMgmt->GetObject(g_bstrClassMergeablePolicy,
  109. WBEM_FLAG_RETURN_WBEM_COMPLETE,
  110. NULL,
  111. &m_pWMIPolicyClassObject,
  112. NULL);
  113. }
  114. }
  115. if (m_pWMIPolicyClassObject)
  116. m_pWMIPolicyClassObject->AddRef();
  117. return m_pWMIPolicyClassObject;
  118. }
  119. // returns addref'd pointer to emply class instance
  120. IWbemClassObject* CPolicyRange::XProvider::GetPolicyTemplateInstance()
  121. {
  122. IWbemClassObject* pObj = NULL;
  123. IWbemClassObject* pClass = NULL;
  124. if (pClass = GetPolicyTemplateClass())
  125. {
  126. CReleaseMe releaseClass(pClass);
  127. pClass->SpawnInstance(0, &pObj);
  128. }
  129. return pObj;
  130. }
  131. CPolicyRange::XProvider::~XProvider()
  132. {
  133. // I fixed it! - HMH ;-)
  134. // CInCritSec lock(&m_pObject->m_CS);
  135. if(NULL != m_pWMIPolicyClassObject)
  136. {
  137. m_pWMIPolicyClassObject->Release();
  138. m_pWMIPolicyClassObject = NULL;
  139. }
  140. }
  141. /*************************\
  142. *** IWbemProviderInit ***
  143. \*************************/
  144. STDMETHODIMP CPolicyRange::XInit::Initialize(
  145. LPWSTR, LONG, LPWSTR, LPWSTR, IWbemServices* pServices, IWbemContext* pCtxt,
  146. IWbemProviderInitSink* pSink)
  147. {
  148. CComPtr<IADs>
  149. pRootDSE;
  150. CComPtr<IADsContainer>
  151. pObject;
  152. HRESULT
  153. hres = WBEM_S_NO_ERROR,
  154. hres2 = WBEM_S_NO_ERROR;
  155. CComVariant
  156. v1;
  157. wchar_t
  158. szDSPath[MAX_PATH];
  159. // **** impersonate client for security
  160. hres = CoImpersonateClient();
  161. if(FAILED(hres))
  162. {
  163. ERRORTRACE((LOG_ESS, "POLICMAN: (CoImpersonateClient) could not assume client permissions, 0x%08X\n", hres));
  164. hres = WBEM_S_ACCESS_DENIED;
  165. }
  166. else
  167. {
  168. // **** safe WMI name space pointer
  169. m_pObject->SetWMIServices(pServices);
  170. // **** get pointer to AD policy template table
  171. hres = ADsGetObject(L"LDAP://rootDSE", IID_IADs, (void**)&pRootDSE);
  172. if (FAILED(hres))
  173. {
  174. ERRORTRACE((LOG_ESS, "POLICMAN: (ADsGetObject) could not get object: LDAP://rootDSE, 0x%08X\n", hres));
  175. hres = WBEM_E_NOT_FOUND;
  176. }
  177. else
  178. {
  179. hres = pRootDSE->Get(L"defaultNamingContext",&v1);
  180. if(FAILED(hres))
  181. {
  182. ERRORTRACE((LOG_ESS, "POLICMAN: (IADs::Get) could not get defaultNamingContext, 0x%08X\n", hres));
  183. hres = WBEM_E_NOT_FOUND;
  184. }
  185. else
  186. {
  187. wcscpy(szDSPath,L"LDAP://CN=PolicyTemplate,CN=WMIPolicy,CN=System,");
  188. wcscat(szDSPath, V_BSTR(&v1));
  189. hres = ADsGetObject(szDSPath, IID_IADsContainer, (void**) &pObject);
  190. if (FAILED(hres))
  191. {
  192. ERRORTRACE((LOG_ESS, "POLICMAN: (ADsGetObject) could not get AD object: %S, 0x%08X\n", szDSPath, hres));
  193. hres = WBEM_E_NOT_FOUND;
  194. }
  195. m_pObject->SetADServices(pObject);
  196. }
  197. }
  198. }
  199. hres2 = pSink->SetStatus(hres, 0);
  200. if(FAILED(hres2))
  201. {
  202. ERRORTRACE((LOG_ESS, "POLICMAN: could not set return status\n"));
  203. if(SUCCEEDED(hres)) hres = hres2;
  204. }
  205. return hres;
  206. }
  207. /*******************\
  208. *** IWbemServices ***
  209. \*******************/
  210. //TODO: clean up bstrs & variants upon raising an exception (maybe theres a CVariantClearMe or some such?)
  211. HRESULT CPolicyRange::XProvider::DoResolve(IWbemServices* pPolicyNamespace,
  212. const BSTR strObjectPath,
  213. IWbemContext __RPC_FAR *pCtx,
  214. IWbemClassObject __RPC_FAR *pInParams,
  215. IWbemClassObject __RPC_FAR *pOutParams,
  216. IWbemObjectSink __RPC_FAR *pResponseHandler)
  217. {
  218. HRESULT
  219. hres = WBEM_E_FAILED;
  220. CComPtr<IUnknown>
  221. pUnk;
  222. ParsedObjectPath
  223. *pParsedObjectPath = NULL;
  224. CComPtr<IWbemClassObject>
  225. pTargetPolicyObj,
  226. pMergedParam;
  227. CComVariant
  228. vRetVal,
  229. vMergedRange,
  230. vObj,
  231. vMergedParamValue,
  232. vMergedParamName,
  233. vTargetValue;
  234. long
  235. nIndex = -1;
  236. wchar_t
  237. *pswIndexStart = NULL;
  238. // **** parse object path
  239. CObjectPathParser
  240. ObjPath(e_ParserAcceptRelativeNamespace);
  241. if(ObjPath.NoError != ObjPath.Parse(strObjectPath, &pParsedObjectPath))
  242. {
  243. ERRORTRACE((LOG_ESS, "POLICMAN: Parse error for object: %S\n", strObjectPath));
  244. hres = WBEM_E_INVALID_QUERY;
  245. }
  246. else
  247. {
  248. // **** get input param obj
  249. hres = pInParams->Get(L"mergedRange", 0, &vMergedRange, NULL, NULL);
  250. if(FAILED(hres)) return hres;
  251. hres = V_UNKNOWN(&vMergedRange)->QueryInterface(IID_IWbemClassObject, (void **)&pMergedParam);
  252. if(FAILED(hres)) return hres;
  253. // **** get target policy object
  254. hres = pInParams->Get(L"obj", 0, &vObj, NULL, NULL);
  255. if(FAILED(hres)) return hres;
  256. hres = V_UNKNOWN(&vObj)->QueryInterface(IID_IWbemClassObject, (void **)&pTargetPolicyObj);
  257. if(FAILED(hres)) return hres;
  258. // **** get name for attribute in target policy object named in param obj
  259. hres = pMergedParam->Get(L"PropertyName", 0, &vMergedParamName, NULL, NULL);
  260. if(FAILED(hres)) return hres;
  261. // **** parse name to see if it is part of an array
  262. if(pswIndexStart = wcsstr(V_BSTR(&vMergedParamName), L"["))
  263. {
  264. *pswIndexStart = L'\0';
  265. nIndex = wcstol(pswIndexStart + 1, NULL, 10);
  266. }
  267. // **** check to see if vParamAttrName is an attribute in target object
  268. hres = pTargetPolicyObj->Get(V_BSTR(&vMergedParamName), 0, &vTargetValue, NULL, NULL);
  269. if(FAILED(hres))
  270. {
  271. if(WBEM_E_NOT_FOUND == hres)
  272. {
  273. ERRORTRACE((LOG_ESS, "POLICMAN: Policy range setting %S not in target object\n", vMergedParamName.bstrVal));
  274. }
  275. else
  276. return hres;
  277. }
  278. else
  279. {
  280. // **** get default value from param obj
  281. hres = pMergedParam->Get(L"Default", 0, &vMergedParamValue, NULL, NULL);
  282. if(FAILED(hres)) return hres;
  283. // **** set value
  284. if(nIndex < 0)
  285. {
  286. // **** check to see if attribute is already set
  287. if(vTargetValue.vt != VT_NULL)
  288. {
  289. ERRORTRACE((LOG_ESS, "POLICMAN: Attempt to set policy range setting %S more than once\n", vMergedParamName.bstrVal));
  290. }
  291. else
  292. {
  293. hres = pTargetPolicyObj->Put(V_BSTR(&vMergedParamName), 0, &vMergedParamValue, 0);
  294. if(FAILED(hres))
  295. {
  296. ERRORTRACE((LOG_ESS, "POLICMAN: Attempting to place attribute %S in target instance generated error 0x%x\n", vMergedParamName.bstrVal, hres));
  297. return hres;
  298. }
  299. }
  300. }
  301. else
  302. {
  303. if((vTargetValue.vt & VT_ARRAY) || (vTargetValue.vt == VT_NULL))
  304. {
  305. CComVariant
  306. vNewArray;
  307. // **** signed and unsigned integers
  308. if((vMergedParamValue.vt & VT_I4))
  309. {
  310. SafeArray<int, VT_I4>
  311. arrayMember(&vTargetValue);
  312. if(arrayMember.IndexMax() < nIndex)
  313. {
  314. arrayMember.ReDim(0, nIndex + 1);
  315. }
  316. arrayMember[nIndex] = vMergedParamValue.lVal;
  317. V_VT(&vNewArray) = (VT_ARRAY | VT_I4);
  318. V_ARRAY(&vNewArray) = arrayMember.Data();
  319. }
  320. // **** real numbers
  321. else if((vMergedParamValue.vt & VT_R8))
  322. {
  323. SafeArray<double, VT_R8>
  324. arrayMember(&vTargetValue);
  325. if(arrayMember.IndexMax() < nIndex)
  326. {
  327. arrayMember.ReDim(0, nIndex + 1);
  328. }
  329. arrayMember[nIndex] = vMergedParamValue.dblVal;
  330. V_VT(&vNewArray) = (VT_ARRAY | VT_R8);
  331. V_ARRAY(&vNewArray) = arrayMember.Data();
  332. }
  333. // **** strings
  334. else if((vMergedParamValue.vt & VT_BSTR))
  335. {
  336. SafeArray<BSTR, VT_BSTR>
  337. arrayMember(&vTargetValue);
  338. if(arrayMember.IndexMax() < nIndex)
  339. {
  340. arrayMember.ReDim(0, nIndex + 1);
  341. }
  342. else if(NULL != arrayMember[nIndex])
  343. {
  344. SysFreeString(arrayMember[nIndex]);
  345. }
  346. arrayMember[nIndex] = SysAllocString(vMergedParamValue.bstrVal);
  347. V_VT(&vNewArray) = (VT_ARRAY | VT_BSTR);
  348. V_ARRAY(&vNewArray) = arrayMember.Data();
  349. }
  350. hres = pTargetPolicyObj->Put(V_BSTR(&vMergedParamName), 0, &vNewArray, 0);
  351. if(FAILED(hres)) return hres;
  352. }
  353. else
  354. return WBEM_E_TYPE_MISMATCH;
  355. }
  356. }
  357. // **** put target policy obj in output param obj
  358. hres = pTargetPolicyObj->QueryInterface(IID_IUnknown, (void **)&pUnk);
  359. if(FAILED(hres)) return hres;
  360. vObj = pUnk;
  361. hres = pOutParams->Put(L"obj", 0, &vObj, 0);
  362. if(FAILED(hres)) return hres;
  363. // **** put status in return value
  364. vRetVal = hres;
  365. hres = pOutParams->Put(L"ReturnValue", 0, &vRetVal, 0);
  366. if(FAILED(hres)) return hres;
  367. // **** send output back to client
  368. hres = pResponseHandler->Indicate(1, &pOutParams);
  369. if(FAILED(hres)) return hres;
  370. }
  371. ObjPath.Free(pParsedObjectPath);
  372. return hres;
  373. }
  374. HRESULT CPolicyRange::XProvider::DoSet()
  375. {
  376. HRESULT hr = WBEM_E_FAILED;
  377. return hr;
  378. }
  379. HRESULT CPolicyRange::XProvider::DoMerge(IWbemServices* pNamespace,
  380. const BSTR strObjectPath,
  381. IWbemContext __RPC_FAR *pCtx,
  382. IWbemClassObject __RPC_FAR *pInParams,
  383. IWbemClassObject __RPC_FAR *pOutParams,
  384. IWbemObjectSink __RPC_FAR *pResponseHandler)
  385. {
  386. HRESULT
  387. hres = WBEM_E_FAILED;
  388. CComPtr<IUnknown>
  389. pUnk;
  390. ParsedObjectPath
  391. *pParsedObjectPath = NULL;
  392. CComPtr<IWbemClassObject>
  393. pMergedParam;
  394. CComVariant
  395. v1;
  396. // **** parse object path
  397. CObjectPathParser
  398. ObjPath(e_ParserAcceptRelativeNamespace);
  399. if(ObjPath.NoError != ObjPath.Parse(strObjectPath, &pParsedObjectPath))
  400. {
  401. ERRORTRACE((LOG_ESS, "POLICMAN: Parse error for object: %S\n", strObjectPath));
  402. hres = WBEM_E_INVALID_QUERY;
  403. }
  404. else
  405. {
  406. int
  407. firstElement = -1,
  408. conflictObj = -1;
  409. CComPtr<IWbemClassObject>
  410. pArrayElement;
  411. CComVariant
  412. vRangeParamType;
  413. // **** get input array
  414. hres = pInParams->Get(L"ranges", 0, &v1, NULL, NULL);
  415. if(FAILED(hres)) return hres;
  416. SafeArray<IUnknown*, VT_UNKNOWN>
  417. InputArray(&v1);
  418. firstElement = -1;
  419. while((++firstElement < InputArray.Size()) && (NULL == InputArray[firstElement]));
  420. if(firstElement >= InputArray.Size()) return WBEM_E_INVALID_PARAMETER;
  421. // **** get actual type of range parameter objects
  422. hres = InputArray[firstElement]->QueryInterface(IID_IWbemClassObject, (void **)&pArrayElement);
  423. if(FAILED(hres)) return hres;
  424. hres = pArrayElement->Get(L"__CLASS", 0, &vRangeParamType, NULL, NULL);
  425. if(FAILED(hres)) return hres;
  426. // **** perform merge
  427. if(-1 == conflictObj)
  428. {
  429. if(_wcsicmp(vRangeParamType.bstrVal, L"MSFT_SintRangeParam") == 0)
  430. hres = Range_Sint32_Merge(InputArray, pMergedParam, conflictObj);
  431. else if(_wcsicmp(vRangeParamType.bstrVal, L"MSFT_UintRangeParam") == 0)
  432. hres = Range_Uint32_Merge(InputArray, pMergedParam, conflictObj);
  433. else if(_wcsicmp(vRangeParamType.bstrVal, L"MSFT_RealRangeParam") == 0)
  434. hres = Range_Real_Merge(InputArray, pMergedParam, conflictObj);
  435. else if(_wcsicmp(vRangeParamType.bstrVal, L"MSFT_SintSetParam") == 0)
  436. hres = Set_Sint32_Merge(InputArray, pMergedParam, conflictObj);
  437. else if(_wcsicmp(vRangeParamType.bstrVal, L"MSFT_UintSetParam") == 0)
  438. hres = Set_Uint32_Merge(InputArray, pMergedParam, conflictObj);
  439. else if(_wcsicmp(vRangeParamType.bstrVal, L"MSFT_StringSetParam") == 0)
  440. hres = Set_String_Merge(InputArray, pMergedParam, conflictObj);
  441. else
  442. return WBEM_E_INVALID_PARAMETER;
  443. }
  444. // **** put merged range in output param obj
  445. if(NULL != pMergedParam.p)
  446. {
  447. hres = pMergedParam->QueryInterface(IID_IUnknown, (void **)&pUnk);
  448. if(FAILED(hres)) return hres;
  449. v1 = pUnk;
  450. hres = pOutParams->Put(L"mergedRange", 0, &v1, 0);
  451. if(FAILED(hres)) return hres;
  452. }
  453. // **** put put which policy object caused conflict
  454. v1 = conflictObj;
  455. hres = pOutParams->Put(L"conflict", 0, &v1, 0);
  456. if(FAILED(hres)) return hres;
  457. // **** put status in return value
  458. v1 = hres;
  459. hres = pOutParams->Put(L"ReturnValue", 0, &v1, 0);
  460. if(FAILED(hres)) return hres;
  461. // **** send output back to client
  462. hres = pResponseHandler->Indicate(1, &pOutParams);
  463. if(FAILED(hres)) return hres;
  464. }
  465. ObjPath.Free(pParsedObjectPath);
  466. return WBEM_S_NO_ERROR;
  467. }
  468. STDMETHODIMP CPolicyRange::XProvider::ExecMethodAsync(
  469. /* [in] */ const BSTR strObjectPath,
  470. /* [in] */ const BSTR strMethodName,
  471. /* [in] */ long lFlags,
  472. /* [in] */ IWbemContext __RPC_FAR *pCtx,
  473. /* [in] */ IWbemClassObject __RPC_FAR *pInParams,
  474. /* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler)
  475. {
  476. HRESULT
  477. hres = WBEM_S_NO_ERROR;
  478. IWbemServices* pNamespace = m_pObject->GetWMIServices();
  479. CReleaseMe RelpNamespace(pNamespace);
  480. // **** impersonate client
  481. hres = CoImpersonateClient();
  482. if(FAILED(hres))
  483. {
  484. ERRORTRACE((LOG_ESS, "POLICMAN: (CoImpersonateClient) could not assume client permissions, 0x%08X\n", hres));
  485. hres = WBEM_S_ACCESS_DENIED;
  486. }
  487. else
  488. {
  489. if((NULL == strObjectPath) ||
  490. (NULL == strMethodName) ||
  491. (NULL == pInParams) ||
  492. (NULL == pResponseHandler))
  493. {
  494. ERRORTRACE((LOG_ESS, "POLICMAN: object handle and/or return status objects are NULL\n"));
  495. hres = WBEM_E_INVALID_PARAMETER;
  496. }
  497. else
  498. {
  499. try
  500. {
  501. // **** get policy template class definition
  502. IWbemClassObject* pClass = NULL;
  503. hres = pNamespace->GetObject(g_bstrClassRangeParam, 0, pCtx, &pClass, NULL);
  504. if(FAILED(hres)) return hres;
  505. CReleaseMe relClass(pClass);
  506. // **** get output object
  507. IWbemClassObject* pOutClass = NULL;
  508. IWbemClassObject* pOutParamsObj = NULL;
  509. CReleaseMe relOutClass(pOutClass);
  510. CReleaseMe relOutObj(pOutParamsObj);
  511. hres = pClass->GetMethod(strMethodName, 0, NULL, &pOutClass);
  512. if(FAILED(hres)) return hres;
  513. hres = pOutClass->SpawnInstance(0, &pOutParamsObj);
  514. if(FAILED(hres)) return hres;
  515. // **** figure out which method we're here to service
  516. if (_wcsicmp(strMethodName, L"Merge") == 0)
  517. hres = DoMerge(pNamespace, strObjectPath, pCtx, pInParams, pOutParamsObj, pResponseHandler);
  518. else if (_wcsicmp(strMethodName, L"Resolve") == 0)
  519. hres = DoResolve(pNamespace, strObjectPath, pCtx, pInParams, pOutParamsObj, pResponseHandler);
  520. else
  521. hres = WBEM_E_INVALID_PARAMETER;
  522. }
  523. catch(long hret)
  524. {
  525. ERRORTRACE((LOG_ESS, "POLICMAN: caught exception with HRESULT 0x%08X\n", hret));
  526. hres = hret;
  527. }
  528. catch(wchar_t *swErrString)
  529. {
  530. ERRORTRACE((LOG_ESS, "POLICMAN: Caught Exception: %S\n", swErrString));
  531. hres = WBEM_E_FAILED;
  532. }
  533. catch(...)
  534. {
  535. ERRORTRACE((LOG_ESS, "POLICMAN: Caught unknown Exception\n"));
  536. hres = WBEM_E_FAILED;
  537. }
  538. }
  539. pResponseHandler->SetStatus(0, hres, NULL, NULL);
  540. hres = CoRevertToSelf();
  541. }
  542. return hres;
  543. }