////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2000 Microsoft Corporation // // Module Name: // SADiskEvent.cpp // // Description: // description-for-module // // [Header File:] // SADiskEvent.h // // History: // Xing Jin (i-xingj) 06-Dec-2000 // ////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include "SADiskEvent.h" #include #include const WCHAR SA_DISKEVENTPROVIDER_DISKCOUNTER_NAME[] = L"\\PhysicalDisk(_Total#0)\\Disk Transfers/sec"; const WCHAR SA_SADEVMONITOR_KEYPATH [] = L"SOFTWARE\\Microsoft\\ServerAppliance\\DeviceMonitor"; const WCHAR SA_SADISKMONITOR_QUERYINTERVAL[] = L"DiskQueryInterval"; //static DWORD g_dwDiskTimeInterval = 1000; const DWORD DEFAULTQUERYINTERVAL = 1000; ////////////////////////////////////////////////////////////////////////////// // // CSADiskEvent::CSADiskEvent // // Description: // Class constructor. // // History: // Xing Jin (i-xingj) 06-Dec-2000 // ////////////////////////////////////////////////////////////////////////////// CSADiskEvent::CSADiskEvent() { m_cRef = 0; m_lStatus = Pending; m_dwDiskTimeInterval = 1000; m_hThread = NULL; m_pNs = NULL; m_pSink = NULL; m_pEventClassDef = NULL; m_hqryQuery = NULL; m_hcntCounter = NULL; m_hQueryInterval = NULL; } ////////////////////////////////////////////////////////////////////////////// // // CSADiskEvent::~CSADiskEvent // // Description: // Class deconstructor. // // History: // Xing Jin (i-xingj) 06-Dec-2000 // ////////////////////////////////////////////////////////////////////////////// CSADiskEvent::~CSADiskEvent() { if( m_hqryQuery ) { PdhCloseQuery( m_hqryQuery ); } if (m_hThread) { CloseHandle(m_hThread); } if( m_hQueryInterval != NULL ) { ::RegCloseKey( m_hQueryInterval ); } if (m_pNs) { m_pNs->Release(); } if (m_pSink) { m_pSink->Release(); } if (m_pEventClassDef) { m_pEventClassDef->Release(); } } ////////////////////////////////////////////////////////////////////////////// // // CSADiskEvent::QueryInterface // // Description: // An method implement of IUnkown interface. // // Arguments: // [in] riid Identifier of the requested interface // [out ppv Address of output variable that receives the // interface pointer requested in iid // // Returns: // NOERROR if the interface is supported // E_NOINTERFACE if not // // History: // Xing Jin (i-xingj) 06-Dec-2000 // ////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CSADiskEvent::QueryInterface( IN REFIID riid, OUT LPVOID * ppv ) { *ppv = 0; if (IID_IUnknown==riid || IID_IWbemEventProvider==riid) { *ppv = (IWbemEventProvider *) this; AddRef(); return NOERROR; } if (IID_IWbemProviderInit==riid) { *ppv = (IWbemProviderInit *) this; AddRef(); return NOERROR; } return E_NOINTERFACE; } ////////////////////////////////////////////////////////////////////////////// // // CSADiskEvent::AddRef // // Description: // increments the reference count for an interface on an object. // // Returns: // The new reference count. // // History: // Xing Jin (i-xingj) 06-Dec-2000 // ////////////////////////////////////////////////////////////////////////////// ULONG CSADiskEvent::AddRef() { return ++m_cRef; } ////////////////////////////////////////////////////////////////////////////// // // CSADiskEvent::Release // // Description: // decrements the reference count for an interface on an object. // // Returns: // The new reference count. // // History: // Xing Jin (i-xingj) 06-Dec-2000 // ////////////////////////////////////////////////////////////////////////////// ULONG CSADiskEvent::Release() { if (0 != --m_cRef) { return m_cRef; } // // If here, we are shutting down. // m_lStatus = PendingStop; return 0; } ////////////////////////////////////////////////////////////////////////////// // // CSADiskEvent::ProvideEvents // // Description: // Called by Windows Management to begin delivery of our events. // // Arguments: // [in] pSinkIn Pointer to the object sink to which we // will deliver its events // lFlagsIn Reserved. It must be zero. // // Returns: // WBEM_NO_ERROR Received the sink, and it will begin delivery // of events // WBEM_E_FAILED Failed. // // History: // Xing Jin (i-xingj) 06-Dec-2000 // ////////////////////////////////////////////////////////////////////////////// HRESULT CSADiskEvent::ProvideEvents( IN IWbemObjectSink __RPC_FAR *pSinkIn, IN long lFlagsIn ) { // // Copy the sink. // m_pSink = pSinkIn; m_pSink->AddRef(); // // Open registry key of alertemail settings. // ULONG ulReturn; ulReturn = ::RegOpenKey( HKEY_LOCAL_MACHINE, SA_SADEVMONITOR_KEYPATH, &m_hQueryInterval ); if( ulReturn == ERROR_SUCCESS ) { DWORD dwDataSize = sizeof( DWORD ); ulReturn = ::RegQueryValueEx( m_hQueryInterval, SA_SADISKMONITOR_QUERYINTERVAL, NULL, NULL, reinterpret_cast(&m_dwDiskTimeInterval), &dwDataSize ); if( ( ulReturn != ERROR_SUCCESS ) || ( m_dwDiskTimeInterval < DEFAULTQUERYINTERVAL ) ) { SATraceString( "CSADiskEvent::ProvideEvents QueryValue failed" ); m_dwDiskTimeInterval = DEFAULTQUERYINTERVAL; } } else { SATraceString( "CSADiskEvent::ProvideEvents OpenKey failed" ); m_hQueryInterval = NULL; } // // Create the event thread. // DWORD dwTID; m_hThread = CreateThread( 0, 0, CSADiskEvent::EventThread, this, 0, &dwTID ); if( m_hThread == NULL ) { SATraceString( "CSADiskEvent::ProvideEvents CreateThread failed" ); return WBEM_E_FAILED; } // // Wait for provider to be 'ready'. // while (m_lStatus != Running) { Sleep( 1000 ); } return WBEM_NO_ERROR; } ////////////////////////////////////////////////////////////////////////////// // // [static] // CSADiskEvent::EventThread // // Description: // The event thread start routine. // // Arguments: // [in] pArg // // History: // Xing Jin (i-xingj) 06-Dec-2000 // ////////////////////////////////////////////////////////////////////////////// DWORD WINAPI CSADiskEvent::EventThread( IN LPVOID pArg ) { // // Make transition to the per-instance method. // ((CSADiskEvent *)pArg)->InstanceThread(); return 0; } ////////////////////////////////////////////////////////////////////////////// // // CSADiskEvent::InstanceThread // // Description: // Called by EventThread to detect disk active. // // History: // Xing Jin (i-xingj) 06-Dec-2000 // ////////////////////////////////////////////////////////////////////////////// void CSADiskEvent::InstanceThread() { PDH_STATUS pdhStatus; PDH_FMT_COUNTERVALUE pdhFmt_CounterValue; m_lStatus = Running; while (m_lStatus == Running) { // // Polling performance data with time interval. // Sleep( m_dwDiskTimeInterval ); // // Collect the query data before geting counter value. // pdhStatus = PdhCollectQueryData( m_hqryQuery ); if( ERROR_SUCCESS == pdhStatus ) { // // Get the counter value formatted by PDH. // pdhStatus = PdhGetFormattedCounterValue( m_hcntCounter, PDH_FMT_LONG, NULL, &pdhFmt_CounterValue ); if( ERROR_SUCCESS == pdhStatus ) { if( pdhFmt_CounterValue.longValue != 0 ) { // // Some disk operations appear during time interval. // NotifyDiskEvent( SA_DISK_DISPLAY_TRANSMITING, SA_RESOURCEEVENT_DEFAULT_CURRENTSTATE ); } else { // // No work on the disk. // NotifyDiskEvent( SA_DISK_DISPLAY_IDLE, SA_RESOURCEEVENT_DEFAULT_CURRENTSTATE ); } // pdhFmt_CounterValue.longValue != 0 }//if( ERROR_SUCCESS == pdhStatus ) else { // // System is busy wait a moment. // Sleep( m_dwDiskTimeInterval ); SATraceString( "CSADiskEvent::InstanceThread GetValue failed" ); } //else } } // // When we get to here, we are no longer interested in the // provider and Release() has long since returned. m_lStatus = Stopped; delete this; } ////////////////////////////////////////////////////////////////////////////// // // CSADiskEvent::NotifyDiskEvent // // Description: // Called by InstanceThread to begin delivery of our events. // // Arguments: // [in] lDisplayInformationIDIn Resource ID for the disk event. // lCurrentStateIn Reserved. // // History: // Xing Jin (i-xingj) 06-Dec-2000 // ////////////////////////////////////////////////////////////////////////////// VOID CSADiskEvent::NotifyDiskEvent( LONG lDisplayInformationIDIn, LONG lCurrentStateIn ) { // // Generate a new event object. // IWbemClassObject *pEvt = 0; CBSTR bstrUniqueName = CBSTR(SA_RESOURCEEVENT_UNIQUENAME); CBSTR bstrDisplayInfo = CBSTR(SA_RESOURCEEVENT_DISPLAYINFORMATION); CBSTR bstrCurrentState = CBSTR(SA_RESOURCEEVENT_CURRENTSTATE); if ( ((BSTR)bstrUniqueName == NULL) || ((BSTR)bstrDisplayInfo == NULL) || ((BSTR)bstrCurrentState == NULL) ) { SATraceString(" SADiskMonitor:CSADiskEvent::NotifyDiskEvent failed on memory allocation "); return; } HRESULT hRes = m_pEventClassDef->SpawnInstance( 0, &pEvt ); if ( hRes != 0 ) { SATraceString( "CSADiskEvent::NotifyDiskEvent SpawnInstance failed" ); return; } CVARIANT cvUniqueName( SA_DISK_EVENT ); pEvt->Put( bstrUniqueName, 0, cvUniqueName, 0 ); CVARIANT cvDisplayInformationID( lDisplayInformationIDIn ); pEvt->Put( bstrDisplayInfo, 0, cvDisplayInformationID, 0 ); CVARIANT cvCount( lCurrentStateIn ); pEvt->Put( bstrCurrentState, 0, cvCount, 0 ); // // Deliver the event to CIMOM. // hRes = m_pSink->Indicate(1, &pEvt); if ( FAILED( hRes ) ) { SATraceString( "CSADiskEvent::NotifyDiskEvent Indicate failed" ); } pEvt->Release(); } ////////////////////////////////////////////////////////////////////////////// // // CSADiskEvent::Initialize // // Description: // Inherite from IWbemProviderInit,called by Windows Management to // initialize a provider and deem it ready to receive client requests. // // Arguments: // [in] pszUserIn // lFlagsIn // pszNamespaceIn // pszLocaleIn // pNamespaceIn // pCtxIn // pInitSinkIn // // Returns: // WBEM_S_NO_ERROR // WBEM_E_FAILED // // History: // Xing Jin (i-xingj) 06-Dec-2000 // ////////////////////////////////////////////////////////////////////////////// HRESULT CSADiskEvent::Initialize( LPWSTR pszUserIn, LONG lFlagsIn, LPWSTR pszNamespaceIn, LPWSTR pszLocaleIn, IWbemServices __RPC_FAR * pNamespaceIn, IWbemContext __RPC_FAR * pCtxIn, IWbemProviderInitSink __RPC_FAR * pInitSinkIn ) { // We don't care about most of the incoming parameters in this // simple sample. However, we will save the namespace pointer // and get our event class definition. m_pNs = pNamespaceIn; m_pNs->AddRef(); // // Grab the class definition for the event. // IWbemClassObject *pObj = 0; CBSTR bstrClassName = CBSTR(SA_RESOURCEEVENT_CLASSNAME); if ( (BSTR)bstrClassName == NULL ) { SATraceString(" SADiskMonitor:CSADiskEvent::Initialize failed on memory allocation "); return E_OUTOFMEMORY; } HRESULT hRes = m_pNs->GetObject( bstrClassName, 0, pCtxIn, &pObj, 0 ); if ( hRes != 0 ) { SATraceString( "CSADiskEvent::Initialize GetObject failed" ); return WBEM_E_FAILED; } m_pEventClassDef = pObj; // // Tell CIMOM that we're up and running. // if( InitDiskQueryContext() ) { pInitSinkIn->SetStatus(WBEM_S_INITIALIZED,0); return WBEM_NO_ERROR; } SATraceString( "CSADiskEvent::Initialize InitDiskQueryContext failed" ); pInitSinkIn->SetStatus(WBEM_E_FAILED ,0); return WBEM_E_FAILED; } ////////////////////////////////////////////////////////////////////////////// // // CSADiskEvent::InitDiskQueryContext // // Description: // Called by Initialize to initial physicaldisk counter. // // Arguments: // // Returns: // TRUE Succeed in retrieving disk counter. // FALSE Failed // // History: // Xing Jin (i-xingj) 06-Dec-2000 // ////////////////////////////////////////////////////////////////////////////// BOOL CSADiskEvent::InitDiskQueryContext() { PDH_STATUS pdhStatus; // // Open a query handle of PDH. // pdhStatus = PdhOpenQuery( NULL, 0, &m_hqryQuery ); if( ERROR_SUCCESS == pdhStatus ) { // // Add the specified counter we want to our query handle. // pdhStatus = PdhAddCounter( m_hqryQuery, SA_DISKEVENTPROVIDER_DISKCOUNTER_NAME, 0, &m_hcntCounter ); } return ( ERROR_SUCCESS == pdhStatus ); }