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.

504 lines
11 KiB

  1. /*++
  2. Copyright (C) 1996-2001 Microsoft Corporation
  3. Module Name:
  4. ASSRULE.CPP
  5. Abstract:
  6. History:
  7. --*/
  8. #include "assrule.h"
  9. #include <stdio.h>
  10. #define CLASSNAME_ASSOCIATION_RULE L"AssociationRule"
  11. #define PROPNAME_ASSOCIATION_CLASS L"AssociationClass"
  12. #define PROPNAME_RULE_IMMUTABLE L"RuleIsImmutable"
  13. #define PROPNAME_PROPNAME_1 L"PropertyName1"
  14. #define PROPNAME_QUERY_1 L"PropertyQuery1"
  15. #define PROPNAME_IMMUTABLE_1 L"Property1IsImmutable"
  16. #define PROPNAME_PROPNAME_2 L"PropertyName2"
  17. #define PROPNAME_QUERY_2 L"PropertyQuery2"
  18. #define PROPNAME_IMMUTABLE_2 L"Property2IsImmutable"
  19. #define EXTRA_GET_PARAMS ,NULL, NULL
  20. #define EXTRA_PUT_PARAMS ,0
  21. CEndpointCache::CEndpointCache()
  22. : m_strQuery(NULL), m_pEnum(NULL)
  23. {
  24. }
  25. void CEndpointCache::Create(BSTR strQuery, BOOL bCache)
  26. {
  27. m_strQuery = SysAllocString(strQuery);
  28. m_bCache = bCache;
  29. }
  30. CEndpointCache::~CEndpointCache()
  31. {
  32. SysFreeString(m_strQuery);
  33. if(m_pEnum)
  34. m_pEnum->Release();
  35. }
  36. HRESULT CEndpointCache::GetInstanceEnum(IWbemServices* pNamespace,
  37. IEnumWbemClassObject** ppEnum)
  38. {
  39. if(m_pEnum)
  40. {
  41. *ppEnum = m_pEnum;
  42. m_pEnum->AddRef();
  43. return S_OK;
  44. }
  45. HRESULT hres = pNamespace->ExecQuery(L"WQL", m_strQuery, 0, ppEnum, NULL);
  46. if(FAILED(hres)) return hres;
  47. if(m_bCache)
  48. {
  49. m_pEnum = *ppEnum;
  50. m_pEnum->AddRef();
  51. }
  52. return hres;
  53. }
  54. CAssocRule::CAssocRule()
  55. : m_strAssocClass(NULL), m_strProp1(NULL), m_strProp2(NULL), m_pClass(NULL),
  56. m_nRef(0), m_bMayCacheResult(FALSE), m_bResultCached(FALSE)
  57. {
  58. }
  59. CAssocRule::~CAssocRule()
  60. {
  61. SysFreeString(m_strAssocClass);
  62. SysFreeString(m_strProp1);
  63. SysFreeString(m_strProp2);
  64. if(m_pClass)
  65. m_pClass->Release();
  66. }
  67. void CAssocRule::AddRef()
  68. {
  69. m_nRef++;
  70. }
  71. void CAssocRule::Release()
  72. {
  73. if(--m_nRef == 0)
  74. {
  75. delete this;
  76. }
  77. }
  78. HRESULT CAssocRule::LoadFromObject(IWbemClassObject* pRule, BOOL bLongTerm)
  79. {
  80. HRESULT hres;
  81. VARIANT v;
  82. VariantInit(&v);
  83. // Read association name
  84. // =====================
  85. hres = pRule->Get(PROPNAME_ASSOCIATION_CLASS, 0, &v EXTRA_GET_PARAMS);
  86. if(FAILED(hres) || V_VT(&v) == VT_NULL)
  87. {
  88. return WBEM_E_FAILED;
  89. }
  90. m_strAssocClass = SysAllocString(V_BSTR(&v));
  91. VariantClear(&v);
  92. // Read property names
  93. // ===================
  94. hres = pRule->Get(PROPNAME_PROPNAME_1, 0, &v EXTRA_GET_PARAMS);
  95. if(FAILED(hres) || V_VT(&v) == VT_NULL)
  96. {
  97. return WBEM_E_FAILED;
  98. }
  99. m_strProp1 = SysAllocString(V_BSTR(&v));
  100. VariantClear(&v);
  101. hres = pRule->Get(PROPNAME_PROPNAME_2, 0, &v EXTRA_GET_PARAMS);
  102. if(FAILED(hres) || V_VT(&v) == VT_NULL)
  103. {
  104. return WBEM_E_FAILED;
  105. }
  106. m_strProp2 = SysAllocString(V_BSTR(&v));
  107. VariantClear(&v);
  108. m_bMayCacheResult = bLongTerm;
  109. // Read property rule (1)
  110. // ======================
  111. VARIANT vImmutable;
  112. VariantInit(&vImmutable);
  113. hres = pRule->Get(PROPNAME_QUERY_1, 0, &v EXTRA_GET_PARAMS);
  114. if(FAILED(hres) || V_VT(&v) == VT_NULL)
  115. {
  116. return WBEM_E_FAILED;
  117. }
  118. hres = pRule->Get(PROPNAME_IMMUTABLE_1, 0, &vImmutable EXTRA_GET_PARAMS);
  119. if(FAILED(hres) || V_VT(&vImmutable) == VT_NULL)
  120. {
  121. return WBEM_E_FAILED;
  122. }
  123. m_Cache1.Create(V_BSTR(&v), V_BOOL(&vImmutable));
  124. VariantClear(&v);
  125. if(!V_BOOL(&vImmutable))
  126. m_bMayCacheResult = FALSE;
  127. // Read property rule (2)
  128. // ======================
  129. hres = pRule->Get(PROPNAME_QUERY_2, 0, &v EXTRA_GET_PARAMS);
  130. if(FAILED(hres) || V_VT(&v) == VT_NULL)
  131. {
  132. return WBEM_E_FAILED;
  133. }
  134. hres = pRule->Get(PROPNAME_IMMUTABLE_2, 0, &vImmutable EXTRA_GET_PARAMS);
  135. if(FAILED(hres) || V_VT(&vImmutable) == VT_NULL)
  136. {
  137. return WBEM_E_FAILED;
  138. }
  139. m_Cache2.Create(V_BSTR(&v), V_BOOL(&vImmutable));
  140. VariantClear(&v);
  141. if(!V_BOOL(&vImmutable))
  142. m_bMayCacheResult = FALSE;
  143. return S_OK;
  144. }
  145. HRESULT CAssocRule::Produce(IWbemServices* pNamespace, IWbemObjectSink* pNotify)
  146. {
  147. HRESULT hres;
  148. // Check if we have it cached
  149. // ==========================
  150. if(m_bResultCached)
  151. {
  152. return m_ObjectCache.Indicate(pNotify);
  153. }
  154. // Get first enumerator
  155. // ====================
  156. IEnumWbemClassObject* pEnum1;
  157. hres = m_Cache1.GetInstanceEnum(pNamespace, &pEnum1);
  158. if(FAILED(hres))
  159. {
  160. return hres;
  161. }
  162. // Get second enumerator
  163. // =====================
  164. IEnumWbemClassObject* pEnum2;
  165. hres = m_Cache2.GetInstanceEnum(pNamespace, &pEnum2);
  166. if(FAILED(hres))
  167. {
  168. pEnum1->Release();
  169. return hres;
  170. }
  171. // Get the association class
  172. // =========================
  173. IWbemClassObject* pClass;
  174. if(m_pClass != NULL)
  175. {
  176. pClass = m_pClass;
  177. pClass->AddRef();
  178. }
  179. else
  180. {
  181. hres = pNamespace->GetObject(m_strAssocClass, 0, &pClass, NULL);
  182. if(FAILED(hres))
  183. {
  184. pEnum1->Release();
  185. pEnum2->Release();
  186. return hres;
  187. }
  188. }
  189. // Create all the associations
  190. // ===========================
  191. IWbemClassObject* pInstance1, *pInstance2;
  192. ULONG lNum;
  193. VARIANT v;
  194. VariantInit(&v);
  195. // Iterate through the first result set
  196. // ====================================
  197. pEnum1->Reset();
  198. while(pEnum1->Next(1, &pInstance1, &lNum) == S_OK)
  199. {
  200. // Get the first path
  201. // ==================
  202. hres = pInstance1->Get(L"__PATH", 0, &v EXTRA_GET_PARAMS);
  203. if(FAILED(hres))
  204. {
  205. pEnum1->Release();
  206. pEnum2->Release();
  207. pClass->Release();
  208. return hres;
  209. }
  210. BSTR strPath1 = V_BSTR(&v);
  211. VariantInit(&v); // intentional.
  212. // Iterate through the second result set
  213. // =====================================
  214. pEnum2->Reset();
  215. while(pEnum2->Next(1, &pInstance2, &lNum) == S_OK)
  216. {
  217. // Get the second path
  218. // ===================
  219. hres = pInstance2->Get(L"__PATH", 0, &v EXTRA_GET_PARAMS);
  220. if(FAILED(hres))
  221. {
  222. pEnum1->Release();
  223. pEnum2->Release();
  224. pClass->Release();
  225. return hres;
  226. }
  227. BSTR strPath2 = V_BSTR(&v);
  228. VariantInit(&v); // intentional
  229. // Create the association instance
  230. // ===============================
  231. IWbemClassObject* pInstance;
  232. hres = pClass->SpawnInstance(0, &pInstance);
  233. if(FAILED(hres))
  234. {
  235. pEnum1->Release();
  236. pEnum2->Release();
  237. pClass->Release();
  238. return hres;
  239. }
  240. // Set the properties
  241. // ==================
  242. V_VT(&v) = VT_BSTR;
  243. V_BSTR(&v) = strPath1;
  244. hres = pInstance->Put(m_strProp1, 0, &v EXTRA_PUT_PARAMS);
  245. if(FAILED(hres))
  246. {
  247. pEnum1->Release();
  248. pEnum2->Release();
  249. pClass->Release();
  250. pInstance->Release();
  251. return hres;
  252. }
  253. V_BSTR(&v) = strPath2;
  254. hres = pInstance->Put(m_strProp2, 0, &v EXTRA_PUT_PARAMS);
  255. if(FAILED(hres))
  256. {
  257. pEnum1->Release();
  258. pEnum2->Release();
  259. pClass->Release();
  260. pInstance->Release();
  261. return hres;
  262. }
  263. // Supply it
  264. // =========
  265. pNotify->Indicate(1, &pInstance);
  266. // Cache it if allowed
  267. // ===================
  268. if(m_bMayCacheResult)
  269. m_ObjectCache.Add(pInstance);
  270. pInstance->Release();
  271. SysFreeString(strPath2);
  272. pInstance2->Release();
  273. }
  274. SysFreeString(strPath1);
  275. pInstance1->Release();
  276. }
  277. pEnum1->Release();
  278. pEnum2->Release();
  279. pClass->Release();
  280. if(m_bMayCacheResult)
  281. m_bResultCached = TRUE;
  282. return S_OK;
  283. }
  284. //*****************************************************************************
  285. CAssocInfoCache::CAssocInfoCache() : m_pNamespace(NULL)
  286. {
  287. }
  288. void CAssocInfoCache::SetNamespace(IWbemServices* pNamespace)
  289. {
  290. m_pNamespace = pNamespace;
  291. m_pNamespace->AddRef();
  292. }
  293. CAssocInfoCache::~CAssocInfoCache()
  294. {
  295. if(m_pNamespace)
  296. m_pNamespace->Release();
  297. for(int i = 0; i < m_aRules.Size(); i++)
  298. {
  299. CAssocRule* pRule = (CAssocRule*)m_aRules[i];
  300. pRule->Release();
  301. }
  302. }
  303. HRESULT CAssocInfoCache::GetRuleForClass(BSTR strClass, CAssocRule** ppRule)
  304. {
  305. // Search our rules to see if we have it
  306. // =====================================
  307. for(int i = 0; i < m_aRules.Size(); i++)
  308. {
  309. CAssocRule* pRule = (CAssocRule*)m_aRules[i];
  310. if(!wcsicmp(pRule->GetAssocClass(), strClass))
  311. {
  312. pRule->AddRef();
  313. *ppRule = pRule;
  314. return S_OK;
  315. }
  316. }
  317. // Don't have it. Search for the rule in the database.
  318. // ===================================================
  319. HRESULT hres;
  320. BSTR strPath = SysAllocStringLen(NULL, wcslen(strClass) + 100);
  321. swprintf(strPath, L"%s.%s=\"%s\"", CLASSNAME_ASSOCIATION_RULE,
  322. PROPNAME_ASSOCIATION_CLASS, strClass);
  323. IWbemClassObject* pRuleInstance;
  324. hres = m_pNamespace->GetObject(strPath, 0, &pRuleInstance, NULL);
  325. SysFreeString(strPath);
  326. if(FAILED(hres))
  327. {
  328. return hres;
  329. }
  330. // Check if it is cachable
  331. // ========================
  332. VARIANT v;
  333. VariantInit(&v);
  334. hres = pRuleInstance->Get(PROPNAME_RULE_IMMUTABLE, 0, &v EXTRA_GET_PARAMS);
  335. if(FAILED(hres))
  336. {
  337. pRuleInstance->Release();
  338. return hres;
  339. }
  340. // Got it. Create the rule.
  341. // ========================
  342. CAssocRule* pRule = new CAssocRule;
  343. hres = pRule->LoadFromObject(pRuleInstance, V_BOOL(&v));
  344. pRuleInstance->Release();
  345. if(FAILED(hres))
  346. {
  347. delete pRule;
  348. return hres;
  349. }
  350. // Cache if allowed
  351. // ================
  352. if(V_BOOL(&v))
  353. {
  354. m_aRules.Add(pRule);
  355. pRule->AddRef();
  356. }
  357. // Return it to the caller
  358. // =======================
  359. pRule->AddRef();
  360. *ppRule = pRule;
  361. return S_OK;
  362. }
  363. //****************************************************************************
  364. CObjectCache::~CObjectCache()
  365. {
  366. Invalidate();
  367. }
  368. void CObjectCache::Invalidate()
  369. {
  370. for(int i = 0; i < m_aObjects.Size(); i++)
  371. {
  372. IWbemClassObject* pObject = (IWbemClassObject*)m_aObjects[i];
  373. pObject->Release();
  374. }
  375. m_aObjects.Empty();
  376. }
  377. void CObjectCache::Add(IWbemClassObject* pObject)
  378. {
  379. m_aObjects.Add((void*)pObject);
  380. pObject->AddRef();
  381. }
  382. HRESULT CObjectCache::Indicate(IWbemObjectSink* pSink)
  383. {
  384. if(m_aObjects.Size() == 0)
  385. return S_OK;
  386. void** ppvData = m_aObjects.GetArrayPtr();
  387. return pSink->Indicate(m_aObjects.Size(), (IWbemClassObject**)ppvData);
  388. }