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.

662 lines
16 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2000 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // SADiskEvent.cpp
  7. //
  8. // Description:
  9. // description-for-module
  10. //
  11. // [Header File:]
  12. // SADiskEvent.h
  13. //
  14. // History:
  15. // Xing Jin (i-xingj) 06-Dec-2000
  16. //
  17. //////////////////////////////////////////////////////////////////////////////
  18. #include <windows.h>
  19. #include <stdio.h>
  20. #include <wbemidl.h>
  21. #include <satrace.h>
  22. #include "SADiskEvent.h"
  23. #include <oahelp.inl>
  24. #include <SAEventComm.h>
  25. const WCHAR SA_DISKEVENTPROVIDER_DISKCOUNTER_NAME[] =
  26. L"\\PhysicalDisk(_Total#0)\\Disk Transfers/sec";
  27. const WCHAR SA_SADEVMONITOR_KEYPATH [] =
  28. L"SOFTWARE\\Microsoft\\ServerAppliance\\DeviceMonitor";
  29. const WCHAR SA_SADISKMONITOR_QUERYINTERVAL[] = L"DiskQueryInterval";
  30. //static DWORD g_dwDiskTimeInterval = 1000;
  31. const DWORD DEFAULTQUERYINTERVAL = 1000;
  32. //////////////////////////////////////////////////////////////////////////////
  33. //
  34. // CSADiskEvent::CSADiskEvent
  35. //
  36. // Description:
  37. // Class constructor.
  38. //
  39. // History:
  40. // Xing Jin (i-xingj) 06-Dec-2000
  41. //
  42. //////////////////////////////////////////////////////////////////////////////
  43. CSADiskEvent::CSADiskEvent()
  44. {
  45. m_cRef = 0;
  46. m_lStatus = Pending;
  47. m_dwDiskTimeInterval = 1000;
  48. m_hThread = NULL;
  49. m_pNs = NULL;
  50. m_pSink = NULL;
  51. m_pEventClassDef = NULL;
  52. m_hqryQuery = NULL;
  53. m_hcntCounter = NULL;
  54. m_hQueryInterval = NULL;
  55. }
  56. //////////////////////////////////////////////////////////////////////////////
  57. //
  58. // CSADiskEvent::~CSADiskEvent
  59. //
  60. // Description:
  61. // Class deconstructor.
  62. //
  63. // History:
  64. // Xing Jin (i-xingj) 06-Dec-2000
  65. //
  66. //////////////////////////////////////////////////////////////////////////////
  67. CSADiskEvent::~CSADiskEvent()
  68. {
  69. if( m_hqryQuery )
  70. {
  71. PdhCloseQuery( m_hqryQuery );
  72. }
  73. if (m_hThread)
  74. {
  75. CloseHandle(m_hThread);
  76. }
  77. if( m_hQueryInterval != NULL )
  78. {
  79. ::RegCloseKey( m_hQueryInterval );
  80. }
  81. if (m_pNs)
  82. {
  83. m_pNs->Release();
  84. }
  85. if (m_pSink)
  86. {
  87. m_pSink->Release();
  88. }
  89. if (m_pEventClassDef)
  90. {
  91. m_pEventClassDef->Release();
  92. }
  93. }
  94. //////////////////////////////////////////////////////////////////////////////
  95. //
  96. // CSADiskEvent::QueryInterface
  97. //
  98. // Description:
  99. // An method implement of IUnkown interface.
  100. //
  101. // Arguments:
  102. // [in] riid Identifier of the requested interface
  103. // [out ppv Address of output variable that receives the
  104. // interface pointer requested in iid
  105. //
  106. // Returns:
  107. // NOERROR if the interface is supported
  108. // E_NOINTERFACE if not
  109. //
  110. // History:
  111. // Xing Jin (i-xingj) 06-Dec-2000
  112. //
  113. //////////////////////////////////////////////////////////////////////////////
  114. STDMETHODIMP
  115. CSADiskEvent::QueryInterface(
  116. IN REFIID riid,
  117. OUT LPVOID * ppv
  118. )
  119. {
  120. *ppv = 0;
  121. if (IID_IUnknown==riid || IID_IWbemEventProvider==riid)
  122. {
  123. *ppv = (IWbemEventProvider *) this;
  124. AddRef();
  125. return NOERROR;
  126. }
  127. if (IID_IWbemProviderInit==riid)
  128. {
  129. *ppv = (IWbemProviderInit *) this;
  130. AddRef();
  131. return NOERROR;
  132. }
  133. return E_NOINTERFACE;
  134. }
  135. //////////////////////////////////////////////////////////////////////////////
  136. //
  137. // CSADiskEvent::AddRef
  138. //
  139. // Description:
  140. // increments the reference count for an interface on an object.
  141. //
  142. // Returns:
  143. // The new reference count.
  144. //
  145. // History:
  146. // Xing Jin (i-xingj) 06-Dec-2000
  147. //
  148. //////////////////////////////////////////////////////////////////////////////
  149. ULONG
  150. CSADiskEvent::AddRef()
  151. {
  152. return ++m_cRef;
  153. }
  154. //////////////////////////////////////////////////////////////////////////////
  155. //
  156. // CSADiskEvent::Release
  157. //
  158. // Description:
  159. // decrements the reference count for an interface on an object.
  160. //
  161. // Returns:
  162. // The new reference count.
  163. //
  164. // History:
  165. // Xing Jin (i-xingj) 06-Dec-2000
  166. //
  167. //////////////////////////////////////////////////////////////////////////////
  168. ULONG
  169. CSADiskEvent::Release()
  170. {
  171. if (0 != --m_cRef)
  172. {
  173. return m_cRef;
  174. }
  175. //
  176. // If here, we are shutting down.
  177. //
  178. m_lStatus = PendingStop;
  179. return 0;
  180. }
  181. //////////////////////////////////////////////////////////////////////////////
  182. //
  183. // CSADiskEvent::ProvideEvents
  184. //
  185. // Description:
  186. // Called by Windows Management to begin delivery of our events.
  187. //
  188. // Arguments:
  189. // [in] pSinkIn Pointer to the object sink to which we
  190. // will deliver its events
  191. // lFlagsIn Reserved. It must be zero.
  192. //
  193. // Returns:
  194. // WBEM_NO_ERROR Received the sink, and it will begin delivery
  195. // of events
  196. // WBEM_E_FAILED Failed.
  197. //
  198. // History:
  199. // Xing Jin (i-xingj) 06-Dec-2000
  200. //
  201. //////////////////////////////////////////////////////////////////////////////
  202. HRESULT
  203. CSADiskEvent::ProvideEvents(
  204. IN IWbemObjectSink __RPC_FAR *pSinkIn,
  205. IN long lFlagsIn
  206. )
  207. {
  208. //
  209. // Copy the sink.
  210. //
  211. m_pSink = pSinkIn;
  212. m_pSink->AddRef();
  213. //
  214. // Open registry key of alertemail settings.
  215. //
  216. ULONG ulReturn;
  217. ulReturn = ::RegOpenKey(
  218. HKEY_LOCAL_MACHINE,
  219. SA_SADEVMONITOR_KEYPATH,
  220. &m_hQueryInterval
  221. );
  222. if( ulReturn == ERROR_SUCCESS )
  223. {
  224. DWORD dwDataSize = sizeof( DWORD );
  225. ulReturn = ::RegQueryValueEx(
  226. m_hQueryInterval,
  227. SA_SADISKMONITOR_QUERYINTERVAL,
  228. NULL,
  229. NULL,
  230. reinterpret_cast<PBYTE>(&m_dwDiskTimeInterval),
  231. &dwDataSize
  232. );
  233. if( ( ulReturn != ERROR_SUCCESS ) ||
  234. ( m_dwDiskTimeInterval < DEFAULTQUERYINTERVAL ) )
  235. {
  236. SATraceString(
  237. "CSADiskEvent::ProvideEvents QueryValue failed"
  238. );
  239. m_dwDiskTimeInterval = DEFAULTQUERYINTERVAL;
  240. }
  241. }
  242. else
  243. {
  244. SATraceString(
  245. "CSADiskEvent::ProvideEvents OpenKey failed"
  246. );
  247. m_hQueryInterval = NULL;
  248. }
  249. //
  250. // Create the event thread.
  251. //
  252. DWORD dwTID;
  253. m_hThread = CreateThread(
  254. 0,
  255. 0,
  256. CSADiskEvent::EventThread,
  257. this,
  258. 0,
  259. &dwTID
  260. );
  261. if( m_hThread == NULL )
  262. {
  263. SATraceString(
  264. "CSADiskEvent::ProvideEvents CreateThread failed"
  265. );
  266. return WBEM_E_FAILED;
  267. }
  268. //
  269. // Wait for provider to be 'ready'.
  270. //
  271. while (m_lStatus != Running)
  272. {
  273. Sleep( 1000 );
  274. }
  275. return WBEM_NO_ERROR;
  276. }
  277. //////////////////////////////////////////////////////////////////////////////
  278. //
  279. // [static]
  280. // CSADiskEvent::EventThread
  281. //
  282. // Description:
  283. // The event thread start routine.
  284. //
  285. // Arguments:
  286. // [in] pArg
  287. //
  288. // History:
  289. // Xing Jin (i-xingj) 06-Dec-2000
  290. //
  291. //////////////////////////////////////////////////////////////////////////////
  292. DWORD
  293. WINAPI CSADiskEvent::EventThread(
  294. IN LPVOID pArg
  295. )
  296. {
  297. //
  298. // Make transition to the per-instance method.
  299. //
  300. ((CSADiskEvent *)pArg)->InstanceThread();
  301. return 0;
  302. }
  303. //////////////////////////////////////////////////////////////////////////////
  304. //
  305. // CSADiskEvent::InstanceThread
  306. //
  307. // Description:
  308. // Called by EventThread to detect disk active.
  309. //
  310. // History:
  311. // Xing Jin (i-xingj) 06-Dec-2000
  312. //
  313. //////////////////////////////////////////////////////////////////////////////
  314. void
  315. CSADiskEvent::InstanceThread()
  316. {
  317. PDH_STATUS pdhStatus;
  318. PDH_FMT_COUNTERVALUE pdhFmt_CounterValue;
  319. m_lStatus = Running;
  320. while (m_lStatus == Running)
  321. {
  322. //
  323. // Polling performance data with time interval.
  324. //
  325. Sleep( m_dwDiskTimeInterval );
  326. //
  327. // Collect the query data before geting counter value.
  328. //
  329. pdhStatus = PdhCollectQueryData( m_hqryQuery );
  330. if( ERROR_SUCCESS == pdhStatus )
  331. {
  332. //
  333. // Get the counter value formatted by PDH.
  334. //
  335. pdhStatus = PdhGetFormattedCounterValue(
  336. m_hcntCounter,
  337. PDH_FMT_LONG,
  338. NULL,
  339. &pdhFmt_CounterValue
  340. );
  341. if( ERROR_SUCCESS == pdhStatus )
  342. {
  343. if( pdhFmt_CounterValue.longValue != 0 )
  344. {
  345. //
  346. // Some disk operations appear during time interval.
  347. //
  348. NotifyDiskEvent(
  349. SA_DISK_DISPLAY_TRANSMITING,
  350. SA_RESOURCEEVENT_DEFAULT_CURRENTSTATE
  351. );
  352. }
  353. else
  354. {
  355. //
  356. // No work on the disk.
  357. //
  358. NotifyDiskEvent(
  359. SA_DISK_DISPLAY_IDLE,
  360. SA_RESOURCEEVENT_DEFAULT_CURRENTSTATE
  361. );
  362. } // pdhFmt_CounterValue.longValue != 0
  363. }//if( ERROR_SUCCESS == pdhStatus )
  364. else
  365. {
  366. //
  367. // System is busy wait a moment.
  368. //
  369. Sleep( m_dwDiskTimeInterval );
  370. SATraceString(
  371. "CSADiskEvent::InstanceThread GetValue failed"
  372. );
  373. } //else
  374. }
  375. }
  376. //
  377. // When we get to here, we are no longer interested in the
  378. // provider and Release() has long since returned.
  379. m_lStatus = Stopped;
  380. delete this;
  381. }
  382. //////////////////////////////////////////////////////////////////////////////
  383. //
  384. // CSADiskEvent::NotifyDiskEvent
  385. //
  386. // Description:
  387. // Called by InstanceThread to begin delivery of our events.
  388. //
  389. // Arguments:
  390. // [in] lDisplayInformationIDIn Resource ID for the disk event.
  391. // lCurrentStateIn Reserved.
  392. //
  393. // History:
  394. // Xing Jin (i-xingj) 06-Dec-2000
  395. //
  396. //////////////////////////////////////////////////////////////////////////////
  397. VOID
  398. CSADiskEvent::NotifyDiskEvent(
  399. LONG lDisplayInformationIDIn,
  400. LONG lCurrentStateIn
  401. )
  402. {
  403. //
  404. // Generate a new event object.
  405. //
  406. IWbemClassObject *pEvt = 0;
  407. CBSTR bstrUniqueName = CBSTR(SA_RESOURCEEVENT_UNIQUENAME);
  408. CBSTR bstrDisplayInfo = CBSTR(SA_RESOURCEEVENT_DISPLAYINFORMATION);
  409. CBSTR bstrCurrentState = CBSTR(SA_RESOURCEEVENT_CURRENTSTATE);
  410. if ( ((BSTR)bstrUniqueName == NULL) ||
  411. ((BSTR)bstrDisplayInfo == NULL) ||
  412. ((BSTR)bstrCurrentState == NULL) )
  413. {
  414. SATraceString(" SADiskMonitor:CSADiskEvent::NotifyDiskEvent failed on memory allocation ");
  415. return;
  416. }
  417. HRESULT hRes = m_pEventClassDef->SpawnInstance( 0, &pEvt );
  418. if ( hRes != 0 )
  419. {
  420. SATraceString(
  421. "CSADiskEvent::NotifyDiskEvent SpawnInstance failed"
  422. );
  423. return;
  424. }
  425. CVARIANT cvUniqueName( SA_DISK_EVENT );
  426. pEvt->Put(
  427. bstrUniqueName,
  428. 0,
  429. cvUniqueName,
  430. 0
  431. );
  432. CVARIANT cvDisplayInformationID( lDisplayInformationIDIn );
  433. pEvt->Put(
  434. bstrDisplayInfo,
  435. 0,
  436. cvDisplayInformationID,
  437. 0
  438. );
  439. CVARIANT cvCount( lCurrentStateIn );
  440. pEvt->Put(
  441. bstrCurrentState,
  442. 0,
  443. cvCount,
  444. 0
  445. );
  446. //
  447. // Deliver the event to CIMOM.
  448. //
  449. hRes = m_pSink->Indicate(1, &pEvt);
  450. if ( FAILED( hRes ) )
  451. {
  452. SATraceString(
  453. "CSADiskEvent::NotifyDiskEvent Indicate failed"
  454. );
  455. }
  456. pEvt->Release();
  457. }
  458. //////////////////////////////////////////////////////////////////////////////
  459. //
  460. // CSADiskEvent::Initialize
  461. //
  462. // Description:
  463. // Inherite from IWbemProviderInit,called by Windows Management to
  464. // initialize a provider and deem it ready to receive client requests.
  465. //
  466. // Arguments:
  467. // [in] pszUserIn
  468. // lFlagsIn
  469. // pszNamespaceIn
  470. // pszLocaleIn
  471. // pNamespaceIn
  472. // pCtxIn
  473. // pInitSinkIn
  474. //
  475. // Returns:
  476. // WBEM_S_NO_ERROR
  477. // WBEM_E_FAILED
  478. //
  479. // History:
  480. // Xing Jin (i-xingj) 06-Dec-2000
  481. //
  482. //////////////////////////////////////////////////////////////////////////////
  483. HRESULT
  484. CSADiskEvent::Initialize(
  485. LPWSTR pszUserIn,
  486. LONG lFlagsIn,
  487. LPWSTR pszNamespaceIn,
  488. LPWSTR pszLocaleIn,
  489. IWbemServices __RPC_FAR * pNamespaceIn,
  490. IWbemContext __RPC_FAR * pCtxIn,
  491. IWbemProviderInitSink __RPC_FAR * pInitSinkIn
  492. )
  493. {
  494. // We don't care about most of the incoming parameters in this
  495. // simple sample. However, we will save the namespace pointer
  496. // and get our event class definition.
  497. m_pNs = pNamespaceIn;
  498. m_pNs->AddRef();
  499. //
  500. // Grab the class definition for the event.
  501. //
  502. IWbemClassObject *pObj = 0;
  503. CBSTR bstrClassName = CBSTR(SA_RESOURCEEVENT_CLASSNAME);
  504. if ( (BSTR)bstrClassName == NULL )
  505. {
  506. SATraceString(" SADiskMonitor:CSADiskEvent::Initialize failed on memory allocation ");
  507. return E_OUTOFMEMORY;
  508. }
  509. HRESULT hRes = m_pNs->GetObject(
  510. bstrClassName,
  511. 0,
  512. pCtxIn,
  513. &pObj,
  514. 0
  515. );
  516. if ( hRes != 0 )
  517. {
  518. SATraceString(
  519. "CSADiskEvent::Initialize GetObject failed"
  520. );
  521. return WBEM_E_FAILED;
  522. }
  523. m_pEventClassDef = pObj;
  524. //
  525. // Tell CIMOM that we're up and running.
  526. //
  527. if( InitDiskQueryContext() )
  528. {
  529. pInitSinkIn->SetStatus(WBEM_S_INITIALIZED,0);
  530. return WBEM_NO_ERROR;
  531. }
  532. SATraceString(
  533. "CSADiskEvent::Initialize InitDiskQueryContext failed"
  534. );
  535. pInitSinkIn->SetStatus(WBEM_E_FAILED ,0);
  536. return WBEM_E_FAILED;
  537. }
  538. //////////////////////////////////////////////////////////////////////////////
  539. //
  540. // CSADiskEvent::InitDiskQueryContext
  541. //
  542. // Description:
  543. // Called by Initialize to initial physicaldisk counter.
  544. //
  545. // Arguments:
  546. //
  547. // Returns:
  548. // TRUE Succeed in retrieving disk counter.
  549. // FALSE Failed
  550. //
  551. // History:
  552. // Xing Jin (i-xingj) 06-Dec-2000
  553. //
  554. //////////////////////////////////////////////////////////////////////////////
  555. BOOL
  556. CSADiskEvent::InitDiskQueryContext()
  557. {
  558. PDH_STATUS pdhStatus;
  559. //
  560. // Open a query handle of PDH.
  561. //
  562. pdhStatus = PdhOpenQuery( NULL, 0, &m_hqryQuery );
  563. if( ERROR_SUCCESS == pdhStatus )
  564. {
  565. //
  566. // Add the specified counter we want to our query handle.
  567. //
  568. pdhStatus = PdhAddCounter( m_hqryQuery,
  569. SA_DISKEVENTPROVIDER_DISKCOUNTER_NAME,
  570. 0,
  571. &m_hcntCounter );
  572. }
  573. return ( ERROR_SUCCESS == pdhStatus );
  574. }