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.

495 lines
12 KiB

  1. //******************************************************************************
  2. //
  3. // Copyright (c) 1999-2000, Microsoft Corporation, All rights reserved
  4. //
  5. //*****************************************************************************
  6. #include "precomp.h"
  7. #include <stdio.h>
  8. #include "ess.h"
  9. #include "moniprov.h"
  10. CMonitorProvider::CMonitorProvider(CLifeControl* pControl) : TUnkBase(pControl),
  11. m_pNamespace(NULL), m_pSink(NULL), m_pAssertClass(NULL), m_pRetractClass(NULL), m_pGoingUpClass(NULL), m_pGoingDownClass(NULL), m_pErrorClass( NULL )
  12. {
  13. }
  14. CMonitorProvider::~CMonitorProvider()
  15. {
  16. Shutdown();
  17. if(m_pNamespace)
  18. m_pNamespace->Release();
  19. if(m_pSink)
  20. m_pSink->Release();
  21. if( m_pAssertClass )
  22. {
  23. m_pAssertClass->Release();
  24. }
  25. if ( m_pRetractClass )
  26. {
  27. m_pRetractClass->Release();
  28. }
  29. if ( m_pGoingUpClass )
  30. {
  31. m_pGoingUpClass->Release();
  32. }
  33. if ( m_pGoingDownClass )
  34. {
  35. m_pGoingDownClass->Release();
  36. }
  37. if ( m_pErrorClass )
  38. {
  39. m_pErrorClass->Release();
  40. }
  41. }
  42. HRESULT CMonitorProvider::Shutdown()
  43. {
  44. CInCritSec ics(&m_cs);
  45. for(TIterator it = m_mapMonitors.begin(); it != m_mapMonitors.end(); it++)
  46. {
  47. delete it->second;
  48. }
  49. m_mapMonitors.clear();
  50. return WBEM_S_NO_ERROR;
  51. }
  52. HRESULT CMonitorProvider::SetNamespace(CEssNamespace* pNamespace)
  53. {
  54. m_pNamespace = pNamespace;
  55. m_pNamespace->AddRef();
  56. //
  57. // Retrieve system classes from the namespace
  58. //
  59. if(FAILED(m_pNamespace->GetClass(ASSERT_EVENT_CLASS, &m_pAssertClass)))
  60. return WBEM_E_CRITICAL_ERROR;
  61. if(FAILED(m_pNamespace->GetClass(RETRACT_EVENT_CLASS, &m_pRetractClass)))
  62. return WBEM_E_CRITICAL_ERROR;
  63. if(FAILED(m_pNamespace->GetClass(GOINGUP_EVENT_CLASS, &m_pGoingUpClass)))
  64. return WBEM_E_CRITICAL_ERROR;
  65. if(FAILED(m_pNamespace->GetClass(GOINGDOWN_EVENT_CLASS, &m_pGoingDownClass)))
  66. return WBEM_E_CRITICAL_ERROR;
  67. if(FAILED(m_pNamespace->GetClass(MONITORERROR_EVENT_CLASS, &m_pErrorClass)))
  68. return WBEM_E_CRITICAL_ERROR;
  69. //
  70. // Retrieve handle values
  71. //
  72. m_pAssertClass->GetPropertyHandleEx(MONITORNAME_EVENT_PROPNAME,
  73. 0, NULL, &m_lNameHandle);
  74. m_pAssertClass->GetPropertyHandleEx(MONITOROBJECT_EVENT_PROPNAME,
  75. 0, NULL, &m_lObjectHandle);
  76. m_pAssertClass->GetPropertyHandleEx(MONITORCOUNT_EVENT_PROPNAME,
  77. 0, NULL, &m_lCountHandle);
  78. m_pAssertClass->GetPropertyHandleEx(MONITORNEW_EVENT_PROPNAME,
  79. 0, NULL, &m_lNewHandle);
  80. return S_OK;
  81. }
  82. STDMETHODIMP CMonitorProvider::ProvideEvents(IWbemObjectSink* pSink,
  83. long lFlags)
  84. {
  85. return pSink->QueryInterface(IID_IWbemEventSink, (void**)&m_pSink);
  86. }
  87. HRESULT CMonitorProvider::AddMonitor(LPCWSTR wszName, LPCWSTR wszQuery,
  88. long lFlags, IWbemContext* pContext)
  89. {
  90. HRESULT hres;
  91. CMonitor* pMonitor = new CMonitor;
  92. if(pMonitor == NULL)
  93. return WBEM_E_OUT_OF_MEMORY;
  94. CFiringMonitorCallback* pCallback =
  95. new CFiringMonitorCallback(this, wszName);
  96. if(pCallback == NULL || pCallback->GetName() == NULL)
  97. return WBEM_E_OUT_OF_MEMORY;
  98. pCallback->AddRef();
  99. CTemplateReleaseMe<CFiringMonitorCallback> rm1(pCallback);
  100. hres = pCallback->Initialize();
  101. if(FAILED(hres))
  102. {
  103. delete pMonitor;
  104. return hres;
  105. }
  106. hres = pMonitor->Construct(m_pNamespace, pCallback, wszQuery);
  107. if(FAILED(hres))
  108. {
  109. delete pMonitor;
  110. return hres;
  111. }
  112. //
  113. // Attempt to start the monitor. TBD: consider monitor's guard
  114. //
  115. hres = pMonitor->Start(pContext);
  116. if(FAILED(hres))
  117. {
  118. //
  119. // Could not start monitor --- depending on whether strong validation
  120. // is required, remove the monitor or keep it inactive
  121. //
  122. if(lFlags & WBEM_FLAG_STRONG_VALIDATION)
  123. {
  124. delete pMonitor;
  125. return hres;
  126. }
  127. }
  128. //
  129. // Add the monitor to the list, active or not
  130. //
  131. {
  132. CInCritSec ics(&m_cs);
  133. m_mapMonitors[wszName] = pMonitor;
  134. }
  135. return hres;
  136. }
  137. HRESULT CMonitorProvider::RemoveMonitor(LPCWSTR wszName, IWbemContext* pContext)
  138. {
  139. CInCritSec ics(&m_cs);
  140. TIterator it = m_mapMonitors.find(wszName);
  141. if(it == m_mapMonitors.end())
  142. return WBEM_S_FALSE;
  143. it->second->Stop(pContext);
  144. delete it->second;
  145. m_mapMonitors.erase(it);
  146. return WBEM_S_NO_ERROR;
  147. }
  148. // static
  149. HRESULT CMonitorProvider::GetMonitorInfo(IWbemClassObject* pMonitorObj,
  150. BSTR* pstrKey, BSTR* pstrQuery, long* plFlags)
  151. {
  152. HRESULT hres;
  153. if(pstrKey)
  154. {
  155. //
  156. // Extract the relpath to use as the key
  157. //
  158. VARIANT v;
  159. hres = pMonitorObj->Get(MONITOR_NAME_PROPNAME, 0, &v, NULL, NULL);
  160. if(FAILED(hres))
  161. {
  162. ERRORTRACE((LOG_ESS, "Monitor without a path? Not valid\n"));
  163. return hres;
  164. }
  165. if(V_VT(&v) != VT_BSTR)
  166. return WBEM_E_CRITICAL_ERROR;
  167. *pstrKey = V_BSTR(&v);
  168. }
  169. if(pstrQuery)
  170. {
  171. //
  172. // Check query type
  173. //
  174. VARIANT vType;
  175. VariantInit(&vType);
  176. CClearMe cm1(&vType);
  177. hres = pMonitorObj->Get(MONITOR_QUERYLANG_PROPNAME, 0, &vType, NULL,
  178. NULL);
  179. if(FAILED(hres))
  180. {
  181. ERRORTRACE((LOG_ESS, "Monitor without a query type? Not valid\n"));
  182. return hres;
  183. }
  184. if(V_VT(&vType) != VT_BSTR)
  185. {
  186. ERRORTRACE((LOG_ESS, "Monitor without a query type? Not valid\n"));
  187. return WBEM_E_INVALID_OBJECT;
  188. }
  189. if(wbem_wcsicmp(V_BSTR(&vType), L"WQL"))
  190. {
  191. ERRORTRACE((LOG_ESS, "Monitor with invalid query type %S is "
  192. "rejected\n", V_BSTR(&vType)));
  193. return hres;
  194. }
  195. //
  196. // Extract the query
  197. //
  198. VARIANT v;
  199. hres = pMonitorObj->Get(MONITOR_QUERY_PROPNAME, 0, &v, NULL, NULL);
  200. if(FAILED(hres))
  201. {
  202. ERRORTRACE((LOG_ESS, "Monitor without a name? Not valid\n"));
  203. return hres;
  204. }
  205. if(V_VT(&v) != VT_BSTR)
  206. return hres;
  207. *pstrQuery = V_BSTR(&v);
  208. }
  209. if(plFlags)
  210. {
  211. //
  212. // TBD: no flags for now
  213. //
  214. *plFlags = 0;
  215. }
  216. return WBEM_S_NO_ERROR;
  217. }
  218. HRESULT CMonitorProvider::ConstructAssert(LPCWSTR wszName, _IWmiObject* pObj,
  219. bool bEvent,
  220. DWORD dwTotalCount, _IWmiObject** ppEvent)
  221. {
  222. HRESULT hres;
  223. hres = GetInstance(m_pAssertClass, wszName, dwTotalCount, ppEvent);
  224. if(FAILED(hres))
  225. return hres;
  226. hres = SetObject(*ppEvent, pObj, bEvent);
  227. if(FAILED(hres))
  228. (*ppEvent)->Release();
  229. return hres;
  230. }
  231. HRESULT CMonitorProvider::ConstructRetract(LPCWSTR wszName, _IWmiObject* pObj, bool bEvent,
  232. DWORD dwTotalCount, _IWmiObject** ppEvent)
  233. {
  234. HRESULT hres;
  235. hres = GetInstance(m_pRetractClass, wszName, dwTotalCount, ppEvent);
  236. if(FAILED(hres))
  237. return hres;
  238. hres = SetObject(*ppEvent, pObj, bEvent);
  239. if(FAILED(hres))
  240. (*ppEvent)->Release();
  241. return hres;
  242. }
  243. HRESULT CMonitorProvider::ConstructGoingUp(LPCWSTR wszName, DWORD dwNumMatching,
  244. _IWmiObject** ppEvent)
  245. {
  246. return GetInstance(m_pGoingUpClass, wszName, dwNumMatching, ppEvent);
  247. }
  248. HRESULT CMonitorProvider::ConstructGoingDown(LPCWSTR wszName, DWORD dwNumMatching,
  249. _IWmiObject** ppEvent)
  250. {
  251. return GetInstance(m_pGoingDownClass, wszName, dwNumMatching, ppEvent);
  252. }
  253. HRESULT CMonitorProvider::ConstructError(LPCWSTR wszName, HRESULT hresError,
  254. IWbemClassObject* pErrorObj,
  255. _IWmiObject** ppEvent)
  256. {
  257. return GetInstance(m_pErrorClass, wszName, 0, ppEvent);
  258. }
  259. HRESULT CMonitorProvider::GetInstance(_IWmiObject* pClass, LPCWSTR wszName, DWORD dwCount,
  260. _IWmiObject** ppEvent)
  261. {
  262. if(pClass == NULL)
  263. return WBEM_E_CRITICAL_ERROR;
  264. HRESULT hres;
  265. IWbemClassObject* pEvent = NULL;
  266. hres = pClass->SpawnInstance(0, &pEvent);
  267. if(FAILED(hres))
  268. return hres;
  269. pEvent->QueryInterface(IID__IWmiObject, (void**)ppEvent);
  270. pEvent->Release();
  271. hres = (*ppEvent)->SetPropByHandle(m_lCountHandle, 0, sizeof(DWORD),
  272. &dwCount);
  273. if(FAILED(hres))
  274. {
  275. (*ppEvent)->Release();
  276. return hres;
  277. }
  278. hres = (*ppEvent)->SetPropByHandle(m_lNameHandle, 0,
  279. wcslen(wszName)*2+2, (LPVOID)wszName);
  280. if(FAILED(hres))
  281. {
  282. (*ppEvent)->Release();
  283. return hres;
  284. }
  285. return WBEM_S_NO_ERROR;
  286. }
  287. HRESULT CMonitorProvider::SetObject(_IWmiObject* pEvent, _IWmiObject* pObj,
  288. bool bFromEvent)
  289. {
  290. HRESULT hres;
  291. hres = pEvent->SetPropByHandle(m_lObjectHandle, 0, sizeof(_IWmiObject*),
  292. &pObj);
  293. if(FAILED(hres))
  294. return hres;
  295. short bNew = (bFromEvent?-1:0);
  296. hres = pEvent->SetPropByHandle(m_lNewHandle, 0, sizeof(short), &bNew);
  297. if(FAILED(hres))
  298. return hres;
  299. return WBEM_S_NO_ERROR;
  300. }
  301. CFiringMonitorCallback::CFiringMonitorCallback(CMonitorProvider* pProvider,
  302. LPCWSTR wszName)
  303. : m_pProvider(pProvider), m_wsName(wszName), m_pSink(NULL), m_lRef(0)
  304. {
  305. if(m_pProvider)
  306. m_pProvider->AddRef();
  307. }
  308. CFiringMonitorCallback::~CFiringMonitorCallback()
  309. {
  310. if(m_pProvider)
  311. m_pProvider->Release();
  312. if(m_pSink)
  313. m_pSink->Release();
  314. }
  315. ULONG STDMETHODCALLTYPE CFiringMonitorCallback::AddRef()
  316. {
  317. return InterlockedIncrement(&m_lRef);
  318. }
  319. ULONG STDMETHODCALLTYPE CFiringMonitorCallback::Release()
  320. {
  321. long lRef = InterlockedIncrement(&m_lRef);
  322. if(lRef == 0)
  323. delete this;
  324. return lRef;
  325. }
  326. HRESULT CFiringMonitorCallback::Initialize()
  327. {
  328. //
  329. // Get us a restricted sink for our key. TBD
  330. //
  331. m_pSink = m_pProvider->GetSink();
  332. m_pSink->AddRef();
  333. return S_OK;
  334. }
  335. bool CFiringMonitorCallback::CheckSink()
  336. {
  337. return (m_pSink && (m_pSink->IsActive() == WBEM_S_NO_ERROR));
  338. }
  339. HRESULT CFiringMonitorCallback::FireEvent(_IWmiObject* pEvent)
  340. {
  341. return m_pSink->Indicate(1, (IWbemClassObject**)&pEvent);
  342. }
  343. HRESULT CFiringMonitorCallback::Assert(_IWmiObject* pObj, LPCWSTR wszPath,
  344. bool bEvent, DWORD dwTotalCount)
  345. {
  346. if(!CheckSink())
  347. return WBEM_S_FALSE;
  348. HRESULT hres;
  349. _IWmiObject* pEvent = NULL;
  350. hres = m_pProvider->ConstructAssert(m_wsName, pObj, bEvent, dwTotalCount, &pEvent);
  351. if(FAILED(hres))
  352. return hres;
  353. CReleaseMe rm(pEvent);
  354. return FireEvent(pEvent);
  355. }
  356. HRESULT CFiringMonitorCallback::Retract(_IWmiObject* pObj, LPCWSTR wszPath,
  357. bool bEvent, DWORD dwTotalCount)
  358. {
  359. if(!CheckSink())
  360. return WBEM_S_FALSE;
  361. HRESULT hres;
  362. _IWmiObject* pEvent = NULL;
  363. hres = m_pProvider->ConstructRetract(m_wsName, pObj, bEvent, dwTotalCount, &pEvent);
  364. if(FAILED(hres))
  365. return hres;
  366. CReleaseMe rm(pEvent);
  367. return FireEvent(pEvent);
  368. }
  369. HRESULT CFiringMonitorCallback::GoingUp(DWORD dwNumMatching)
  370. {
  371. if(!CheckSink())
  372. return WBEM_S_FALSE;
  373. HRESULT hres;
  374. _IWmiObject* pEvent = NULL;
  375. hres = m_pProvider->ConstructGoingUp(m_wsName, dwNumMatching, &pEvent);
  376. if(FAILED(hres))
  377. return hres;
  378. CReleaseMe rm(pEvent);
  379. return FireEvent(pEvent);
  380. }
  381. HRESULT CFiringMonitorCallback::GoingDown(DWORD dwNumMatching)
  382. {
  383. if(!CheckSink())
  384. return WBEM_S_FALSE;
  385. HRESULT hres;
  386. _IWmiObject* pEvent = NULL;
  387. hres = m_pProvider->ConstructGoingDown(m_wsName, dwNumMatching, &pEvent);
  388. if(FAILED(hres))
  389. return hres;
  390. CReleaseMe rm(pEvent);
  391. return FireEvent(pEvent);
  392. }
  393. HRESULT CFiringMonitorCallback::Error(HRESULT hresError,
  394. IWbemClassObject* pErrorObj)
  395. {
  396. if(!CheckSink())
  397. return WBEM_S_FALSE;
  398. HRESULT hres;
  399. _IWmiObject* pEvent = NULL;
  400. hres = m_pProvider->ConstructError(m_wsName, hresError, pErrorObj, &pEvent);
  401. if(FAILED(hres))
  402. return hres;
  403. CReleaseMe rm(pEvent);
  404. return FireEvent(pEvent);
  405. }